Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

A Toggling SplitterBar DDT Style

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • A Toggling SplitterBar DDT Style

    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.
    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
    '-----------------------------------------------------------------------------------
    A test program of the SplitterBar and new Statusbar:
    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
    '----------------------------------------------------------------------------------
    Any comments and suggestions would be appreciated in the PB for Windows Forum!
Working...
X