This started out as a test of the new PB 9.0 Statusbar control... but I ended up writing a program of a toggling SplitterBar. The SplitterBar can be toggled between vertical stacking and horizontal stacking of controls. It will retain it's relative position in the client area. It also can be toggled between continuous update of the controls during splitterbar dragging or updating after the splitterbar is moved.
This was an excersize to try mostly DDT. No RECT, no POINTAPI, no BRUSHes, no GetWindowDC, no LoadCursor.
BTW, the new DDT Statusbar control works great!
This source code is placed into the Public Domain.
A test program of the SplitterBar and new Statusbar:
Any comments and suggestions would be appreciated in the PB for Windows Forum!
This was an excersize to try mostly DDT. No RECT, no POINTAPI, no BRUSHes, no GetWindowDC, no LoadCursor.
BTW, the new DDT Statusbar control works great!
This source code is placed into the Public Domain.
Code:
'TOGGLESPLITTER.INC - Bill Kuehnling '----------------------------------------------------------------------------------- TYPE TOGGLESPLITTER MODE AS STRING * 4' "VERT" OR "HORZ" Dragging AS LONG ' in dragging process Top AS LONG ' Top of SplitterBar LEFT AS LONG ' Left of SplitterBar WIDTH AS LONG ' Width of SplitterBar SplitID AS LONG ' the control %ID assigned to the new SplitterBar CtlID1 AS LONG ' the left or top Control %ID being split CtlID2 AS LONG ' the right or bottom Control %ID being split BorderTop AS LONG ' the top border ht of the client area being split BorderBtm AS LONG ' the bottom border ht in the area being split BorderLeft AS LONG ' the left border width in the area being split BorderRight AS LONG ' the right border width in the area being split Proportion AS SINGLE' the position of splitter in proportion to the client area Continuous AS LONG ' TRUE if Controls are re-sized while dragging splitter PARENT AS DWORD ' the handle of the Dialog END TYPE '----------------------------------------------------------------------------------- GLOBAL SplitBar AS TOGGLESPLITTER '----------------------------------------------------------------------------------- %SPLIT_VERT=1 %SPLIT_HORIZ=0 %SPLIT_CONT=1 %SPLIT_NORM=0 '----------------------------------------------------------------------------------- SUB AddSplitter(hDlg AS DWORD,lSplitID AS LONG, lMode AS LONG, lWidth AS LONG, _ lCtlID1 AS LONG, lCtlID2 AS LONG, lBorderTop AS LONG, _ lBorderBtm AS LONG, lBorderLeft AS LONG, lBorderRight AS LONG, _ fProportion AS SINGLE, lContinuous AS LONG ) SplitBar.Parent=hDlg SplitBar.SplitID=lSplitID ' convert 0 and 1 to text values: SplitBar.MODE=IIF$( lMode=0 ,"HORZ","VERT") SplitBar.WIDTH=lWidth SplitBar.CtlID1=lCtlID1 SplitBar.CtlID2=lCtlID2 SplitBar.BorderTop=lBorderTop SplitBar.BorderBtm=lBorderBtm SplitBar.BorderLeft=lBorderLeft SplitBar.BorderRight=lBorderRight ' Fix any misguided percent parameters: IF fProportion <=0 THEN fProportion=.5 IF fProportion =>1 THEN fProportion=(fProportion MOD 100)*.01 SplitBar.Proportion=fProportion SplitBar.Continuous=IIF(lContinuous=1,-1,0) CONTROL ADD LABEL, SplitBar.Parent, SplitBar.SplitID, "", 5, 5, 5, 5 InitSplitter END SUB '----------------------------------------------------------------------------------- ' Set up the SplitterBar. SUB InitSplitter() IF SplitBar.Mode="HORZ" THEN SplitBar.Top=SplitBar.BorderTop ELSE 'SplitBar.Mode="VERT" SplitBar.Left=SplitBar.BorderLeft END IF AdjustSplitterPos CONTROL SET COLOR SplitBar.Parent, SplitBar.SplitID, 0, %LTGRAY UpdateSplitter SizeControls END SUB '----------------------------------------------------------------------------------- ' Resize the SplitterBar. Called from CASE %WM_SIZE SUB SplitResize() AdjustSplitterPos ' figure the proportional location of the splitter in the client area UpdateSplitter ' position the splitter bar SizeControls ' size the Editboxes in this case END SUB '----------------------------------------------------------------------------------- ' Called from CASE %WM_LBUTTONDOWN SUB SplitLBtnDown( lX AS LONG, lY AS LONG) IF OnSplitter(lX, lY) THEN IF SplitBar.Mode="HORZ" THEN MOUSEPTR 9 ELSE MOUSEPTR 7 StartDrag lX, lY END IF END SUB '----------------------------------------------------------------------------------- ' Called from CASE %WM_MOUSEMOVE SUB SplitMouseMove(lX AS LONG, lY AS LONG) IF OnSplitter(lX, lY) THEN IF SplitBar.Mode="HORZ" THEN MOUSEPTR 9 ELSE MOUSEPTR 7 END IF IF NOT SplitBar.Dragging THEN EXIT SUB IF SplitBar.Mode="HORZ" THEN DragHorizSplitter lX, lY ELSE 'SplitBar.Mode="VERT" DragVertSplitter lX, lY END IF END SUB '----------------------------------------------------------------------------------- ' Compute the new location of the SplitterBar based on proportion in client area SUB AdjustSplitterPos LOCAL lClWide, lClHigh AS LONG DIALOG GET CLIENT SplitBar.Parent TO lClWide, lClHigh IF SplitBar.Mode="HORZ" THEN SplitBar.Left=SplitBar.Proportion * _ ((lClWide-SplitBar.BorderLeft-SplitBar.BorderRight)-.5*SplitBar.Width) _ + SplitBar.BorderLeft ELSE 'SplitBar.Mode="VERT" SplitBar.Top=SplitBar.Proportion * _ ((lClHigh -SplitBar.BorderTop-SplitBar.BorderBtm)-.5*SplitBar.Width) _ + SplitBar.BorderTop END IF END SUB '----------------------------------------------------------------------------------- ' Position the SplitterBar in the client area SUB UpdateSplitter() LOCAL lClWide, lClHigh, lSplit AS LONG lSplit=SplitBar.Width/3 DIALOG GET CLIENT SplitBar.Parent TO lClWide, lClHigh IF SplitBar.Mode="HORZ" THEN SetControlPos SplitBar.SplitID, SplitBar.Left+lSplit, SplitBar.BorderTop, lSplit, _ lClHigh-SplitBar.BorderTop-SplitBar.BorderBtm ELSE 'SplitBar.Mode="VERT" SetControlPos SplitBar.SplitID, SplitBar.BorderLeft, SplitBar.Top+lSplit, _ lClWide-SplitBar.BorderLeft-SplitBar.BorderRight, lSplit END IF CONTROL REDRAW SplitBar.Parent, SplitBar.SplitID END SUB '----------------------------------------------------------------------------------- ' Resize and position the two controls being split using SplitterBar coordinates SUB SizeControls() LOCAL lClWide, lClHigh AS LONG DIALOG GET CLIENT SplitBar.Parent TO lClWide, lClHigh IF SplitBar.Mode="HORZ" THEN SetControlPos SplitBar.CtlID1, SplitBar.BorderLeft, SplitBar.BorderTop, _ SplitBar.Left-SplitBar.BorderLeft, _ lClHigh-SplitBar.BorderTop-SplitBar.BorderBtm SetControlPos SplitBar.CtlID2, SplitBar.Left+SplitBar.Width, SplitBar.BorderTop, _ lClWide-SplitBar.Left-SplitBar.Width-SplitBar.BorderRight, _ lClHigh-SplitBar.BorderTop-SplitBar.BorderBtm ELSE 'SplitBar.Mode="VERT" SetControlPos SplitBar.CtlID1, SplitBar.BorderLeft, SplitBar.BorderTop, _ lClWide-SplitBar.BorderLeft-SplitBar.BorderRight, _ SplitBar.Top-SplitBar.BorderTop SetControlPos SplitBar.CtlID2, SplitBar.BorderLeft, SplitBar.Top+SplitBar.Width, _ lClWide-SplitBar.BorderLeft-SplitBar.BorderRight, _ lClHigh-SplitBar.Top-SplitBar.Width-SplitBar.BorderBtm END IF END SUB '----------------------------------------------------------------------------------- ' Determine if cursor is on top of the SplitterBar. Called from CASE %WM_MOUSEMOVE FUNCTION OnSplitter(lX AS LONG, lY AS LONG) AS LONG LOCAL lClWide, lClHigh AS LONG DIALOG GET CLIENT SplitBar.Parent TO lClWide, lClHigh IF SplitBar.Mode="HORZ" THEN IF lX>SplitBar.Left AND lX<SplitBar.Left+SplitBar.Width THEN IF lY>SplitBar.BorderTop AND lY< lClHigh- SplitBar.BorderBtm THEN OnSplitter=-1 END IF END IF ELSE 'SplitBar.Mode="VERT" IF ly>SplitBar.Top AND ly<SplitBar.Top+SplitBar.Width THEN IF lX>SplitBar.Left AND lX<lClWide-SplitBar.BorderRight THEN OnSplitter=-1 END IF END IF END IF END FUNCTION '----------------------------------------------------------------------------------- ' We are OnSplitter and detected %WM_LBUTTONDOWN so start a drag ' Called from SplitLBtnDown SUB StartDrag(lX AS LONG, lY AS LONG) SplitBar.Dragging=-1 SetCapture SplitBar.Parent CONTROL SET COLOR SplitBar.Parent, SplitBar.SplitID, 0, %BLACK CONTROL REDRAW SplitBar.Parent, SplitBar.SplitID END SUB '----------------------------------------------------------------------------------- ' Called from SplitMouseMove SUB DragHorizSplitter(lX AS LONG, lY AS LONG) LOCAL lClWide, lClHigh AS LONG DIALOG GET CLIENT SplitBar.Parent TO lClWide, lClHigh IF lX<SplitBar.Width\2 THEN lx=SplitBar.Width\2 IF lX>lClWide-(SplitBar.Width\2) THEN lx=lClWide-(SplitBar.Width\2) SplitBar.Left= lX-(SplitBar.Width\2) UpdateSplitter IF SplitBar.Continuous THEN SizeControls END SUB '----------------------------------------------------------------------------------- ' Called from SplitMouseMove SUB DragVertSplitter(lX AS LONG, lY AS LONG) LOCAL lClWide, lClHigh AS LONG DIALOG GET CLIENT SplitBar.Parent TO lClWide, lClHigh IF lY<SplitBar.BorderTop+(SplitBar.Width\2) THEN _ lY=SplitBar.BorderTop+(SplitBar.Width\2) IF lY>lClHigh-SplitBar.BorderBtm-(SplitBar.Width\2) THEN _ lY=lClHigh-SplitBar.BorderBtm-(SplitBar.Width\2) SplitBar.Top=lY-(SplitBar.Width\2) UpdateSplitter IF SplitBar.Continuous THEN SizeControls END SUB '----------------------------------------------------------------------------------- ' Called from %WM_LBUTTONUP. Stop dragging. SUB SplitStopDrag(lX AS LONG, lY AS LONG) IF SplitBar.Dragging=0 THEN EXIT SUB LOCAL X1, Y1, lWide1, lHigh1 AS LONG LOCAL lClWide, lClHigh AS LONG DIALOG GET CLIENT SplitBar.Parent TO lClWide, lClHigh CONTROL GET LOC SplitBar.Parent, SplitBar.SplitID TO X1, Y1 CONTROL GET SIZE SplitBar.Parent, SplitBar.SplitID TO lWide1, lHigh1 ReleaseCapture() SplitBar.Dragging=0 IF SplitBar.Mode="HORZ" THEN SplitBar.Left=X1 - (SplitBar.Width\2) SplitBar.Proportion=(X1-SplitBar.BorderLeft)/ _ (lClWide-SplitBar.BorderLeft-SplitBar.BorderRight) ELSE ' SplitBar.Mode="VERT" SplitBar.Top=Y1 - (SplitBar.Width\2) SplitBar.Proportion=(Y1-SplitBar.BorderTop)/ _ (lClHigh -SplitBar.BorderTop-SplitBar.BorderBtm) END IF UpdateSplitter SizeControls CONTROL SET COLOR SplitBar.Parent, SplitBar.SplitID, 0, %LTGRAY CONTROL REDRAW SplitBar.Parent, SplitBar.SplitID END SUB '----------------------------------------------------------------------------------- ' Switch between horizontal and vertical stacking of the controls SUB ToggleSplitterMode() IF SplitBar.Mode="HORZ" THEN SplitBar.Mode="VERT" ELSE SplitBar.Mode="HORZ" InitSplitter END SUB '----------------------------------------------------------------------------------- ' Switch between continuous or not resizing the controls during dragging SUB ToggleContinuous() SplitBar.Continuous = NOT SplitBar.Continuous END SUB '----------------------------------------------------------------------------------- ' Substituted this for the API function SetWindowPos. SUB SetControlPos(lCtlID AS LONG, lLeft AS LONG, lTop AS LONG, lWidth AS LONG, lHeight AS LONG ) CONTROL SET LOC SplitBar.Parent, lCtlID, lLeft, lTop CONTROL SET SIZE SplitBar.Parent, lCtlID, lWidth, lHeight END SUB '-----------------------------------------------------------------------------------
Code:
'Toggle SplitterBar.BAS ' Test a SplitterBar that can be toggled between vertical stacking and horizontal ' stacking of controls. ' The splitterbar will retain it's relative position in the client area. ' It also can be toggled between continuous update of the controls during ' splitterbar dragging or updating after the splitterbar is moved. ' This was an excersize to try mostly DDT. ' No RECT, no POINTAPI, no BRUSHes, no GetWindowDC, no LoadCursor ' This source code is placed into the Public Domain. ' #COMPILER PBWIN 9 #COMPILE EXE OPTION EXPLICIT '----------------------------------------------------------------------------------- #INCLUDE ONCE "WIN32API.INC" #INCLUDE ONCE "TOGGLESPLITTER.INC" '----------------------------------------------------------------------------------- %TXT_BOX1=1001 %TXT_BOX2=1002 %STAT_STATUSBAR=1003 %BTN_HV=1004 %BTN_CONT=1005 %ID_SPLITTER=1006 '----------------------------------------------------------------------------------- FUNCTION PBMAIN() ShowDIALOG %HWND_DESKTOP END FUNCTION '----------------------------------------------------------------------------------- CALLBACK FUNCTION ShowDIALOGProc() STATIC hWndSaveFocus AS DWORD LOCAL NA , lHtTop, lHtBtm AS LONG SELECT CASE AS LONG CB.MSG CASE %WM_INITDIALOG ' get a top border height, for this case using the top of the edit box CONTROL GET LOC CB.HNDL, %TXT_BOX1 TO NA, lHtTop ' get a bottom border height, using the height of the Statusbar CONTROL GET SIZE CB.HNDL, %STAT_STATUSBAR TO NA, lHtBtm ' add the SplitterBar. See the function in the inc file for req'd parameters AddSplitter(CB.HNDL,%ID_SPLITTER, %SPLIT_HORIZ, 6, %TXT_BOX1, %TXT_BOX2, _ lHtTop, lHtBtm+4, 4, 4, .75, %SPLIT_CONT) CASE %WM_SIZE SplitResize ' <-- For resizing SplitterBar ' for statusbar demo UpdateStatusBar CB.HNDL CONTROL SEND CB.HNDL, %STAT_STATUSBAR, CB.MSG, CB.WPARAM, CB.LPARAM CONTROL REDRAW CB.HNDL, %STAT_STATUSBAR ' <-- Need to do after resize CASE %WM_NCACTIVATE IF ISFALSE CBWPARAM THEN hWndSaveFocus=GetFocus() ELSEIF hWndSaveFocus THEN SetFocus(hWndSaveFocus) hWndSaveFocus=0 END IF CASE %WM_LBUTTONDOWN ' SplitterBar function here SplitLBtnDown LO(WORD, CB.LPARAM), HI(WORD, CB.LPARAM) CASE %WM_MOUSEMOVE ' SplitterBar function here SplitMouseMove LO(WORD, CB.LPARAM), HI(WORD, CB.LPARAM) ' for statusbar demo IF SplitBar.Dragging THEN UpdateStatusBar CB.HNDL CASE %WM_LBUTTONUP ' SplitterBar function here SplitStopDrag LO(WORD, CB.LPARAM), HI(WORD, CB.LPARAM) ' for statusbar demo UpdateStatusBar CB.HNDL CASE %WM_COMMAND SELECT CASE AS LONG CB.CTL CASE %BTN_HV ToggleSplitterMode ' for statusbar demo UpdateStatusBar CB.HNDL CASE %BTN_CONT ToggleContinuous ' for statusbar demo UpdateStatusBar CB.HNDL END SELECT END SELECT END FUNCTION '----------------------------------------------------------------------------------- FUNCTION ShowDIALOG(BYVAL hParent AS DWORD) AS LONG LOCAL lRslt AS LONG LOCAL hDlg AS DWORD ' Using PIXELS so that mouse coordinates don't have to be converted DIALOG NEW PIXELS, hParent, "DDT Toggle Splitter", 137, 87, 700, 500, _ %WS_POPUP OR %WS_THICKFRAME _ OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR _ %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _ %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _ %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg 'DIALOG SET COLOR hDlg,-1, %WHITE 'helps reduce flicker while edits redraw CONTROL ADD STATUSBAR, hDlg, %STAT_STATUSBAR, "DDT STATUSBAR", 0, 0, 0, 0 CONTROL ADD TEXTBOX, hDlg, %TXT_BOX1, "TextBox1", 0, 25, 279, 417, _ %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_VSCROLL OR %ES_LEFT _ OR %ES_MULTILINE OR %ES_AUTOVSCROLL OR %ES_WANTRETURN, _ %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _ %WS_EX_RIGHTSCROLLBAR CONTROL ADD TEXTBOX, hDlg, %TXT_BOX2, "TextBox2", 286, 25, 318, 417, _ %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_VSCROLL OR %ES_LEFT _ OR %ES_MULTILINE OR %ES_AUTOVSCROLL OR %ES_WANTRETURN, _ %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _ %WS_EX_RIGHTSCROLLBAR CONTROL ADD BUTTON, hDlg, %BTN_HV, "TOGGLE H/V", 5, 2, 85, 20 CONTROL ADD BUTTON, hDlg, %BTN_CONT, "TOGGLE CONT", 100, 2, 85, 20 STATUSBAR SET PARTS hDlg, %STAT_STATUSBAR, 120, 60, 60, 60, 9999 STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 2, 0, "TWO" STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 3, 0, "THREE" STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 4, 0, "FOUR" STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 5, 0, "FIVE" DIALOG SHOW MODAL hDlg, CALL ShowDIALOGProc TO lRslt FUNCTION=lRslt END FUNCTION '----------------------------------------------------------------------------------- ' Update info in the Statusbar SUB UpdateStatusBar(hDlg AS DWORD) LOCAL sText AS STRING LOCAL lClWide, lClHigh AS LONG LOCAL lspx, lspy AS LONG DIALOG GET CLIENT hDlg TO lClWide, lClHigh lspx=lClWide-SplitBar.BorderLeft-SplitBar.BorderRight lspy=lClHigh - SplitBar.BorderTop-SplitBar.BorderBtm IF SplitBar.Mode="HORZ" THEN STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 4, 0, _ FORMAT$(SplitBar.Left-SplitBar.BorderLeft) ELSE 'SplitBar.Mode ="VERT" STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 4, 0, _ FORMAT$(SplitBar.Top-SplitBar.BorderBtm) END IF sText= IIF$( SplitBar.Continuous ,"CONT","NORM") STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 2, 0, SplitBar.Mode STATUSBAR SET TEXT hDlg, %STAT_STATUSBAR, 3, 0, sText sText= FORMAT$(SplitBar.Proportion,"0.0%") STATUSBAR SET TEXT hDlg,%STAT_STATUSBAR,5,0, sText END SUB '----------------------------------------------------------------------------------