Older Version Newer Version

JanetTerra JanetTerra Sep 13, 2015

===Reviewing the Stylebits Parameters=== 

The four parameters of stylebits are AddBit, RemoveBit, AddExtendedBit, RemoveExtendedBit. For a review of these four parameters, and an introduction to Stylebits in general, please view [[Stylebits - Windows]].

===Why a Dialog Window?=== 

There are several reasons you might want to use a dialog window in your program. A common reason is the default button. Without stylebits, only dialog windows are capable of default buttons. From the Liberty BASIC help file:

//A window of type DIALOG can contain a button with the extension ".default". If the user presses the ENTER key while the dialog window has focus, it is the same as if the button whose extension is "default" is pressed and program execution will continue at the event handler [branchLabel] for that button.// 

The following code is a simple program illustrating the default button.
[[code format="vb"]]
    Statictext #dlg.txt, "Press Okay to close this window.", 20, 50, 100, 20
    Button #dlg.default, " Okay ", [OkayButton], UL, 140, 100
    Open "Default Button" for Dialog as #dlg
    Wait

[OkayButton]
    Close #dlg
    End
[[code]]
===The Choice: A Default Button or a Menu=== 

Unfortunately, dialog windows do not support menus. For a long time, Liberty BASIC programmers have had to choose between a default button and a menu. Recently, Brent Thorn posted code using Stylebits that will allow a default button in a regular window. So, while you still can't program a menu in a dialog window, you can code a default button in a regular window. This means a default button AND a menu in the same window. Thanks, Brent! One peculiarity I did discover was that one of the window controls needs to be given focus prior to the activation of the default button. A simple Setfocus to a textbox (any textbox) will accomplish that. Here is a modification of Brent's code.
[[code format="vb"]]
'Using a Dialog Default Button in a Regular Window
'Thanks to Brent Thorn
' http://libertybasic.conforums.com/index.cgi?board=novice&action=display&num=1134254812
'Modifications by Janet = Menu and Setfocus to #main.tbx1

    WindowWidth = 300
    WindowHeight = 350
    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)

    Menu #main, "&Options", "E&xit", EndDemoMenu
    Textbox #main.tbx1, 150, 50, 120, 30
    Textbox #main.tbx2, 150, 100, 120, 30
    Textbox #main.tbx3, 150, 150, 120, 30
    Textbox #main.tbx4, 150, 200, 120, 30
    Stylebits #main.default, _BS_DEFPUSHBUTTON, 0, 0, 0
    Button #main.default, "", DefaultButton, UL, -100, -100

    Open "Default Button in a Regular Window" for Window as #main
    #main "Trapclose EndDemo"
    #main.tbx1 "!Setfocus"

    Wait

    Sub DefaultButton handle$
        #main.tbx1 "!Contents? text1$"
        #main.tbx2 "!Contents? text2$"
        #main.tbx3 "!Contents? text3$"
        #main.tbx4 "!Contents? text4$"
        Notice "The textboxes read";Chr$(13);Chr$(13) + _
            text1$;Chr$(13);text2$;Chr$(13);text3$;Chr$(13);text4$
    End Sub

    Sub EndDemoMenu
        Call EndDemo "#main"
    End Sub

    Sub EndDemo handle$
        Close #main
        End
    End Sub
[[code]]
[[#StylebitsTextbox]]
===An Improved Stylebits Textbox=== 
Since the release of Liberty BASIC 4.0 and stylebits, multilines and wordwrapping have been accomplished in textboxes using the sequence _WS_VSCROLL OR _ES_MULTILINE, _ES_AUTOHSCROLL, 0, 0. [[Stylebits - Textboxes]] discusses such a textbox. While the text does, indeed, wrap, the user must resort to CTRL - Enter to force a line feed. Using a hidden button with the stylebit _BS_DEFPUSHBUTTON allows the program to retrieve the contents of the textbox, append Chr$(13);Chr$(10) to the text, then rewrite that text to the textbox. Now the textbox behaves just like any other word processing tool. As is common with so many of the Stylebits tricks, an API call is required to add the final polish. With native Liberty BASIC code, the cursor is placed in front of any text that's been printed in a textbox. The API call "SendMessageA" can be used to position the cursor at the end of the text instead. This cursor position makes keyboarding a more natural and fluent activity.
[[code format="vb"]]
    Nomainwin

    WindowWidth = 400
    WindowHeight = 300

    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)

' Add a Textbox with Word Wrapping Capability
    Stylebits #main.tbx, _WS_VSCROLL OR _ES_MULTILINE, _ES_AUTOHSCROLL, 0, 0
    Textbox #main.tbx, 20, 20, 150, 200

' Add a Hidden Default Button - Use Stylebits Addbits _BS_DEFPUSHBUTTON
    Stylebits #main.btn, _BS_DEFPUSHBUTTON, 0, 0, 0
    Button #main.btn, "", DefaultButton, UL, -10, -10

    Open "Main Window" for Window as #main
    #main "Trapclose EndDemo"
    #main "Font Verdana 10 Bold"
    #main.tbx "!Setfocus"

    Wait

    Sub EndDemo handle$
        Close #main
        End
    End Sub

    Sub DefaultButton handle$
        hTextbox = hWnd(#main.tbx)
        #main.tbx "!Contents? text$"
        text$ = text$;Chr$(13);Chr$(10)
        #main.tbx text$
        pos = Len(text$)
        CallDLL #user32, "SendMessageA", _
            hTextbox as Ulong, _
            _EM_SETSEL as Long, _
            pos as Long, _
            pos as Long, _
            result as Long
    End Sub
[[code]]
//If you desire or need a truly editable textbox that mimics a text editor, use Alyce Watson's free API Text Editor available at [[http://www.alycesrestaurant.com|Alyce's Restaurant]].// 

===Resizing a Dialog Window=== 

The borders of a native dialog Window (default style = _WS_DLGFRAME) cannot be resized by the user. Neither can the dialog window be maximized or minimized.
[[code format="vb"]]
    Nomainwin
    WindowWidth = 300
    WindowHeight = 350
    Open "Testing" for Dialog as #dlg
    #dlg "Trapclose CloseDlg"

    Wait

    Sub CloseDlg handle$
        Close #dlg
        End
    End Sub
[[code]]
In a regular window, you can use _WS_MAXIMIZEBOX or _WS_MINIMIZEBOX in RemoveBits to remove the Maximize and Minimize Controls. In a dialog window, place one or both of these stylebits in the AddBits. To allow border resizing, add the stylebit _WS_THICKFRAME
[[code format="vb"]]
'Demo illustrating a Dialog Window with Resizable Edges

    Nomainwin

    WindowWidth = 800
    WindowHeight = 600

    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)

    Button #main.b1, "  Normal Dialog Window  ", DialogWin1, UL, 320, 250
    Button #main.b2, " Stylebits Dialog Window ", DialogWin2, UL, 320, 300

    Open "Main Window" for Window as #main
    #main "Trapclose EndDemo"
    Wait

    Sub EndDemo handle$
        Close #main
        End
        End Sub

    Sub DialogWin1 handle$
        WindowWidth = 400
        WindowHeight = 300
        Stylebits #dlg, 0, 0, 0, 0
        Button #dlg.default, " Close ", CloseDlg, UL, 180, 200
        Open "Dialog Window" for Dialog_Modal as #dlg
        #dlg "Trapclose CloseDlg"
        End Sub

    Sub DialogWin2 handle$
        WindowWidth = 400
        WindowHeight = 300
        Stylebits #dlg, _WS_THICKFRAME or _DS_CENTER or _WS_MAXIMIZEBOX or _WS_MINIMIZEBOX, 0, 0, 0
        Button #dlg.default, " Close ", CloseDlg, UL, 180, 200
        Open "Dialog Window" for Dialog_Modal as #dlg
        #dlg "Trapclose CloseDlg"
        End Sub

    Sub CloseDlg handle$
        Close #dlg
        End Sub
[[code]]
Don't expect to be able to issue a resizehandler control to this modified dialog window, though. The resizehandler command wasn't designed to work with a dialog window, not even a 'stylebitized' dialog window.

===Positioning a Dialog Window=== 
A dialog window can easily be centered using the Stylebit _DS_CENTER. See Tip Corner - Center a Dialog with Stylebits by Alyce Watson in the Liberty BASIC Newsletter Issue #128. This centering is in relationship to the screen (monitor) display. By default, dialog windows position themselves according to the client (calling window) area. In the following demo, move the main window (#main) around the screen prior to opening the dialog window. The dialog window will always position itself according to the position of the main window.
[[code format="vb"]]
    Nomainwin
    WindowWidth = 600
    WindowHeight = 400

    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)

    Button #main.dlg, "Native Dialog", dlg, UL, 220, 200, 140, 30

    Open "Stylebits and Dialogs" for Window as #main
    Wait

    Sub CloseMain handle$
        Close #main
        End
    End Sub

    Sub CloseDlg handle$
        Close #handle$
    End Sub

    Sub dlg handle$
        WindowWidth = 300
        WindowHeight = 250

        UpperLeftX = 20 'UpperLeftX 20 pixels to right of #main upper left corner
        UpperLeftY = 20 'UpperLeftY 20 pixels down from #main upper left corner

        text$ = "UpperLeftX and UpperLeftY are, by default, based upon the client "
        text$ = text$;"coordinates of the calling window and not the screen coordinates."
        text$ = text$;Chr$(13);Chr$(13);"UpperLeftX = 20";Chr$(13);"UpperLeftY = 20"
        Statictext #dlg1, text$, 50, 50, 200, 200
        Open "Dialog - No Stylebits" for Dialog_Modal as #dlg
        #dlg "Trapclose CloseDlg"
    End Sub
[[code]]
If your program requires a dialog window to be placed according to screen coordinates, use the stylebit _DS_ABSALIGN.
[[code format="vb"]]
    Nomainwin
    WindowWidth = 600
    WindowHeight = 400

    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)

    Button #main.dlg, "_DS_ABSALIGN", dlg, UL, 220, 200, 140, 30

    Open "Stylebits and Dialogs" for Window as #main
    Wait

    Sub CloseMain handle$
        Close #main
        End
    End Sub

    Sub CloseDlg handle$
        Close #handle$
    End Sub

    Sub dlg handle$
        WindowWidth = 300
        WindowHeight = 250

        UpperLeftX = 20 'UpperLeftX 20 pixels to right of upper left screen corner
        UpperLeftY = 20 'UpperLeftY 20 pixels down from upper left screen corner

        text$ = "_DS_ABSALIGN causes the UpperLeftX and UpperLeftY to be "
        text$ = text$;"determined not as client coordinates but as screen coordinates."
        text$ = text$;Chr$(13);Chr$(13);"UpperLeftX = 20";Chr$(13);"UpperLeftY = 20"
        Statictext #dlg, text$, 50, 50, 200, 200
        Stylebits #dlg, _DS_ABSALIGN, 0, 0, 0
        Open "Dialog - _DS_ABSALIGN" for Dialog_Modal as #dlg
        #dlg "Trapclose CloseDlg"
    End Sub
[[code]]
One other coordinate positioning trick can be accomplished with stylebits. Assigning the stylebit _DS_CENTERMOUSE will cause the dialog window to position itself so that the cursor lies in the center of the dialog window.
[[code format="vb"]]
    Nomainwin
    WindowWidth = 600
    WindowHeight = 400

    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)

'All 4 Buttons Call Same Sub
    Button #main.dlg1, "Mouse Centered Dialog", dlg, UL, 20, 80, 140, 30
    Button #main.dlg2, "Mouse Centered Dialog", dlg, UL, 160, 120, 140, 30
    Button #main.dlg3, "Mouse Centered Dialog", dlg, UL, 300, 220, 140, 30
    Button #main.dlg4, "Mouse Centered Dialog", dlg, UL, 400, 300, 140, 30

    Open "Stylebits and Dialogs" for Window as #main

    #main "Trapclose CloseMain"

    Wait

    Sub CloseMain handle$
        Close #main
        End
    End Sub

    Sub CloseDlg handle$
        Close #handle$
    End Sub

    Sub dlg handle$
        WindowWidth = 300
        WindowHeight = 250

        UpperLeftX = 20 'UpperLeftX will be ignored
        UpperLeftY = 20 'UpperLeftY will be ignored

        Stylebits #dlg, _DS_CENTERMOUSE, 0, 0, 0
        Open "Dialog - _DS_CENTERMOUSE" for Dialog_Modal as #dlg
        #dlg "Trapclose CloseDlg"
    End Sub
[[code]]
A dialog window can also be positioned in the forefront of all other windows, even when that dialog window isn't the window with focus. The _DS_SYSMODAL stylebit acts the same as the _WS_EX_TOPMOST stylebit for regular windows.</p>
[[code format="vb"]]
    Nomainwin
    WindowWidth = 600
    WindowHeight = 400

    UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
    UpperLeftY = Int((DisplayHeight - WindowHeight)/2)

'All 4 Buttons Call Same Sub
    Button #main.dlg, "_DS_SYSMODAL", dlg, UL, 220, 200, 140, 30

    Open "Stylebits and Dialogs" for Window as #main

    #main "Trapclose CloseMain"

    Wait

    Sub CloseMain handle$
        Close #main
        End
    End Sub

    Sub CloseDlg handle$
        Close #handle$
    End Sub

    Sub dlg handle$
        WindowWidth = 300
        WindowHeight = 250

        UpperLeftX = 20
        UpperLeftY = 20

        Stylebits #dlg, _DS_SYSMODAL, 0, 0, 0
        Open "Dialog - _DS_SYSMODAL" for Dialog as #dlg
        #dlg "Trapclose CloseDlg"
    End Sub
[[code]]
===A List of Stylebits=== 

You can get a list of all [[http://msdn.microsoft.com/en-us/library/ms632600(VS.85).aspx|dwStyles]] and [[http://msdn.microsoft.com/en-us/library/ms632680(VS.85).aspx|dwExStyles]] available with the Stylebits command at the [[http://msdn.microsoft.com/en-us/library/ms644994(VS.85).aspx#styles|MSDN Library - Dialog Styles]].
Be sure to precede these constants with an underscore (if constant is DS_CENTERMOUSE, then LB Stylebits is _DS_CENTERMOUSE) when using Windows constants in your Liberty BASIC programs.