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

Cheezy Splitter Bar

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

  • Cheezy Splitter Bar

    There's a lot of fine examples here which demonstrate splitter bars of various sorts, and a search did not reveal one quite like this one. Full working example, the splitter bar handler stuff is at the bottom. This is a little different because it uses a custom window class to handle the movement of the splitter bar indication, in this case, a focus rectangle. Converting this to a live update is not that much more of an effort either, just uncomment the PostMessage in the %WM_MOUSEMOVE. I think it's cheezy because I'm using the DrawFocusRect in a "non-live" mode to indicate the location of the splitter bar.
    Code:
    #PBFORMS CREATED V1.51
    '------------------------------------------------------------------------------
    ' The first line in this file is a PB/Forms metastatement.
    ' It should ALWAYS be the first line of the file. Other
    ' PB/Forms metastatements are placed at the beginning and
    ' end of "Named Blocks" of code that should be edited
    ' with PBForms only. Do not manually edit or delete these
    ' metastatements or PB/Forms will not be able to reread
    ' the file correctly.  See the PB/Forms documentation for
    ' more information.
    ' Named blocks begin like this:    #PBFORMS BEGIN ...
    ' Named blocks end like this:      #PBFORMS END ...
    ' Other PB/Forms metastatements such as:
    '     #PBFORMS DECLARATIONS
    ' are used by PB/Forms to insert additional code.
    ' Feel free to make changes anywhere else in the file.
    '------------------------------------------------------------------------------
    
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES
    %USEMACROS = 1
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #IF NOT %DEF(%COMMCTRL_INC)
        #INCLUDE "COMMCTRL.INC"
    #ENDIF
    #INCLUDE "PBForms.INC"
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS
    %IDD_CHEEZYSPLITTER =  101
    
    %IDR_MENU1          =  102
    %IDR_ACCELERATOR1   =  103
    
    %IDM_FILE_EXIT      =  104
    %IDM_EDIT_NOTHING   =  105
    
    %IDT_TEXTBOXLEFT    = 1001
    %IDT_TEXTBOXRIGHT   = 1002
    %IDSB_STATUS        = 1003
    %IDCC_SPLITTER      = 1004
    #PBFORMS END CONSTANTS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** User Constants **
    '------------------------------------------------------------------------------
    %SPLITPOINT         = 0
    %SPLITLEFT          = 4
    %SPLITRIGHT         = 8
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE FUNCTION AttachMENU1(BYVAL hDlg AS DWORD) AS DWORD
    DECLARE FUNCTION ASSIGNACCEL(tAccel AS ACCELAPI, BYVAL wKey AS WORD, BYVAL _
        wCmd AS WORD, BYVAL byFVirt AS BYTE) AS LONG
    DECLARE FUNCTION AttachACCELERATOR1(BYVAL hDlg AS DWORD) AS DWORD
    DECLARE CALLBACK FUNCTION ShowCHEEZYSPLITTERProc()
    DECLARE FUNCTION ShowCHEEZYSPLITTER(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        IF ISFALSE RegisterSplitterWindow(GetModuleHandle("")) THEN
            MSGBOX "Failed to register the Splitter Bar Class"
        ELSE
            PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR _
                %ICC_INTERNET_CLASSES)
            ShowCHEEZYSPLITTER %HWND_DESKTOP
        END IF
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Menus **
    '------------------------------------------------------------------------------
    FUNCTION AttachMENU1(BYVAL hDlg AS DWORD) AS DWORD
    #PBFORMS BEGIN MENU %IDR_MENU1->%IDD_CHEEZYSPLITTER
        LOCAL hMenu   AS DWORD
        LOCAL hPopUp1 AS DWORD
    
        MENU NEW BAR TO hMenu
        MENU NEW POPUP TO hPopUp1
        MENU ADD POPUP, hMenu, "File", hPopUp1, %MF_ENABLED
            MENU ADD STRING, hPopUp1, "E&xit" + $TAB + "Alt+F4", %IDM_FILE_EXIT, _
                %MF_ENABLED
        MENU NEW POPUP TO hPopUp1
        MENU ADD POPUP, hMenu, "Edit", hPopUp1, %MF_ENABLED
            MENU ADD STRING, hPopUp1, "Nothing", %IDM_EDIT_NOTHING, %MF_ENABLED
    
        MENU ATTACH hMenu, hDlg
    #PBFORMS END MENU
        FUNCTION = hMenu
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Accelerators **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN ASSIGNACCEL
    FUNCTION ASSIGNACCEL(tAccel AS ACCELAPI, BYVAL wKey AS WORD, BYVAL wCmd AS _
        WORD, BYVAL byFVirt AS BYTE) AS LONG
        tAccel.fVirt = byFVirt
        tAccel.key   = wKey
        tAccel.cmd   = wCmd
    END FUNCTION
    #PBFORMS END ASSIGNACCEL
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    FUNCTION AttachACCELERATOR1(BYVAL hDlg AS DWORD) AS DWORD
    #PBFORMS BEGIN ACCEL %IDR_ACCELERATOR1->%IDD_CHEEZYSPLITTER
        LOCAL hAccel   AS DWORD
        LOCAL tAccel() AS ACCELAPI
        DIM   tAccel(1 TO 1) AS ACCELAPI
    
        ASSIGNACCEL tAccel(1), %VK_F4, %IDM_FILE_EXIT, %FVIRTKEY OR %FALT OR _
            %FNOINVERT
    
        ACCEL ATTACH hDlg, tAccel() TO hAccel
    #PBFORMS END ACCEL
        FUNCTION = hAccel
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowCHEEZYSPLITTERProc()
    LOCAL FormX, FormY, FrameX, StatusX, StatusY    AS DWORD
    LOCAL SplitPoint                                AS LONG
    LOCAL hSplitter                                 AS DWORD
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                ' Initialization handler
    
            CASE %WM_SIZE
                ' Dialog has been resized
                CONTROL SEND CBHNDL, %IDSB_STATUS, CBMSG, CBWPARAM, CBLPARAM
                DIALOG GET CLIENT CB.HNDL TO FormX, FormY
                CONTROL HANDLE CB.HNDL, %IDCC_SPLITTER TO hSplitter
                ' the SplitPoint is stored as a PERCENTAGE
                SplitPoint = GetWindowLong(hSplitter, %SPLITPOINT)
                ' note setting limits in PIXELS
                SetWindowLong hSplitter, %SPLITLEFT, ((FormX / 100) * 20)
                SetWindowLong hSplitter, %SPLITRIGHT, ((FormX / 100) * 80)
                FrameX = ((FormX / 100) * SplitPoint) - 2
                CONTROL GET SIZE CB.HNDL, %IDSB_STATUS TO StatusX, StatusY
                FormY = FormY - StatusY
                CONTROL SET LOC CB.HNDL, %IDT_TEXTBOXLEFT, 0, 0
                CONTROL SET SIZE CB.HNDL, %IDT_TEXTBOXLEFT, FrameX, FormY
                CONTROL SET LOC CB.HNDL, %IDCC_SPLITTER, FrameX, 0
                CONTROL SET SIZE CB.HNDL, %IDCC_SPLITTER, 4, FormY
                FrameX = FrameX + 4
                FormX = FormX - FrameX
                CONTROL SET LOC CB.HNDL, %IDT_TEXTBOXRIGHT, FrameX, 0
                CONTROL SET SIZE CB.HNDL, %IDT_TEXTBOXRIGHT, FormX, FormY
    
    
            CASE %WM_MENUSELECT
                ' Update the status bar text
                STATIC szMenuPrompt AS ASCIIZ * %MAX_PATH
                IF ISFALSE LoadString(GetModuleHandle(BYVAL 0&), CBCTL, _
                    szMenuPrompt, SIZEOF(szMenuPrompt)) THEN
                    szMenuPrompt = "Please choose from the menus above..."
                END IF
                CONTROL SEND CBHNDL, %IDSB_STATUS, %SB_SETTEXT, 0, _
                    VARPTR(szMenuPrompt)
                FUNCTION = 1
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    ' Save control focus
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    ' Restore control focus
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
            CASE %WM_COMMAND
                ' Process control notifications
                SELECT CASE AS LONG CBCTL
                    CASE %IDM_FILE_EXIT
                        DIALOG END CB.HNDL
    
                    CASE %IDM_EDIT_NOTHING
                        MSGBOX "%IDM_EDIT_NOTHING=" + FORMAT$(%IDM_EDIT_NOTHING), _
                            %MB_TASKMODAL
    
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowCHEEZYSPLITTER(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_CHEEZYSPLITTER->%IDR_MENU1->%IDR_ACCELERATOR1
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW PIXELS, hParent, "Cheezy Splitter", _
            %CW_USEDEFAULT, %CW_USEDEFAULT, 400, 300, _
            %WS_POPUP OR %WS_BORDER OR %WS_THICKFRAME OR %WS_CAPTION _
            OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX _
            OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN 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
        CONTROL ADD TEXTBOX, hDlg, %IDT_TEXTBOXLEFT, "Text Box Left", _
            8, 16, 60, 72, _
            %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_HSCROLL OR _
            %WS_VSCROLL OR %ES_LEFT OR %ES_MULTILINE OR %ES_AUTOHSCROLL, _
            %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR
        CONTROL ADD TEXTBOX, hDlg, %IDT_TEXTBOXRIGHT, "Text Box Right", _
            124, 16, 56, 72, _
            %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_HSCROLL OR _
            %WS_VSCROLL OR %ES_LEFT OR %ES_MULTILINE OR %ES_AUTOHSCROLL, _
            %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR
        CONTROL ADD "SPLITTERBAR", hDlg, %IDCC_SPLITTER, "Splitter", _
            76, 16, 36, 72, _
            %WS_CHILD OR %WS_VISIBLE, _
            %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
        CONTROL ADD STATUSBAR, hDlg, %IDSB_STATUS, "Status", _
            0, 109, 201, 12, _
            %WS_CHILD OR %WS_VISIBLE, %WS_EX_TRANSPARENT OR %WS_EX_LEFT _
            OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    
        AttachMENU1 hDlg
    
        AttachACCELERATOR1 hDlg
    #PBFORMS END DIALOG
    
        DIALOG SHOW MODAL hDlg, CALL ShowCHEEZYSPLITTERProc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_CHEEZYSPLITTER
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    ' ** register my splitterbar class
    '------------------------------------------------------------------------------
    FUNCTION RegisterSplitterWindow(hInstance AS DWORD) AS LONG
    LOCAL wc                AS WndClassEx
    LOCAL szClassName       AS ASCIIZ * 80
    
        szClassName = "SPLITTERBAR"
    
        wc.cbSize        = SIZEOF(wc)
        wc.cbClsExtra    = 0
        wc.cbWndExtra    = 12
        wc.hbrBackground = GetStockObject(%BLACK_BRUSH)
        wc.hCursor       = LoadCursor(%NULL, BYVAL %IDC_SIZEWE)
        wc.hIcon         = 0
        wc.hIconSm       = 0
        wc.hInstance     = GetModuleHandle("")
        wc.lpfnWndProc   = CODEPTR(SplitterBarProc)
        wc.lpszClassName = VARPTR(szClassName)
        wc.lpszMenuName  = %NULL
        wc.style         = 0 ' %CS_HREDRAW OR %CS_VREDRAW
    
        RegisterSplitterWindow = RegisterClassEx(wc)
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    ' ** cheezy splitter bar window procedure
    '------------------------------------------------------------------------------
    FUNCTION SplitterBarProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
                      BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
    LOCAL winPlace              AS WINDOWPLACEMENT
    LOCAL winDC, pWnd, sPoint   AS DWORD
    LOCAL mRect                 AS RECT
    ' the offsets and rectangle need to be statics
    STATIC winRect              AS RECT
    STATIC winOffsets           AS POINTAPI
    
        SELECT CASE wMsg
            CASE %WM_CREATE
                ' note the SplitPoint is a PERCENTAGE
                SetWindowLong hWnd, %SPLITPOINT, 50
            CASE %WM_MOUSEMOVE
                IF (wParam AND %MK_LBUTTON) = %MK_LBUTTON THEN
                    ' get the parent information and clear the prior focus rectangle
                    pWnd = GetParent(hWnd)
                    winDC = GetWindowDC(pWnd)
                    DrawFocusRect winDC, winRect
                    ' get our position
                    winPlace.Length = SIZEOF(winPlace)
                    GetWindowPlacement hWnd, winPlace
                    ' do calculations to the new position of the splitter
                    mRect = winPlace.rcNormalPosition
                    OffsetRect mRect, LO(INTEGER, lParam), 0
                    ' note that the main resize sets these as PIXELS
                    IF (mRect.nLeft > GetWindowLong(hWnd, %SPLITLEFT)) _
                        AND (mRect.nLeft < GetWindowLong(hWnd, %SPLITRIGHT)) THEN
                            winRect = mRect
                            OffsetRect winRect, winOffsets.x, winOffsets.y
                            GetClientRect pWnd, mRect
                            ' winPlace.rcNormalPosition.nLeft contains upper left of splitter
                            sPoint = winPlace.rcNormalPosition.nLeft + LO(INTEGER, lParam)
                            ' sPoint now is relative to original position
                            sPoint = CSNG(sPoint / mRect.nRight) * 100
                            SetWindowLong hWnd, %SPLITPOINT, sPoint
                    END IF
                    DrawFocusRect winDC, winRect
                    ReleaseDC pWnd, winDC
                    ' PostMessage pWnd, %WM_SIZE, 0, 0
                END IF
            CASE %WM_LBUTTONDOWN
                ' cheat, clear the original offsets
                winOffsets = winPlace.ptMinPosition
                ' get the location of the splitter in the parents client area
                winPlace.Length = SIZEOF(winPlace)
                GetWindowPlacement hWnd, winPlace
                winRect = winPlace.rcNormalPosition
                ' have our position, get the parent's position on the screen
                pWnd = GetParent(hWnd)
                GetWindowRect pWnd, mRect
                ' this converts the clients' upper left corner into a screen position
                ClientToScreen pWnd, winOffsets
                ' do the math to adjust from window upper left to client upper left
                winOffsets.x = winOffsets.x - mRect.nLeft
                winOffsets.y = winOffsets.y - mRect.nTop
                OffsetRect winRect, winOffsets.x, winOffsets.y
                ' note we are getting the WINDOW DC, not the CLIENT DC
                winDC = GetWindowDC(pWnd)
                DrawFocusRect winDC, winRect
                ReleaseDC pWnd, winDC
                ' and capture the mouse
                SetCapture hWnd
            CASE %WM_LBUTTONUP
                ' clear the focus rectangle and inform parent that we're done
                pWnd = GetParent(hWnd)
                winDC = GetWindowDC(pWnd)
                DrawFocusRect winDC, winRect
                ReleaseDC pWnd, winDC
                ReleaseCapture
                PostMessage pWnd, %WM_SIZE, 0, 0
        END SELECT
    
        SplitterBarProc = DefWindowProc(hWnd, wMsg, wParam, lParam)
    END FUNCTION
    '------------------------------------------------------------------------------
    Attached Files
    Last edited by colin glenn; 6 Mar 2009, 08:51 AM. Reason: Added a zip
    Furcadia, an interesting online MMORPG in which you can create and program your own content.

  • #2
    Footnote:

    Program generated and compiled with PB9 and PBForms, hence, one thing that probably won't work in versions that don't support it is:
    IF ISFALSE RegisterSplitterWindow(GetModuleHandle("")) THEN
    Due to using new ISFALSE construct.

    Use:
    IF RegisterSplitterWindow(GetModuleHandle("")) = 0 THEN
    And it will work just as well.

    Also, you can probably comment out the lines which are PBForms specific:

    The:
    #INCLUDE "PBForms.INC"
    In the #PBFORMS BEGIN INCLUDES, and the:
    PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR _
    %ICC_INTERNET_CLASSES)

    In the FUNCTION PBMAIN(),
    And the program will compile just fine.
    Furcadia, an interesting online MMORPG in which you can create and program your own content.

    Comment

    Working...
    X