Splitter

>> Wednesday, October 28, 2009



#include <windows.h>

#define MINSIZE 50
// The minimal width and height a childwindow should have
#define SBS 2 // Short for SplitterBarSize

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hwndChild1, hwndChild2, hwndChild3;
static CREATESTRUCT *cs;
static HCURSOR hcSizeNS, hcSizeEW, hcArrow;
static int xDiv, yDiv;
static BOOL xSizing, ySizing;

int xPos, yPos;
RECT rect, focusrect;
HDC hdc;

switch (iMsg)
{
case WM_CREATE:
cs = (CREATESTRUCT*)lParam;
xDiv = 300;
yDiv = 300;

hwndChild1 = CreateWindowEx(WS_EX_CLIENTEDGE, "Pane 1", "Child 1",
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, 0, 0, 0, 0, hwnd, NULL, cs
->hInstance, NULL);
hwndChild2 = CreateWindowEx(WS_EX_CLIENTEDGE, "Pane 2", "Child 2",
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, 0, 0, 0, 0, hwnd, NULL, cs
->hInstance, NULL);
hwndChild3 = CreateWindowEx(WS_EX_CLIENTEDGE, "Pane 3", "Child 3",
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, 0, 0, 0, 0, hwnd, NULL, cs
->hInstance, NULL);

hcSizeNS = LoadCursor(NULL, IDC_SIZENS);
hcSizeEW = LoadCursor(NULL, IDC_SIZEWE);
hcArrow = LoadCursor(NULL, IDC_ARROW);
break;

case WM_SIZE:
GetClientRect(hwnd, &rect);
// Make sure splitterbars are visible
if (xDiv > rect.right - MINSIZE)
{
xDiv = rect.right - MINSIZE;
}
else if (xDiv < MINSIZE)
{
xDiv = MINSIZE;
}
if (yDiv > rect.bottom - MINSIZE)
{
yDiv = rect.bottom - MINSIZE;
}
else if (yDiv < MINSIZE)
{
yDiv = MINSIZE;
}
MoveWindow(hwndChild1, rect.left, rect.top + 1, rect.left + xDiv - SBS,
rect.top + yDiv - SBS, FALSE);
MoveWindow(hwndChild2, rect.left + xDiv + SBS, rect.top + 1, rect.right -
rect.left - xDiv - SBS, rect.top + yDiv - SBS, FALSE);
MoveWindow(hwndChild3, rect.left, rect.top + yDiv + SBS, rect.right -
rect.left, rect.bottom - rect. top - yDiv - SBS, FALSE);
InvalidateRect(hwnd, &rect, TRUE);
break;

case WM_LBUTTONDOWN:
xPos = (int)LOWORD(lParam);
yPos = (int)HIWORD(lParam);

xSizing = (xPos > xDiv - SBS && xPos < xDiv + SBS);
ySizing = (yPos > yDiv - SBS && yPos < yDiv + SBS);

if (xSizing || ySizing)
{
SetCapture(hwnd); // Track movement of the mousepointer
if (xSizing)
{
SetCursor(hcSizeEW);
}
else if (ySizing)
{
SetCursor(hcSizeNS);
}
}
break;

case WM_LBUTTONUP:
if (xSizing || ySizing)
{
ReleaseCapture();
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect);
if (xSizing)
{
SetRect(&focusrect, xDiv - SBS, rect.top, xDiv + SBS, yDiv);
DrawFocusRect(hdc, &focusrect);
xSizing = FALSE;
}
if (ySizing)
{
SetRect(&focusrect, rect.left + 1, yDiv - SBS, rect.right, yDiv + SBS)
;
DrawFocusRect(hdc, &focusrect);
ySizing = FALSE;
}
ReleaseDC(hwnd, hdc);
}
// Post a size message so the childwindows get their new size
PostMessage(hwnd, WM_SIZE, 0, 0);
break;

case WM_MOUSEMOVE:
xPos = (int)LOWORD(lParam);
yPos = (int)HIWORD(lParam);

if (wParam == MK_LBUTTON)
// Is one of the splitterbars being moved?
{
if (xSizing || ySizing)
{
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect);

if (xSizing)
{
SetRect(&focusrect, xDiv - SBS, rect.top, xDiv + SBS, yDiv);
DrawFocusRect(hdc, &focusrect);

xDiv = xPos;

SetRect(&focusrect, xDiv - SBS, rect.top, xDiv + SBS, yDiv);
DrawFocusRect(hdc, &focusrect);
}
if (ySizing)
{
SetRect(&focusrect, rect.left + 1, yDiv - SBS, rect.right, yDiv +
SBS);
DrawFocusRect(hdc, &focusrect);

yDiv = yPos;

SetRect(&focusrect, rect.left + 1, yDiv - SBS, rect.right, yDiv +
SBS);
DrawFocusRect(hdc, &focusrect);
}
ReleaseDC(hwnd, hdc);
}
break; // Leave
}

if ((xPos > xDiv - SBS && xPos < xDiv + SBS) && GetCursor() != hcSizeEW)
{
SetCursor(hcSizeEW); // hovering above the vertical splitterbar
}
else if ((yPos > yDiv - SBS && yPos < yDiv + SBS) && GetCursor() !=
hcSizeNS)
{
SetCursor(hcSizeNS); // hovering above the horizontal splitterbar
}
else if (GetCursor() != hcArrow)
{
SetCursor(hcArrow); // not hovering above a splitterbar
}
break;

case WM_CLOSE:
DestroyWindow(hwnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

LRESULT CALLBACK Child1WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam
)
{
switch (iMsg)
{
case WM_CREATE:
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

LRESULT CALLBACK Child2WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam
)
{
switch (iMsg)
{
case WM_CREATE:
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

LRESULT CALLBACK Child3WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam
)
{
switch (iMsg)
{
case WM_CREATE:
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine,
int iCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
char szAppName[] = "SplitterApp";

wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, szAppName);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
RegisterClass(&wndclass);

wndclass.lpfnWndProc = Child1WndProc;
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclass.lpszClassName = "Pane 1";
RegisterClass(&wndclass);

wndclass.lpfnWndProc = Child2WndProc;
wndclass.lpszClassName = "Pane 2";
RegisterClass(&wndclass);

wndclass.lpfnWndProc = Child3WndProc;
wndclass.lpszClassName = "Pane 3";
RegisterClass(&wndclass);

hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW | SW_MAXIMIZE |
WS_VISIBLE, 0, 0, 600, 500, NULL, NULL, hInstance, szCmdLine);

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}


0 comments: