' colin glenn ' Splitter Example (Revised) ' ' Ok, this is the Horizontal version. Looks rather like the vertical, just ' the layout of the windows and the fact that I'm using the X point instead ' of the Y point in the code, so this should not be terribly hard to meld ' ' with the VSPLITTER above. I'll find out. :) ' '-------------------------------------------------------------- ' ' Filename : HSPLITTER.BAS ' ' Description : This program demonstrates a simple "splitter window" ' ' Compiler Version - PB/WIN 7.02 (original) ' * Compiler Version - PB/WIN 8.00 (used when doing this.) ' * Win32Api Version - Last Update: 1 March 2005. ' Creation Date - Jan 1, 2004 ' Creation Time - 11:42 PM EST ' Window Platforms - Windows 95, 98, ME And XP. (And 2000) ' ' Original code: Raymond King ' Added horizontal split: Peter Redei ' Modified to limit the splits and several code adjustments: ' Colin August 25, 2005 ' This Source Code is placed into the Public Domain. ' '-------------------------------------------------------------- ' added all the %NO's I could find for making a light EXE, 18.5k. %NOANIMATE = 1 ' Animate control %NOBUTTON = 1 ' Button %NOCOMBO = 1 ' Combo box %NOCOMBOEX = 1 ' ComboBoxEx %NODATETIMEPICK = 1 ' Date/time picker %NODRAGLIST = 1 ' Drag list control %NOEDIT = 1 ' Edit control %NOFLATSBAPIS = 1 ' Flat scroll bar %NOHEADER = 1 ' Header control %NOHOTKEY = 1 ' HotKey control %NOIMAGELIST = 1 ' Image APIs %NOIPADDRESS = 1 ' IP Address edit control %NOLIST = 1 ' List box control %NOLISTVIEW = 1 ' ListView control %NOMENUHELP = 1 ' Menu help %NOMONTHCAL = 1 ' MonthCal %NOMUI = 1 ' MUI %NONATIVEFONTCTL = 1 ' Native Font control %NOPAGESCROLLER = 1 ' Pager %NOPROGRESS = 1 ' Progress control %NOREBAR = 1 ' Rebar control ' %NOSTATUSBAR = 1 ' Status bar %NOTABCONTROL = 1 ' Tab control %NOTOOLBAR = 1 ' Tool bar %NOTOOLTIPS = 1 ' Tool tips %NOTRACKBAR = 1 ' Track bar %NOTRACKMOUSEEVENT = 1 ' Track Mouse Event %NOTREEVIEW = 1 ' TreeView %NOUPDOWN = 1 ' Up Down arrow control #COMPILE EXE #INCLUDE "WIN32API.INC" #INCLUDE "CommCtrl.inc" GLOBAL szAppName AS ASCIIZ * 30 ' Class Name GLOBAL hInst AS DWORD ' Instance Handle GLOBAL hWnd AS DWORD ' hWnd Main Window GLOBAL hWndChild1 AS DWORD ' hwndChild1 Text Window GLOBAL hWndChild2 AS DWORD ' hwndChild2 Text Window GLOBAL hStaticBar AS DWORD GLOBAL hStatus AS DWORD GLOBAL oldx AS LONG ' old x value GLOBAL oldy AS LONG ' old y value GLOBAL fDragMode AS LONG ' Splitter Dragging. GLOBAL nSplitterPos AS LONG ' nSplitterPos = 100 GLOBAL nSplitterBorder AS LONG ' nSplitterBorder = 2 GLOBAL nSplitterLimit AS LONG GLOBAL iCaptionHeight AS LONG ' height of the window title area GLOBAL fSplitPercent AS SINGLE GLOBAL nStatusHeight AS DWORD GLOBAL nSplitMin AS DWORD GLOBAL nSplitMax AS DWORD %PERCENT_MIN = 20 %PERCENT_MAX = 80 FUNCTION WINMAIN (BYVAL hInstance AS DWORD, _ BYVAL hPrevInst AS DWORD, _ BYVAL lpszCmdLine AS ASCIIZ PTR, _ BYVAL nCmdShow AS LONG ) AS LONG LOCAL wc AS WNDCLASSEX LOCAL msg AS tagMSG LOCAL lStyles AS LONG oldx = - 4 oldy = - 4 fDragMode = %FALSE nSplitterPos = 1 ' some undersize number to generate the initial split nSplitterBorder = 3 ' make as big as you desire fSplitPercent = 0.20 ' needed otherwise weird code reactions szAppName = "Horizontal Splitter" ' REGISTER our MAIN window class wc.cbSize = SIZEOF(wc) wc.style = 0 wc.lpfnWndProc = CODEPTR(WndProc) wc.cbClsExtra = 0 wc.cbWndExtra = 0 wc.hInstance = hInstance wc.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) wc.hCursor = LoadCursor (%NULL, BYVAL %IDC_SIZEWE) REM wc.hbrBackground = (%COLOR_3DFACE + 1) wc.hbrBackground = GetStockObject(%HOLLOW_BRUSH) wc.lpszMenuName = 0 wc.lpszClassName = VARPTR(szAppName) wc.hIconSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) RegisterClassEx(wc) hInst = hInstance ' CREATE a window USING the registered class lStyles = %WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN ' CREATE the MAIN window. This window will HOST two child controls. hWnd = CreateWindowEx(0, _ ' EXTENDED style (NOT needed) szAppName, _ ' window class NAME szAppName, _ ' window caption lStyles, _ ' window styles %CW_USEDEFAULT, _ ' initial x position %CW_USEDEFAULT, _ ' initial y position %CW_USEDEFAULT, _ ' initial x SIZE %CW_USEDEFAULT, _ ' initial y SIZE %NULL, _ ' parent window HANDLE %NULL, _ ' use window class MENU hInst, _ ' program instance HANDLE BYVAL %NULL) ' creation parameters ShowWindow(hWnd, nCmdShow) WHILE(GetMessage(msg, %NULL, 0, 0)) TranslateMessage(msg) DispatchMessage(msg) WEND FUNCTION = 0 END FUNCTION FUNCTION Sp_SizeWindow(BYVAL nWidth AS LONG, BYVAL nHeight AS LONG) AS LONG LOCAL tx AS ASCIIZ * 120 LOCAL nSplitPoint AS LONG IF nWidth > 0 OR nHeight > 0 THEN ' if either width or height is 0, do not attempt to mod the numbers nHeight = nHeight - nStatusHeight ' the splitmin and splitmax are rebuilt here nSplitMin = nWidth * (%PERCENT_MIN / 100) nSplitMax = nWidth * (%PERCENT_MAX / 100) ' and we generate a check for if the split is in the right area nSplitPoint = nWidth * fSplitPercent ' check and see if we are within our limits or splitter percentage IF nSplitterPos > nSplitMax THEN nSplitterPos = nSplitMax ELSEIF nSplitterPos < nSplitMin THEN nSplitterPos = nSplitMin ELSEIF nSplitterPos <> nSplitPoint THEN nSplitterPos = nSplitPoint END IF END IF ' found out that the static child needs to be moved first ' otherwise weird drawing problems occur MoveWindow(hStaticBar, nSplitterPos, 0, nSplitterBorder, nHeight, %TRUE) MoveWindow(hwndChild1, 0, 0, nSplitterPos, nHeight, %TRUE) MoveWindow(hwndChild2, nSplitterPos + nSplitterBorder, 0, nWidth - nSplitterPos - nSplitterBorder, nHeight, %TRUE) tx = tx + " Cap:" + STR$(iCaptionHeight) + ":" + STR$(nStatusHeight) tx = tx + " Old:" + STR$(oldx) + "," + TRIM$(STR$(oldy)) tx = tx + " Win:" + STR$(nWidth) + "," + TRIM$(STR$(nHeight)) tx = tx + " MinMax:" + STR$(nSplitMin) + "," + TRIM$(STR$(nSplitMax)) tx = tx + " Percent:" + STR$(fSplitPercent) + ":" + STR$(nSplitterPos) + ":" + STR$(nSplitPoint) SetWindowText hStatus, tx FUNCTION = 0 END FUNCTION ' Here are the splitter functions SUB Sp_DrawBar(hDC AS DWORD, _ x1 AS LONG, _ y1 AS LONG, _ lWidth AS LONG, _ lHeight AS LONG) LOCAL hbr AS DWORD LOCAL hbrushOld AS DWORD '------------------------------------------------------------ ' Brush Hatch Styles: ' %HS_BDIAGONAL - 45-degree upward LEFT-TO-RIGHT hatch ' %HS_CROSS - Horizontal AND vertical crosshatch ' %HS_DIAGCROSS - 45-degree crosshatch ' %HS_FDIAGONAL - 45-degree downward LEFT-TO-RIGHT hatch ' %HS_HORIZONTAL - Horizontal hatch HS_VERTICAL Vertical hatch '------------------------------------------------------------ hbr = CreateHatchBrush(%HS_FDIAGONAL, RGB(0, 0, 0)) SetBrushOrgEx(hDC, x1, y1, BYVAL %NULL) hbrushOld = SelectObject(hDC, hbr) PatBlt(hDC, x1 + 4, y1, lWidth - 8, lHeight, %PATINVERT) SelectObject(hDC, hbrushOld) DeleteObject(hbr) END SUB FUNCTION Sp_OnLButtonDown(BYVAL hWnd AS DWORD, _ BYVAL wMsg AS DWORD, _ BYVAL wParam AS DWORD, _ BYVAL lParam AS LONG) AS LONG LOCAL pt AS POINTAPI LOCAL hdc AS DWORD LOCAL rc AS RECT LOCAL tx AS ASCIIZ * 80 pt.x = LOWRD(lParam) ' horizontal position OF cursor pt.y = HIWRD(lParam) ' get the clients area GetClientRect(hWnd, rc) fDragMode = %TRUE SetCapture(hWnd) hdc = GetWindowDC(hWnd) Sp_DrawBar(hdc, pt.x + 3, iCaptionHeight, 4, rc.nBottom - nSplitterLimit) tx = "Horizontal" fSplitPercent = pt.x / rc.nRight ReleaseDC(hWnd, hdc) oldx = pt.x oldy = pt.y tx = tx + " Cap:" + STR$(iCaptionHeight) + "," + TRIM$(STR$(nStatusHeight)) tx = tx + " Old:" + STR$(oldx) + "," + TRIM$(STR$(oldy)) tx = tx + " Win:" + STR$(rc.nRight) + "," + TRIM$(STR$(rc.nBottom)) tx = tx + " MinMax:" + STR$(nSplitMin) + "," + TRIM$(STR$(nSplitMax)) tx = tx + " Percent:" + STR$(fSplitPercent) SetWindowText hStatus, tx FUNCTION = 0 END FUNCTION FUNCTION Sp_OnLButtonUp(BYVAL hWnd AS DWORD, _ BYVAL wMsg AS DWORD, _ BYVAL wParam AS DWORD, _ BYVAL lParam AS LONG) AS LONG LOCAL hdc AS DWORD LOCAL rc AS RECT LOCAL pt AS POINTAPI LOCAL tx AS ASCIIZ * 80 IF (fDragMode = %FALSE) THEN FUNCTION = 0 EXIT FUNCTION END IF pt.x = LOWRD(lParam) ' horizontal position OF cursor pt.y = HIWRD(lParam) GetClientRect(hWnd, rc) hdc = GetWindowDC(hWnd) Sp_DrawBar(hdc, oldx + 3, iCaptionHeight, 4, rc.nBottom - nSplitterLimit) tx = "Horizontal" ReleaseDC(hWnd, hdc) oldx = pt.x oldy = pt.y fDragMode = %FALSE Sp_SizeWindow(rc.nRight, rc.nBottom) ReleaseCapture() tx = tx + " Cap:" + STR$(iCaptionHeight) + "," + TRIM$(STR$(nStatusHeight)) tx = tx + " Old:" + STR$(oldx) + "," + TRIM$(STR$(oldy)) tx = tx + " Win:" + STR$(rc.nRight) + "," + TRIM$(STR$(rc.nBottom)) tx = tx + " MinMax:" + STR$(nSplitMin) + "," + TRIM$(STR$(nSplitMax)) tx = tx + " Percent:" + STR$(fSplitPercent) SetWindowText hStatus, tx FUNCTION = 0 END FUNCTION FUNCTION Sp_OnMouseMove(BYVAL hWnd AS DWORD, _ BYVAL wMsg AS DWORD, _ BYVAL wParam AS DWORD, _ BYVAL lParam AS LONG) AS LONG LOCAL hdc AS DWORD LOCAL rc AS RECT LOCAL pt AS POINTAPI LOCAL tx AS ASCIIZ * 80 pt.x = LOWRD(lParam) ' horizontal position OF cursor pt.y = HIWRD(lParam) GetClientRect(hWnd, rc) IF (fDragMode = %FALSE) THEN tx = "Mouse:" + STR$(pt.x) + "," + TRIM$(STR$(pt.y)) tx = tx + " Win:" + STR$(rc.nRight) + "," + TRIM$(STR$(rc.nBottom)) tx = tx + " Splitter:" + STR$(nSplitterPos) + " :" + STR$(nSplitMin) + "," + TRIM$(STR$(nSplitMax)) tx = tx + " Percent:" + STR$(fSplitPercent) SetWindowText hStatus, tx FUNCTION = 0 EXIT FUNCTION END IF IF (pt.x <> oldx AND (wParam AND %MK_LBUTTON) = %TRUE) THEN hdc = GetWindowDC(hWnd) IF pt.x < nSplitMin THEN pt.x = nSplitMin ELSEIF pt.x > nSplitMax THEN pt.x = nSplitMax END IF ' if the resulting move moves the bar outside the limits ' then exit the function IF pt.x < (nSplitMin) THEN EXIT FUNCTION IF pt.x > (nSplitMax) THEN EXIT FUNCTION ' otherwise draw the bar nSplitterPos = pt.x hdc = GetWindowDC(hWnd) Sp_DrawBar(hdc, oldx + 3, iCaptionHeight, 4, rc.nBottom - nSplitterLimit) Sp_DrawBar(hdc, pt.x + 3, iCaptionHeight, 4, rc.nBottom - nSplitterLimit) ReleaseDC(hWnd, hdc) tx = "Horizontal" fSplitPercent = pt.x / rc.nRight END IF ReleaseDC(hWnd, hdc) oldx = pt.x oldy = pt.y tx = tx + " Cap:" + STR$(iCaptionHeight) + "," + TRIM$(STR$(nStatusHeight)) tx = tx + " Old:" + STR$(oldx) + "," + TRIM$(STR$(oldy)) tx = tx + " Win:" + STR$(rc.nRight) + "," + TRIM$(STR$(rc.nBottom)) tx = tx + " MinMax:" + STR$(nSplitMin) + "," + TRIM$(STR$(nSplitMax)) tx = tx + " Percent:" + STR$(fSplitPercent) SetWindowText hStatus, tx FUNCTION = 0 END FUNCTION FUNCTION CenterWindow (BYVAL hWnd AS DWORD) AS LONG LOCAL WndRect AS RECT LOCAL x AS LONG LOCAL y AS LONG CALL GetWindowRect(hWnd, WndRect) x = (GetSystemMetrics(%SM_CXSCREEN) - (WndRect.nRight - WndRect.nLeft)) \ 2 y = (GetSystemMetrics(%SM_CYSCREEN) - (WndRect.nBottom - WndRect.nTop + _ GetSystemMetrics(%SM_CYCAPTION))) \ 2 CALL SetWindowPos(hWnd, %NULL, x, y, 0, 0, %SWP_NOSIZE OR %SWP_NOZORDER) END FUNCTION FUNCTION WndProc(BYVAL hWnd AS DWORD, _ BYVAL wMsg AS DWORD, _ BYVAL wParam AS DWORD, _ BYVAL lParam AS LONG) AS LONG LOCAL rc1 AS RECT SELECT CASE wMsg CASE %WM_CREATE iCaptionHeight = GetSystemMetrics(%SM_CYCAPTION) + GetSystemMetrics(%SM_CYFRAME) CenterWindow (hWnd) hwndChild1 = CreateWindowEx(%WS_EX_CLIENTEDGE, _ "edit",_ ' window class name "",_ ' window caption %WS_CHILD OR _ ' styles used %WS_CLIPSIBLINGS OR _ %WS_VISIBLE OR _ %ES_MULTILINE OR _ %ES_AUTOVSCROLL OR _ %WS_BORDER OR _ %ES_LEFT OR _ %ES_NOHIDESEL OR _ %WS_VSCROLL, _ 0, 0, 0, 0, hWnd, 0, hInst, BYVAL %NULL) hwndChild2 = CreateWindowEx(%WS_EX_CLIENTEDGE, _ "edit",_ ' window class name "",_ ' window caption %WS_CHILD OR _ ' styles used %WS_CLIPSIBLINGS OR _ %WS_VISIBLE OR _ %ES_MULTILINE OR _ %ES_AUTOVSCROLL OR _ %WS_BORDER OR _ %ES_LEFT OR _ %ES_NOHIDESEL OR _ %WS_VSCROLL, _ 0, 0, 0, 0, hWnd, 0, hInst, BYVAL %NULL) hStaticBar = CreateWindowEx(0, _ "STATIC", "", _ %WS_VISIBLE OR %WS_CHILD OR %SS_BLACKRECT, _ 0, 0, 0, 0, hWnd, 0, hInst, BYVAL %NULL) ' ought to update this to reflect latest SDK recommendations. hStatus = CreateStatusWindow(%WS_CHILD OR %WS_BORDER OR %WS_VISIBLE OR %SBS_SIZEGRIP, "", hWnd, 200) GetClientRect hStatus, rc1 nStatusHeight = rc1.nBottom nSplitterLimit = nStatusHeight ' + iCaptionHeight FUNCTION = 0 CASE %WM_SIZE SendMessage hStatus, wMsg, wParam, lParam FUNCTION = Sp_SizeWindow(LOWRD(lParam), HIWRD(lParam)) CASE %WM_CLOSE FUNCTION = DestroyWindow(hWnd) CASE %WM_DESTROY PostQuitMessage(0) CASE %WM_LBUTTONDOWN FUNCTION = Sp_OnLButtonDown(hWnd, wMsg, wParam, lParam) CASE %WM_LBUTTONUP FUNCTION = Sp_OnLButtonUp(hWnd, wMsg, wParam, lParam) CASE %WM_MOUSEMOVE FUNCTION = Sp_OnMouseMove(hWnd, wMsg, wParam, lParam) CASE ELSE END SELECT FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam) END FUNCTION