Download source and demo (4Kb)
Download EasySplit 2.0 Splitter Library by L.D. Blake (20kb)
I've added a new sourcecode download from L.D. Blake who kindly sent me a great little splitter library called "Easy Split". From the readme:
"EasySplitter is a custom control, in library format, that can be used
with Pelles C to implement a very simple splitter window. With EasySplitter
you create a splitter bar as a windows control that you can size, move and
stylize like any other windows control. All mouse capture and window drag
operations are handled internally by the control itself."
There is no such thing as a "splitter window". Sorry to disappoint anyone who wants to implement one, but I can't say it any simpler than that. Neither does there exist any method to split a window in half or quarters. What you are seeing when you see a so-called "splitter window" is a visual illusion.
What people most likely mean when they say "splitter windows", is the horizontal or vertical bar which separates two windows. This bar can be dragged back and forth using the mouse to resize the two windows which it separates.

There is no trickery used to perform this behaviour. This resizing or splitter bar is just a standard window, but the windows it divides and the bar itself are arranged in such a way to give the required effect.
There are two main ways of implementing a divider bar between two windows. They differ only in the organisation and relationship of the windows involved.
|
|
||||||
| Method 1 | Method 2 |
Both cases take advantage of the way that standard windows are drawn. Because the two windows will be positioned close to each other, their 3d borders give the illusion that there is a 3d bar in-between the two windows. In reality, it is just a standard flat grey window with no fancy graphics.
To make it obvious to the user that our splitter bar actually does something useful, then it is necessary to display some kind of sizing mouse cursor when the mouse moves over the "bar".
![]()
A cursor similar to the two above is probably the right kind of thing to display. There are two ways to display a custom cursor in a window.
This is the code that we use to register the splitter class.
WNDCLASSEX wc; ... wc.cbSize = sizeof(wndclass); wc.style = 0; wc.lpfnWndProc = SplitterProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor (hInstance, MAKEINTRESOURCE(IDC_HORZSPLITTER)); wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1); wc.lpszMenuName = NULL; wc.lpszClassName = "Splitter"; wc.hIconSm = NULL; RegisterClassEx(&wc);
To make a useable splitter bar, we need to handle the three standard mouse messages. Typical code that we would want to execute when the mouse button is pressed over our splitter window is below. Note that this is not executable code - it is presented to give an idea of the steps necessary to implement the dragging around of a splitter bar.
splitpos = GetCursorPos(); fDragMode = TRUE; /* set dragging to active */ SetCapture(hwnd); /* capture the mouse so we receive all messages */ hdc = GetDC(hwnd); /* Draw the checkered resizing bar */ DrawXorBar(hdc, splitpos); ReleaseDC(hwnd); old_splitpos = splitpos;
if(fDragMode == FALSE) return; splitpos = GetCursorPos(); hdc = GetDC(hwnd); DrawXorBar(hdc, old_splitpos); /* Erase where the bar WAS */ DrawXorBar(hdc, splitpos); /* Draw it where it IS now */ ReleaseDC(hwnd); old_splitpos = splitpos;
if(fDragMode == FALSE) return; fDragMode = FALSE; /* set dragging to unactive */ ReleaseCapture(); /* release the mouse capture: we don't need it */ hdc = GetDC(hwnd); /* Draw the bar again to erase it */ DrawXorBar(hdc, old_splitpos); ReleaseDC(hwnd);
Although the code above is just a sample of what needs to be achieved, in
reality the code is not much more complex. Probably the most complicated thing
to do is to draw some kind of checkered bar to provide feed-back when the
splitter bar is dragged around.
The feedback bar is just a simple rectangle, but drawn using a checkered pattern. Because we draw the rectangle using the PATINVERT style, we can easly restore the background to its original state by simply drawing the same rectangle back to the original position. So, calling DrawXorBar twice in succession will draw the checkered bar, but then immediately erase it again, restoring the background.
void DrawXorBar(HDC hdc, int x1, int y1, int width, int height)
{
static WORD _dotPatternBmp[8] = { 0x00aa, 0x0055, 0x00aa, 0x0055,
0x00aa, 0x0055, 0x00aa, 0x0055};
HBITMAP hbm;
HBRUSH hbr, hbrushOld;
/* create a monochrome checkered pattern */
hbm = CreateBitmap(8, 8, 1, 1, _dotPatternBmp);
hbr = CreatePatternBrush(hbm);
SetBrushOrgEx(hdc, x1, y1, 0);
hbrushOld = (HBRUSH)SelectObject(hdc, hbr);
/* draw the checkered rectangle to the screen */
PatBlt(hdc, x1, y1, width, height, PATINVERT);
SelectObject(hdc, hbrushOld);
DeleteObject(hbr);
DeleteObject(hbm);
}
I have presented the basic steps necessary to create a divider bar, or splitter window as it is more commonly refered to. What I haven't described is how to create a generic frame-work which magically does all of this work for you. If you want a frame-work to do this, then go and use MFC in your projects. Otherwise, it is up to you, the programmer, to decide how to arrange and manage your windows.
This sample project implements a simple splitter bar to get you started.
Please send any comments or suggestions to:
Last modified: 05 January 2006 22:06:54