Bay Six Software Forum Index Bay Six Software
Beyond the Basics
 
 FAQFAQ   SearchSearch   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Demos - More / Less dialog
 
More / Less dialog
LessMore
No descriptionNo description

Code:
'**********************************************************************
' More/Less Demo
' By Brent D. Thorn, 7/2006
' PUBLIC DOMAIN
'**********************************************************************

'    NoMainWin

    If Val(Version$) < 4 Then
        Notice "Code  requires LB 4.0 or later."
        End
    End If

    Global g.hInst

    CallDLL #kernel32, "GetModuleHandleA", _
        _NULL As Long, _
        g.hInst As ULong

    Call MLDemo.Open

    Call DoEvents

Sub DoEvents
  [localLoop]
    Scan
    CallDLL #kernel32, "Sleep", _
        50 As Long, _
        ret As Void
    GoTo [localLoop]
End Sub

Sub MLDemo.Open
    ' Create dialog fully expanded.
    WindowWidth = 276
    WindowHeight = 158

    ' The "Less" controls.
    ' stcIcon will display an icon.
    StaticText  #MLDemo.stcIcon, "", 10, 10, 32, 32
      StyleBits #MLDemo.stcIcon, _SS_ICON, 0, 0, 0
    StaticText  #MLDemo.stcLess, "Something happened!", 48, 10, 144, 32
    Button      #MLDemo.default, "OK", MLDemo.btnOK.Click, UL, 200, 10, 60, 25
    ' btnMorL is the toggle button.
    Button      #MLDemo.btnMorL, "Mor&e >>", MLDemo.btnMorL.Click, UL, 200, 40, 60, 25

    ' The "More" controls.
    ' Positions must be relative to the container created after opening window.
    CheckBox    #MLDemo.chkLock, "&Lock", MLDemo.chkLock.Set, MLDemo.chkLock.Reset, 200, 5, 60, 20
    ' txtMore needs to have a vert. scroll bar and be read-only.
    TextBox     #MLDemo.txtMore, 10, 5, 180, 48
      StyleBits #MLDemo.txtMore, _ES_READONLY Or _WS_VSCROLL, _ES_AUTOHSCROLL, 0, 0

    ' Center the dialog and open it hidden.
    StyleBits #MLDemo, _DS_CENTER, _WS_VISIBLE, 0, 0

    Open "More/Less Demo" For Dialog As #MLDemo

    ' Set LB event handlers.
    #MLDemo "TrapClose MLDemo.Close"

    ' Set controls' initial text or setting.
    #MLDemo.txtMore "What that something is I do not know."

    ' Get "warning" icon and show it in stcIcon.
    ret = SendMessageLong(HWnd(#MLDemo.stcIcon), _STM_SETICON, _
                          GetOEMIcon(_IDI_EXCLAMATION), 0)

    ' Set up More/Less controls and display contracted view.
    Call CreateMoreOrLess "#MLDemo", "txtMore chkLock", "Less", 0, 65, 276, 53
End Sub

Sub MLDemo.Close wnd$
    Close #wnd$

    End
End Sub

Sub MLDemo.btnMorL.Click btn$
    ' Get handle of parent window.
    wnd$ = Word$(btn$, 1, ".")

    ' Toggle More/Less state vertically.
    If ShowMoreOrLessV$(wnd$) = "More" Then
        #btn$ "Mor&e >>"
    Else
        #btn$ "L&ess <<"
    End If
End Sub

Sub MLDemo.btnOK.Click btn$
    ' Get handle of parent window.
    wnd$ = Word$(btn$, 1, ".")
    ' Explicitly call the "Close" event handler.
    Call MLDemo.Close wnd$
End Sub

Sub MLDemo.chkLock.Set chk$
    ' Get handle of parent window.
    wnd$ = Word$(chk$, 1, ".")
    ' Get handle of btnMorL button and disable it.
    btnMorL$ = wnd$ + ".btnMorL"
    #btnMorL$ "!Disable"
End Sub

Sub MLDemo.chkLock.Reset chk$
    ' Get handle of parent window.
    wnd$ = Word$(chk$, 1, ".")
    ' Get handle of btnMorL button and enable it.
    btnMorL$ = wnd$ + ".btnMorL"
    #btnMorL$ "!Enable"
End Sub

'**********************************************************************
' More/Less Management
'**********************************************************************

Sub CreateMoreOrLess Window$, CtlExts$, MoreOrLess$, X, Y, Width, Height
'-- Purpose: Helps easily implement a "More/Less" style of window. Creates a
'   container control, sets some special attributes, moves controls into con-
'   tainer, and adjusts the window's dimensions.
'-- Parameters:
'   - Window$:  a handle to the parent window
'   - CtlExts$:  a space-separated list of control extensions without leading
'       dots (e.g. control #wnd.ext would be listed as "ext")
'   - MoreOrLess$:  a string, either "More" or "Less" to indicate the desired
'       initial state, expanded or collapsed, respectively.
'   - X, Y:  the position where the container is created. If X is less than or
'       equal to Y, the window will expand vertically. If Y is less than X, then
'       the window will expand horizontally.
'   - Width, Height:  the size of the container
'-- Dependencies:
'   - Subs: GetClientSize, GetWindowRect, SetControlsParent, SetWindowPos,
'           ShowWindow
'-- Note #1: The parent window must be opened with its WindowWidth and Window-
'   Height the same as its fully expanded view.
'-- Note #2: The parent window should be hidden before opening by removing the
'   _WS_VISIBLE style bit.

    hWindow = HWnd(#Window$)

    ' Create the "More" container hidden.
    hCon = CreateContainer(0, 0, X, Y, Width, Height, hWindow, g.hInst, 0)

    ' Set container's text so it can be found easily. This text will not show
    ' on-screen.
    CallDLL #user32, "SetWindowTextA", hCon As ULong, "MoreContainer" As Ptr, _
        ret As Long

    ' Have container "adopt" controls.
    Call SetControlsParent Window$, CtlExts$, hCon

    ' Set up the desire initial view.
    If Lower$(MoreOrLess$) = "less" Then
        ' Get outside dimensions.
        Call GetWindowRect hWindow

        If X <= Y Then
            ' Expands/contracts vertically. Save width.
            cx = WindowRect.right.struct - WindowRect.left.struct + 1

            ' Compute new height minus container.
            Call GetClientSize hCon, 0, cy
            cy = WindowRect.bottom.struct - WindowRect.top.struct - cy
        Else
            ' Expands/contracts horizontally. Save height.
            cy = WindowRect.bottom.struct - WindowRect.top.struct + 1

            ' Compute new width minus container.
            Call GetClientSize hCon, cx, 0
            cx = WindowRect.right.struct - WindowRect.left.struct - cx
        End If

        ' Adjust outside dimensions and show the window.
        Call SetWindowPos hWindow, _NULL, 0, 0, cx, cy, _
                          _SWP_SHOWWINDOW Or _SWP_NOZORDER Or _SWP_NOMOVE
    Else
        ' If it isn't "less," assume it's "more." Just show container & window.
        Call ShowWindow hCon, _SW_SHOW
        Call ShowWindow hWindow, _SW_SHOW
    End If
End Sub

Function ShowMoreOrLessV$( Window$ )
'-- Purpose:  Toggles a More/Less window between expanded or contracted views
'   in the VERTICAL orientation.
'-- Returns:  Usually a suggestion  for the text  for the toggle control (usually
'   a button).
'   - "More":  Window is contracted.
'   - "Less":  Window is expanded.
'   - "Error":  An error occurred. Usually happens when CreateMoreOrLess has not
'       been previously called.
'-- Dependencies:
'   - Subs: CreateMoreOrLess, GetClientSize, GetWindowRect, ShowWindow

    hWindow = HWnd(#Window$)

    ' Find the "More" container.
    hCon = FindWindowEx(hWindow, _NULL, "#32770", "MoreContainer")

    If hCon = 0 Then
        ShowMoreOrLess$ = "Error"
        Exit Function
    End If

    ' Get outside dimensions of parent window.
    Call GetWindowRect HWnd(#Window$)
    cx = WindowRect.right.struct - WindowRect.left.struct + 1

    ' Get client height of container.
    Call GetClientSize hCon, 0, cy

    CallDLL #user32, "IsWindowVisible", hCon As ULong, tis As Long

    If tis Then
        ' Container  if showing, prepare to hide it.
        showCmd = _SW_HIDE

        ' Compute new outside height minus container.
        cy = WindowRect.bottom.struct - WindowRect.top.struct - cy

        ' Return suggested text  for button.
        ShowMoreOrLessV$ = "More"
    Else
        ' Container is hidden, prepare to show it.
        showCmd = _SW_SHOW

        ' Compute new outside height plus container.
        cy = WindowRect.bottom.struct - WindowRect.top.struct + cy

        ' Return suggested text  for button.
        ShowMoreOrLessV$ = "Less"
    End If

    ' Adjust outside height.
    Call SetWindowPos hWindow, _NULL, 0, 0, cx, cy, _
                      _SWP_NOZORDER Or _SWP_NOMOVE

    ' Finally show or hide container. Doing so here eliminates flicker.
    Call ShowWindow hCon, showCmd
End Function

Function ShowMoreOrLessH$( Window$ )
'-- Purpose:  Toggles a More/Less window between expanded or contracted views
'   in the HORIZONTAL orientation.
'-- Returns:  Usually a suggestion  for the text  for the toggle control (usually
'   a button).
'   - "More":  Window is contracted.
'   - "Less":  Window is expanded.
'   - "Error":  An error occurred. Usually happens when CreateMoreOrLess has not
'       been previously called.
'-- Dependencies:
'   - Subs: CreateMoreOrLess, GetClientSize, GetWindowRect, ShowWindow

    hWindow = HWnd(#Window$)

    ' Find the "More" container.
    hCon = FindWindowEx(hWindow, _NULL, "#32770", "MoreContainer")

    If hCon = 0 Then
        Print "ERROR! ShowMoreOrLessH$ cannot find container control."
        Exit Function
    End If

    ' Get outside dimensions of parent window.
    Call GetWindowRect hWindow
    cy = WindowRect.bottom.struct - WindowRect.top.struct + 1

    ' Get client width of container.
    Call GetClientSize hCon, cx, 0

    CallDLL #user32, "IsWindowVisible", hCon As ULong, tis As Long

    If tis Then
        ' Container  if showing, prepare to hide it.
        showCmd = _SW_HIDE

        ' Compute new outside width minus container.
        cx = WindowRect.right.struct - WindowRect.left.struct - cx

        ' Return suggested text  for button.
        ShowMoreOrLessH$ = "More"
    Else
        ' Container is hidden, prepare to show it.
        showCmd = _SW_SHOW

        ' Compute new outside width plus container.
        cx = WindowRect.right.struct - WindowRect.left.struct + cx

        ' Return suggested text  for button.
        ShowMoreOrLessH$ = "Less"
    End If

    ' Adjust outside width.
    Call SetWindowPos hWindow, _NULL, 0, 0, cx, cy, _
                      _SWP_NOZORDER Or _SWP_NOMOVE

    ' Finally show or hide container. Doing so here eliminates flicker.
    Call ShowWindow hCon, showCmd
End Function

'**********************************************************************
' Container Management
'**********************************************************************

Function CreateContainer( ExStyle, Style, X, Y, Width, Height, hParent, hInstance, lParam )
'-- Purpose:  Creates a child dialog box  for use as a container object  for con-
'   trols. Controls must be "adopted" by the container using the SetParent API.
'-- Returns:  Window handle (HWND) of the newly created container.
'-- Dependencies:
'   - Functions:  ContainerProc, GetClassName$, HIWORD, LOWORD, MulDiv

    If Left$(GetClassName$(hParent), 1) <> "#" Then
        ' Get dialog base units.
        ' They're used to convert pixels to dialog units.
        CallDLL #user32, "GetDialogBaseUnits", _
            base As ULong
        baseX = LOWORD(base)
        baseY = HIWORD(base)
    Else
        baseX = 4
        baseY = 8
    End If

    ' Initialize dialog template struct.
    Struct DLGTEMPLATE, _
        style As ULong, _
        dwExtendedStyle As ULong, _
        cdit As Word, _
        x As Short, _
        y As Short, _
        cx As Short, _
        cy As Short, _
        menus As Word, _ 'pseudo element
        class As Word, _ 'pseudo element
        title As Word    'pseudo element

    DLGTEMPLATE.style.struct = Style Or _WS_CHILDWINDOW Or _DS_CONTROL
    DLGTEMPLATE.dwExtendedStyle.struct = ExStyle Or _WS_EX_CONTROLPARENT
    DLGTEMPLATE.cdit.struct = 0
    DLGTEMPLATE.x.struct = MulDiv(X, 4, baseX)
    DLGTEMPLATE.y.struct = MulDiv(Y, 4, baseY)
    DLGTEMPLATE.cx.struct = MulDiv(Width, 4, baseX)
    DLGTEMPLATE.cy.struct = MulDiv(Height, 4, baseY)
    DLGTEMPLATE.menus.struct = 0
    DLGTEMPLATE.class.struct = 0
    DLGTEMPLATE.title.struct = 0

    ' Template must be in global memory space.
    cbDT = Len(DLGTEMPLATE.struct)
    CallDLL #kernel32, "GlobalAlloc", _
        _GMEM_MOVEABLE As ULong, _
        cbDT As ULong, _
        hDT As ULong
    CallDLL #kernel32, "GlobalLock", _
        hDT As ULong, _
        pDT As ULong

    ' Copy struct to global memory.
    CallDLL #kernel32, "RtlMoveMemory", _
        pDT As ULong, _
        DLGTEMPLATE As Struct, _
        cbDT As Long, _
        ret As Void

    ' Get pointer to ContainerProc().
    Callback lpDlgProc, ContainerProc( ULong, ULong, ULong, ULong ), ULong

    ' Create the modeless, child dialog box.
    CallDLL #user32, "CreateDialogIndirectParamA", _
        hInstance As Long, _
        pDT As ULong, _
        hParent As ULong, _
        lpDlgProc As ULong, _
        lParam As Long, _
        hDlg As ULong

    ' Memory is no longer needed. Let's clean up.
    CallDLL #kernel32, "GlobalUnlock", _
        hDT As ULong, _
        ret As Long
    CallDLL #kernel32, "GlobalFree", _
        hDT As ULong, _
        ret As ULong

    ' Return dialog's window handle.
    CreateContainer = hDlg
End Function

Function ContainerProc( hDlg, uMsg, wParam, lParam )
'-- Purpose:  Acts as container dialog box's dialog procedure. Forwards WM_COM-
'   MAND and WM_NOTIFY messages to the container's parent window.

    Select Case uMsg
    Case _WM_COMMAND, _WM_NOTIFY
print "ContainerProc"
        CallDLL #user32, "GetParent", hDlg As ULong, hParent As Ulong
        CallDLL #user32, "SendMessageA", hParent As ULong,_
        uMsg As ULong, wParam As ULong, lParam As ULong, r As Long
    End Select
End Function

'***********************************************
' Support Procedures
'***********************************************

Sub SetControlsParent OldParent$, CtlExts$, hWndNewParent
'-- Dependencies:
'   - Functions: GetParent
'   - Subs: SetParent

    On Error GoTo [Bad_Handle_Error]

    c = 0
    GoSub [Get_Next_Ctl]

    Do While Len(ext$)
        Call SetParent HWnd(#ctl$), hWndNewParent
        GoSub [Get_Next_Ctl]
    Loop

    Exit Sub
[Get_Next_Ctl]
    c = c + 1
    ext$ = Word$(CtlExts$, c)
    ctl$ = OldParent$ + "." + ext$
    Return
[Bad_Handle_Error]
    hWnd = Int(Val(ext$))
    CallDLL #user32, "IsWindow", hWnd As ULong, tis As Long
    If tis Then
        If GetParent(hWnd) = HWnd(#OldParent$) Then
            Call SetParent hWnd, hWndNewParent
        End If
    End If
    GoSub [Get_Next_Ctl]
    Resume
End Sub

Function HIWORD( dw )
    HIWORD = (dw And 4294901760) / 65536
End Function

Function LOWORD( dw )
    LOWORD = (dw And 65535)
End Function

Function MulDiv( Factor, Numer, Denom )
    CallDLL #kernel32, "MulDiv", Factor As Long, Numer As Long, Denom As Long, _
        MulDiv As Long
End Function

Sub SetWindowPos hWnd, hWndAfter, X, Y, Width, Height, Flags
    CallDLL #user32, "SetWindowPos", hWnd As ULong, hWndAfter As ULong, _
        X As Long, Y As Long, Width As Long, Height As Long, Flags As ULong, _
        ret As Long
End Sub

Sub SetParent hWnd, hWndNewParent
    CallDLL #user32, "SetParent", hWnd As ULong, hWndNewParent As ULong, _
        ret As ULong
End Sub

Function GetOEMIcon( IDI )
    CallDLL #user32, "LoadIconA", _NULL As Long, IDI As ULong, _
        GetOEMIcon As ULong
End Function

Function SendMessageLong( hWnd, uMsg, wParam, lParam )
    CallDLL #user32, "SendMessageA", hWnd As ULong, uMsg As ULong, _
        wParam As ULong, lParam As Long, SendMessageLong As Long
End Function

Sub GetClientSize hWnd, ByRef Width, ByRef Height
    Struct ClientSize, left As Long, top As Long, width As Long, height As Long
    CallDLL #user32, "GetClientRect", hWnd As ULong, ClientSize As Struct, _
        ret As Long
    Width = ClientSize.width.struct
    Height = ClientSize.height.struct
End Sub

Sub GetWindowRect hWnd
    Struct WindowRect, left As Long, top As Long, right As Long, bottom As Long
    CallDLL #user32, "GetWindowRect", hWnd As ULong, WindowRect As Struct, _
        ret As Long
End Sub

Function FindWindowEx( hWndParent, hWndFirstChild, Class$, Text$ )
    CallDLL #user32, "FindWindowExA", hWndParent As ULong, _
        hWndFirstChild As ULong, Class$ As Ptr, Text$ As Ptr, _
        FindWindowEx As ULong
End Function

Function GetParent( hWnd )
    CallDLL #user32, "GetParent", hWnd As ULong, GetParent As ULong
End Function

Function GetClassName$( hWnd )
    buf$ = Space$(256)
    CallDLL #user32, "GetClassNameA", hWnd As ULong, buf$ As Ptr, 255 As Long, _
        cch As Long
    GetClassName$ = Left$(buf$, cch)
End Function

Sub ShowWindow hWnd, nCmdShow
    CallDLL #user32, "ShowWindow", hWnd As ULong, nCmdShow As Long, ret As Long
End Sub

Powered by phpBB © 2001, 2005 phpBB Group