mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
819 lines
22 KiB
819 lines
22 KiB
#include "ctlspriv.h"
|
|
|
|
#define CURSORSLOP 3
|
|
|
|
static WCHAR szHeaderClassW[] = HEADERCLASSNAMEW;
|
|
static CCHAR szHeaderClassA[] = HEADERCLASSNAMEA;
|
|
|
|
static HCURSOR hSplit;
|
|
|
|
|
|
/* I only need one of these since you can only have capture on one window
|
|
* at a time
|
|
*/
|
|
static struct
|
|
{
|
|
HWND hWnd;
|
|
HWND hOldWnd;
|
|
HWND hwndParent;
|
|
|
|
UINT ID;
|
|
|
|
int nPart;
|
|
int nLastVisible;
|
|
int *pSaveParts;
|
|
RECT rc;
|
|
|
|
} state = { NULL, NULL, NULL, 0, -1, 0, NULL, { 0, 0, 0, 0 } } ;
|
|
|
|
Static void NEAR PASCAL BeginAdjust(HWND hWnd, PSTATUSINFO pStatusInfo, int nPart, POINT pt);
|
|
|
|
/* Return the partition index if the position is close enough; -1 otherwise
|
|
*/
|
|
Static int NEAR PASCAL
|
|
GetPart(PSTATUSINFO pStatusInfo, PSTRINGINFO pStringInfo, POINT pt)
|
|
{
|
|
int nParts;
|
|
|
|
for (nParts = 0; nParts < pStatusInfo->nParts - 1; ++nParts, ++pStringInfo)
|
|
{
|
|
if (pStringInfo->right - pt.x < CURSORSLOP && pStringInfo->right - pt.x > (1 - CURSORSLOP))
|
|
break;
|
|
if (nParts >= pStatusInfo->nParts - 2)
|
|
{
|
|
nParts = -1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(nParts);
|
|
}
|
|
|
|
|
|
Static int NEAR PASCAL GetPrevVisible(PSTATUSINFO pStatusInfo, int nPart)
|
|
{
|
|
for (--nPart; nPart >= 0; --nPart)
|
|
if (pStatusInfo->sInfo[nPart].right > 0)
|
|
break;
|
|
|
|
return(nPart);
|
|
}
|
|
|
|
|
|
Static int NEAR PASCAL GetNextVisible(PSTATUSINFO pStatusInfo, int nPart)
|
|
{
|
|
for (++nPart; nPart < pStatusInfo->nParts; ++nPart)
|
|
if (pStatusInfo->sInfo[nPart].right > 0)
|
|
return(nPart);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
/* Note that the handle returned here should NOT be freed by the caller
|
|
*/
|
|
Static HLOCAL NEAR PASCAL GetHeaderParts(HWND hWnd, PSTATUSINFO pStatusInfo, BOOL bAdjustLast)
|
|
{
|
|
static HLOCAL hSaveParts = NULL;
|
|
static int nSaveParts = 0;
|
|
|
|
HLOCAL hTemp;
|
|
PSTRINGINFO pSaveParts, pStringInfo, pNewInfo;
|
|
int nParts, nSprings, nTotal, nTemp, nLast, nLastVisible;
|
|
RECT rcClient;
|
|
|
|
/* Allocate a single moveable buffer that is large enough to hold the
|
|
* largest array of parts.
|
|
*/
|
|
nParts = pStatusInfo->nParts;
|
|
if (nParts > nSaveParts)
|
|
{
|
|
if (hSaveParts)
|
|
{
|
|
hTemp = LocalReAlloc(hSaveParts, nParts * sizeof(STRINGINFO), LMEM_MOVEABLE);
|
|
if (!hTemp)
|
|
return(NULL);
|
|
}
|
|
else
|
|
{
|
|
hTemp = LocalAlloc(LMEM_FIXED, nParts * sizeof(STRINGINFO));
|
|
if (!hTemp)
|
|
return(NULL);
|
|
}
|
|
hSaveParts = hTemp;
|
|
nSaveParts = nParts;
|
|
}
|
|
pSaveParts = (PSTRINGINFO) hSaveParts;
|
|
|
|
/* Go through the list, counting the number of "springs" and the
|
|
* minimum width.
|
|
*/
|
|
for (nTotal = 0, nSprings = 0, pNewInfo = pSaveParts, pStringInfo = pStatusInfo->sInfo;
|
|
nParts > 0; --nParts, ++pNewInfo, ++pStringInfo)
|
|
{
|
|
pNewInfo->pString = pStringInfo->pString;
|
|
pNewInfo->uType = pStringInfo->uType | SBT_NOBORDERS;
|
|
nTemp = pStringInfo->right;
|
|
if (nTemp < 0)
|
|
{
|
|
nTemp = 0;
|
|
pNewInfo->uType &= ~HBT_SPRING;
|
|
}
|
|
|
|
if (pNewInfo->uType & HBT_SPRING)
|
|
++nSprings;
|
|
|
|
nTotal += nTemp;
|
|
pNewInfo->right = nTemp;
|
|
}
|
|
|
|
/* Determine the amount left to distribute to the springs, and then
|
|
* distribute this amount evenly.
|
|
*/
|
|
GetClientRect(hWnd, &rcClient);
|
|
nTotal = rcClient.right - nTotal;
|
|
if (nTotal < 0)
|
|
nTotal = 0;
|
|
|
|
for (nParts = 0, nLast = 0, nLastVisible = -1, pNewInfo = pSaveParts,
|
|
pStringInfo = pStatusInfo->sInfo; nParts < pStatusInfo->nParts;
|
|
++nParts, ++pNewInfo, ++pStringInfo)
|
|
{
|
|
if ((pNewInfo->uType&HBT_SPRING) && nSprings)
|
|
{
|
|
nTemp = nTotal / nSprings;
|
|
--nSprings;
|
|
nTotal -= nTemp;
|
|
pNewInfo->right += nTemp;
|
|
}
|
|
|
|
/* Save the rightmost visible guy.
|
|
*/
|
|
if (pNewInfo->right)
|
|
nLastVisible = nParts;
|
|
|
|
/* Transform the width to an absolute position.
|
|
*/
|
|
pNewInfo->right += nLast;
|
|
nLast = pNewInfo->right;
|
|
}
|
|
|
|
if (bAdjustLast && nLastVisible>=0)
|
|
{
|
|
for (pNewInfo = pSaveParts + nLastVisible; nLastVisible < pStatusInfo->nParts;
|
|
++nLastVisible, ++pNewInfo)
|
|
pNewInfo->right = rcClient.right;
|
|
}
|
|
|
|
return(hSaveParts);
|
|
}
|
|
|
|
|
|
Static void NEAR PASCAL AdjustBorders(HWND hWnd, PSTATUSINFO pStatusInfo)
|
|
{
|
|
POINT pt, ptTemp, ptSave;
|
|
int nPart;
|
|
int accel = 0;
|
|
HWND hwndParent;
|
|
|
|
UINT uiID;
|
|
|
|
MSG msg;
|
|
RECT rc;
|
|
int nStart;
|
|
int nDirection;
|
|
HLOCAL hSaveParts;
|
|
PSTRINGINFO pSaveParts;
|
|
|
|
GetCursorPos(&ptSave);
|
|
GetClientRect(hWnd, &rc);
|
|
|
|
hwndParent = GetParent(hWnd);
|
|
|
|
uiID = GetWindowLong(hWnd, GWL_ID);
|
|
ShowCursor(TRUE);
|
|
|
|
pt.x = 0;
|
|
pt.y = (pStatusInfo->nFontHeight+1) / 2;
|
|
ClientToScreen(hWnd, &pt);
|
|
|
|
nDirection = 1;
|
|
nPart = pStatusInfo->nParts - 2;
|
|
goto MoveTheCursor;
|
|
|
|
for ( ; ; )
|
|
{
|
|
while (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE|PM_NOYIELD))
|
|
;
|
|
|
|
switch (msg.message)
|
|
{
|
|
case WM_KEYDOWN:
|
|
switch (msg.wParam)
|
|
{
|
|
case VK_TAB:
|
|
DoTab:
|
|
/* If the sift key is down, go backwards
|
|
*/
|
|
if (GetKeyState(VK_SHIFT) & 0x8000)
|
|
nDirection = -1;
|
|
else
|
|
nDirection = 1;
|
|
MoveTheCursor:
|
|
/* Make sure the previous adjust is cleaned up,
|
|
* then tell the app we are starting.
|
|
*/
|
|
if (state.nPart >= 0)
|
|
SendMessage(hWnd, WM_LBUTTONUP, 0, 0L);
|
|
|
|
SendMessage (hwndParent, WM_COMMAND,
|
|
GET_WM_COMMAND_MPS(uiID,0, HBN_BEGINADJUST));
|
|
|
|
hSaveParts = GetHeaderParts(hWnd, pStatusInfo, FALSE);
|
|
if (!hSaveParts)
|
|
goto EndAdjust;
|
|
|
|
pSaveParts = (PSTRINGINFO) hSaveParts;
|
|
|
|
/* Don't try to adjust anything that is not
|
|
* currently on the screen or has no visible
|
|
* cols to its right.
|
|
*/
|
|
nStart = nPart;
|
|
do {
|
|
nPart += nDirection;
|
|
if (nPart >= pStatusInfo->nParts - 1)
|
|
nPart = 0;
|
|
if (nPart < 0)
|
|
nPart = pStatusInfo->nParts-2;
|
|
if (nPart == nStart)
|
|
goto EndAdjust;
|
|
} while ((UINT)pSaveParts[nPart].right >= (UINT)rc.right
|
|
|| pStatusInfo->sInfo[nPart].right < 0
|
|
|| GetNextVisible(pStatusInfo, nPart) < 0);
|
|
|
|
/* Immediately go into adjusting mode; send BEGINADJUST right
|
|
* afterwards to get the right MenuHelp
|
|
*/
|
|
BeginAdjust(hWnd, pStatusInfo, nPart, pt);
|
|
|
|
SendMessage (hwndParent, WM_COMMAND,
|
|
GET_WM_COMMAND_MPS(uiID,state.nPart, HBN_BEGINADJUST));
|
|
break;
|
|
|
|
case VK_LEFT:
|
|
case VK_RIGHT:
|
|
case VK_UP:
|
|
case VK_DOWN:
|
|
GetCursorPos(&ptTemp);
|
|
|
|
++accel;
|
|
if (msg.wParam == VK_LEFT || msg.wParam == VK_UP)
|
|
ptTemp.x -= accel;
|
|
else
|
|
ptTemp.x += accel;
|
|
SetCursorPos(ptTemp.x, ptTemp.y);
|
|
break;
|
|
|
|
case VK_RETURN:
|
|
DoReturn:
|
|
SendMessage(hWnd, WM_LBUTTONUP, 0, 0L);
|
|
goto EndAdjust;
|
|
|
|
case VK_ESCAPE:
|
|
SendMessage(hWnd, WM_CHAR, VK_ESCAPE, 0L);
|
|
goto EndAdjust;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_KEYUP:
|
|
accel = 0;
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
goto DoReturn;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
goto DoTab;
|
|
|
|
default:
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
EndAdjust:
|
|
ShowCursor(FALSE);
|
|
SetCursorPos(ptSave.x, ptSave.y);
|
|
|
|
SendMessage (hwndParent, WM_COMMAND,
|
|
GET_WM_COMMAND_MPS(uiID, 0, HBN_ENDADJUST));
|
|
}
|
|
|
|
|
|
Static void NEAR PASCAL PaintHeaderWnd(HWND hWnd, PSTATUSINFO pStatusInfo)
|
|
{
|
|
HLOCAL hSaveParts;
|
|
PSTRINGINFO pStringInfo, pSaveParts;
|
|
int nParts, nBorderY; // andrewbe
|
|
int nBorderWidth, nBorderHeight; // andrewbe
|
|
HDC hDC;
|
|
HBRUSH hBrush, hOldBrush;
|
|
RECT rcClient;
|
|
|
|
hSaveParts = GetHeaderParts(hWnd, pStatusInfo, TRUE);
|
|
if (!hSaveParts)
|
|
return;
|
|
|
|
pSaveParts = (PSTRINGINFO) hSaveParts;
|
|
|
|
/* Let the status bar code draw the text
|
|
*/
|
|
PaintStatusWnd (hWnd, pStatusInfo, pSaveParts, pStatusInfo->nParts,
|
|
pStatusInfo->nBorderX, TRUE);
|
|
|
|
/* Now draw the lines between panes
|
|
*/
|
|
hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME));
|
|
if (hBrush)
|
|
{
|
|
hDC = GetDC(hWnd);
|
|
|
|
hOldBrush = SelectObject(hDC, hBrush);
|
|
if (hOldBrush)
|
|
{
|
|
GetClientRect(hWnd, &rcClient);
|
|
|
|
nBorderWidth = pStatusInfo->nBorderPart; // andrewbe
|
|
|
|
nBorderY = 0; //
|
|
nBorderHeight = rcClient.bottom; // To stop the
|
|
// blasted
|
|
if (!(GetWindowLong(hWnd, GWL_STYLE)&CCS_NOHILITE)) { // flickering
|
|
nBorderY++; // (andrewbe)
|
|
nBorderHeight--; //
|
|
} //
|
|
|
|
for (nParts = pStatusInfo->nParts - 1, pStringInfo = pSaveParts;
|
|
nParts > 0; --nParts, ++pStringInfo)
|
|
{
|
|
PatBlt (hDC, pStringInfo->right, nBorderY, nBorderWidth, nBorderHeight,
|
|
PATCOPY);
|
|
}
|
|
|
|
SelectObject(hDC, hOldBrush);
|
|
}
|
|
|
|
ReleaseDC(hWnd, hDC);
|
|
DeleteObject(hBrush);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
Static void NEAR PASCAL BeginAdjust(HWND hWnd, PSTATUSINFO pStatusInfo, int nPart, POINT pt)
|
|
{
|
|
HLOCAL hSaveParts;
|
|
PSTRINGINFO pSaveParts;
|
|
RECT rc;
|
|
int nParts;
|
|
|
|
/* Just make sure we are cleaned up from the last SetCapture
|
|
*/
|
|
if (state.nPart >= 0)
|
|
SendMessage(state.hWnd, WM_LBUTTONUP, 0, 0L);
|
|
|
|
hSaveParts = GetHeaderParts(hWnd, pStatusInfo, FALSE);
|
|
if (!hSaveParts)
|
|
return;
|
|
|
|
if (nPart >= 0)
|
|
state.nPart = nPart;
|
|
else
|
|
{
|
|
state.nPart = GetPart(pStatusInfo, hSaveParts, pt);
|
|
if (state.nPart < 0)
|
|
return;
|
|
}
|
|
|
|
/* Save the current state in case the user aborts
|
|
*/
|
|
state.pSaveParts = (int *)LocalAlloc(LMEM_FIXED,
|
|
pStatusInfo->nParts * sizeof(int));
|
|
if (!state.pSaveParts)
|
|
{
|
|
state.nPart = -1;
|
|
return;
|
|
}
|
|
for (nParts = pStatusInfo->nParts - 1; nParts >= 0; --nParts)
|
|
state.pSaveParts[nParts] = pStatusInfo->sInfo[nParts].right;
|
|
|
|
/* Set all min widths to their current widths. Special case nParts=0.
|
|
*/
|
|
pSaveParts = (PSTRINGINFO)hSaveParts;
|
|
for (nParts = pStatusInfo->nParts - 1, state.nLastVisible =- 1; nParts > 0; --nParts)
|
|
{
|
|
if (state.pSaveParts[nParts] > 0)
|
|
{
|
|
pStatusInfo->sInfo[nParts].right = pSaveParts[nParts].right
|
|
- pSaveParts[nParts-1].right;
|
|
if (state.nLastVisible < 0)
|
|
state.nLastVisible = nParts;
|
|
}
|
|
}
|
|
|
|
/* Set the last visible one very wide so there is never any spring.
|
|
*/
|
|
if (state.nLastVisible >= 0)
|
|
pStatusInfo->sInfo[state.nLastVisible].right = 0x3fff;
|
|
|
|
if (nParts == 0 && state.pSaveParts[0]> 0 )
|
|
pStatusInfo->sInfo[0].right = pSaveParts[0].right;
|
|
|
|
state.hWnd = hWnd;
|
|
pt.x = pSaveParts[state.nPart].right;
|
|
ClientToScreen(hWnd, &pt);
|
|
SetCursorPos(pt.x, pt.y);
|
|
SetCapture(hWnd);
|
|
state.hOldWnd = SetFocus(hWnd);
|
|
|
|
GetClientRect(hWnd, &state.rc);
|
|
|
|
if (state.nPart > 0)
|
|
state.rc.left = pSaveParts[state.nPart-1].right;
|
|
|
|
/* Clip the cursor to the appropriate area.
|
|
*/
|
|
rc = state.rc;
|
|
++rc.left;
|
|
/* Some code below assumes that state.rc.right is the width of the
|
|
* window.
|
|
*/
|
|
rc.right -= rc.left;
|
|
ClientToScreen(hWnd, (LPPOINT)&rc);
|
|
rc.right += rc.left;
|
|
rc.top = 0;
|
|
rc.bottom = GetSystemMetrics(SM_CYSCREEN);
|
|
ClipCursor(&rc);
|
|
|
|
SendMessage (hWnd, WM_SETCURSOR, (WPARAM)hWnd,
|
|
MAKELONG(HTCLIENT, WM_LBUTTONDOWN));
|
|
|
|
state.ID = GetWindowLong(hWnd, GWL_ID);
|
|
|
|
state.hwndParent = GetParent(hWnd);
|
|
|
|
SendMessage (state.hwndParent, WM_COMMAND,
|
|
GET_WM_COMMAND_MPS(state.ID,state.nPart, HBN_BEGINDRAG));
|
|
|
|
}
|
|
|
|
|
|
Static void NEAR PASCAL TermAdjust(void)
|
|
{
|
|
if (state.nPart < 0)
|
|
return;
|
|
|
|
state.nPart = -1;
|
|
LocalFree((HLOCAL)state.pSaveParts);
|
|
|
|
ReleaseCapture();
|
|
if (state.hOldWnd)
|
|
SetFocus(state.hOldWnd);
|
|
ClipCursor(NULL);
|
|
|
|
/* Send a dragging message just in case
|
|
*/
|
|
SendMessage(state.hwndParent, WM_COMMAND,
|
|
GET_WM_COMMAND_MPS(state.ID,state.nPart, HBN_DRAGGING));
|
|
|
|
SendMessage(state.hwndParent, WM_COMMAND,
|
|
GET_WM_COMMAND_MPS(state.ID,state.nPart, HBN_ENDDRAG));
|
|
}
|
|
|
|
|
|
Static void NEAR PASCAL AbortAdjust(PSTATUSINFO pStatusInfo)
|
|
{
|
|
int nPart;
|
|
|
|
if (state.nPart < 0)
|
|
return;
|
|
|
|
for (nPart = pStatusInfo->nParts - 1; nPart >= 0; --nPart)
|
|
pStatusInfo->sInfo[nPart].right = state.pSaveParts[nPart];
|
|
|
|
InvalidateRect(state.hWnd, NULL, TRUE);
|
|
|
|
TermAdjust();
|
|
}
|
|
|
|
|
|
/* Since a header bar and a status bar are so similar, I am just going to
|
|
* code the differences here, and call StatusWndProc for any messages I
|
|
* don't want to handle
|
|
*/
|
|
LRESULT CALLBACK HeaderWndProc(HWND hWnd, UINT uMessage, WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PSTATUSINFO pStatusInfo;
|
|
|
|
pStatusInfo = (PSTATUSINFO)GetWindowLong(hWnd, GWL_PSTATUSINFO);
|
|
if (!pStatusInfo)
|
|
{
|
|
if (uMessage == WM_CREATE)
|
|
{
|
|
#define lpcs ((LPCREATESTRUCT)lParam)
|
|
|
|
if (!(lpcs->style&(CCS_TOP|CCS_NOMOVEY|CCS_BOTTOM)))
|
|
{
|
|
lpcs->style |= CCS_NOMOVEY;
|
|
SetWindowLong(hWnd, GWL_STYLE, lpcs->style);
|
|
}
|
|
}
|
|
|
|
goto DoDefault;
|
|
}
|
|
|
|
switch (uMessage)
|
|
{
|
|
/* We just use the system font for DBCS systems
|
|
*/
|
|
#ifndef DBCS
|
|
case WM_SETFONT:
|
|
if (wParam == 0)
|
|
{
|
|
HDC hDC;
|
|
|
|
hDC = GetDC(hWnd);
|
|
wParam = (WPARAM)
|
|
|
|
|
|
#if 0
|
|
//
|
|
// Use unicode font
|
|
//
|
|
CreateFont(-8 * GetDeviceCaps(hDC, LOGPIXELSY) / 72,
|
|
0, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
|
VARIABLE_PITCH | FF_SWISS, UNICODE_FONT_NAME);
|
|
#endif
|
|
CreateFont(-8 * GetDeviceCaps(hDC, LOGPIXELSY) / 72,
|
|
0, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
|
VARIABLE_PITCH | FF_SWISS, szSansSerif);
|
|
|
|
ReleaseDC(hWnd, hDC);
|
|
|
|
if (!wParam)
|
|
break;
|
|
|
|
StatusWndProc(hWnd, uMessage, wParam, lParam);
|
|
pStatusInfo->bDefFont = TRUE;
|
|
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case WM_PAINT:
|
|
PaintHeaderWnd(hWnd, pStatusInfo);
|
|
return(TRUE);
|
|
|
|
case SB_SETBORDERS:
|
|
{
|
|
int nBorder;
|
|
LPINT lpInt;
|
|
|
|
lpInt = (LPINT)lParam;
|
|
|
|
nBorder = *lpInt++;
|
|
pStatusInfo->nBorderX = nBorder<0 ? 0 : nBorder;
|
|
|
|
nBorder = *lpInt++;
|
|
pStatusInfo->nBorderY = nBorder<0 ? 0 : nBorder;
|
|
|
|
nBorder = *lpInt;
|
|
pStatusInfo->nBorderPart = nBorder<0 ? GetSystemMetrics(SM_CXBORDER) // andrewbe
|
|
: nBorder;
|
|
return(TRUE);
|
|
}
|
|
|
|
case HB_SAVERESTORE:
|
|
{
|
|
int *pInt;
|
|
BOOL bRet;
|
|
LPTSTR *lpNames;
|
|
|
|
pInt = (int *)LocalAlloc(LMEM_FIXED, pStatusInfo->nParts * sizeof(int));
|
|
if (!pInt)
|
|
return(FALSE);
|
|
|
|
lpNames = (LPTSTR *)lParam;
|
|
|
|
if (wParam)
|
|
{
|
|
SendMessage (hWnd, SB_GETPARTS, pStatusInfo->nParts,
|
|
(LPARAM)(LPINT)pInt);
|
|
bRet = WritePrivateProfileStruct(lpNames[0], szHeaderClassW,
|
|
(LPBYTE)pInt, pStatusInfo->nParts*sizeof(int), lpNames[1]);
|
|
}
|
|
else
|
|
{
|
|
bRet = GetPrivateProfileStruct(lpNames[0], szHeaderClassW,
|
|
(LPBYTE)pInt, pStatusInfo->nParts*sizeof(int), lpNames[1]);
|
|
if (bRet)
|
|
SendMessage (hWnd, SB_SETPARTS, pStatusInfo->nParts,
|
|
(LPARAM)(LPINT)pInt);
|
|
}
|
|
|
|
LocalFree((HLOCAL)pInt);
|
|
return(bRet);
|
|
}
|
|
|
|
case HB_ADJUST:
|
|
AdjustBorders(hWnd, pStatusInfo);
|
|
break;
|
|
|
|
case HB_GETPARTS:
|
|
{
|
|
HLOCAL hSaveParts;
|
|
PSTRINGINFO pSaveParts;
|
|
LPINT lpResult;
|
|
|
|
hSaveParts = GetHeaderParts(hWnd, pStatusInfo, FALSE);
|
|
if (!hSaveParts)
|
|
return(0L);
|
|
|
|
pSaveParts = (PSTRINGINFO) hSaveParts;
|
|
|
|
if (wParam > (WPARAM)pStatusInfo->nParts)
|
|
wParam = pStatusInfo->nParts;
|
|
|
|
for (lpResult = (LPINT)lParam; wParam > 0; --wParam, ++lpResult, ++pSaveParts)
|
|
*lpResult = pSaveParts->right;
|
|
|
|
return((LRESULT)pStatusInfo->nParts);
|
|
}
|
|
|
|
case HB_SHOWTOGGLE:
|
|
if (wParam >= (WPARAM)pStatusInfo->nParts)
|
|
return(FALSE);
|
|
|
|
pStatusInfo->sInfo[wParam].right = -pStatusInfo->sInfo[wParam].right;
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
return(TRUE);
|
|
|
|
case WM_SETCURSOR:
|
|
if ((HWND)wParam == hWnd)
|
|
{
|
|
POINT pt;
|
|
HLOCAL hSaveParts;
|
|
|
|
if (state.nPart >= 0)
|
|
{
|
|
SetCursor(hSplit);
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
GetCursorPos(&pt);
|
|
ScreenToClient(hWnd, &pt);
|
|
|
|
hSaveParts = GetHeaderParts(hWnd, pStatusInfo, FALSE);
|
|
if (!hSaveParts)
|
|
return(FALSE);
|
|
|
|
if (GetPart(pStatusInfo, hSaveParts, pt) >= 0)
|
|
{
|
|
SetCursor(hSplit);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
{
|
|
POINT pt;
|
|
|
|
LONG2POINT( lParam,pt );
|
|
BeginAdjust(hWnd, pStatusInfo, -1, pt);
|
|
break;
|
|
}
|
|
|
|
case WM_CHAR:
|
|
if (wParam == VK_ESCAPE)
|
|
AbortAdjust(pStatusInfo);
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
if (state.nPart>=0 && hWnd==state.hWnd)
|
|
{
|
|
/* We need to get the current position in case old MOUSEMOVE
|
|
* messages haven't been cleared yet.
|
|
*/
|
|
|
|
// andrewbe -- Fixed attempt to squeeze 64 bits into lParam
|
|
{
|
|
POINT CursorPos;
|
|
|
|
GetCursorPos(&CursorPos);
|
|
ScreenToClient(hWnd, &CursorPos);
|
|
lParam = MAKELPARAM((WORD)CursorPos.x, (WORD)CursorPos.y);
|
|
}
|
|
|
|
pStatusInfo->sInfo[state.nPart].right = LOWORD(lParam) - state.rc.left;
|
|
|
|
InvalidateRect(hWnd, &state.rc, FALSE);
|
|
UpdateWindow(hWnd);
|
|
|
|
SendMessage (state.hwndParent, WM_COMMAND,
|
|
GET_WM_COMMAND_MPS(state.ID,state.nPart, HBN_DRAGGING));
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
if (state.nPart >= 0 && hWnd == state.hWnd) // fix access violation (andrewbe)
|
|
{
|
|
HLOCAL hSaveParts;
|
|
PSTRINGINFO pSaveParts;
|
|
|
|
/* Save the width of the last column if it is visible.
|
|
*/
|
|
if (state.nLastVisible >= 0)
|
|
{
|
|
hSaveParts = GetHeaderParts(hWnd, pStatusInfo, FALSE);
|
|
if (hSaveParts)
|
|
{
|
|
pSaveParts = (PSTRINGINFO) hSaveParts;
|
|
if (pSaveParts[state.nLastVisible-1].right < state.rc.right)
|
|
{
|
|
pStatusInfo->sInfo[state.nLastVisible].right =
|
|
state.rc.right - pSaveParts[state.nLastVisible-1].right;
|
|
}
|
|
else
|
|
{
|
|
pStatusInfo->sInfo[state.nLastVisible].right =
|
|
state.pSaveParts[state.nLastVisible];
|
|
}
|
|
}
|
|
}
|
|
TermAdjust();
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DoDefault:
|
|
return(StatusWndProc(hWnd, uMessage, wParam, lParam));
|
|
}
|
|
|
|
BOOL FAR PASCAL InitHeaderClass(HINSTANCE hInstance)
|
|
{
|
|
WNDCLASS rClass;
|
|
|
|
if (GetClassInfo(hInstance, szHeaderClassW, &rClass))
|
|
return(TRUE);
|
|
|
|
hSplit = LoadCursor(hInst, (LPTSTR) MAKEINTRESOURCE(IDC_SPLIT));
|
|
|
|
rClass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
|
|
rClass.lpfnWndProc = (WNDPROC)HeaderWndProc;
|
|
rClass.cbClsExtra = 0;
|
|
rClass.cbWndExtra = sizeof(PSTATUSINFO);
|
|
rClass.hInstance = hInstance;
|
|
rClass.hIcon = NULL;
|
|
rClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
rClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
|
|
rClass.lpszMenuName = NULL;
|
|
rClass.lpszClassName = szHeaderClassW;
|
|
|
|
return(RegisterClass(&rClass));
|
|
}
|
|
|
|
|
|
HWND WINAPI CreateHeaderWindowA(LONG style, LPCSTR lpszText,
|
|
HWND hwndParent, WORD wID)
|
|
{
|
|
/* Create a default window and return
|
|
*/
|
|
return(CreateWindowA (szHeaderClassA, lpszText, style,
|
|
-100, -100, 10, 10, hwndParent, (HMENU)wID, hInst, NULL));
|
|
}
|
|
|
|
HWND WINAPI CreateHeaderWindowW(LONG style, LPCWSTR lpszText,
|
|
HWND hwndParent, WORD wID)
|
|
{
|
|
/* Create a default window and return
|
|
*/
|
|
return(CreateWindowW (szHeaderClassW, lpszText, style,
|
|
-100, -100, 10, 10, hwndParent, (HMENU)wID, hInst, NULL));
|
|
}
|
|
|