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

New Graphic Buttons for Console Compiler

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

  • New Graphic Buttons for Console Compiler

    Attached is a .zip file containing four demo files, the include file GrButtons.inc and an HTML ReadMe file.
    The source code of Demo0 and Demo1a is placed in this post directly.
    The .inc file (> 2300 line of code) should be downloaded from the .zip file.

    Discussion can take place here:



    The main features of the Graphic Buttons are:

    - The include file GrButtons.inc is a collection of routines for creating and using Graphic Buttons, TickBoxes, Frames and Text.
    - Version V0.4 is compiled using the GRAPHIC WINDOW commands and new features of PB/CC 5.0.
    - Subclassing the graphic windows is not necessary anymore, and therefore it uses only a few Win32API calls.
    - It is based on Steve Rossel's initial suggestions:

    - The help of PB support on some missing features of PB/CC 5.0 is greatly acknowledged.

    - A graphical button window (GW) can have any size and contain as many objects as needed.
    - Hierarchical button windows are allowed. They each have their own ID.
    - They can be stacked: A newer window (placed on top of other ones) has to be closed in order to return to the next lower one.
    - The Graphic Buttons can be called from the Console or another Graphic Window ("BaseApplication").
    - Some window management is built in: Button windows move (get locked) and hide with the Console/BaseApplication.
    The top window always stays on top.
    - Error detection catches a GW getting closed externally (Alt F4 etc.) or when a GW gets closed in the wrong order.

    - The following objects can be placed in a graphical window:

    o Buttons (variable in location, size, color, text, ID and hotkeys).
    o TickBoxes as another type of button (one can choose: square box with an X or radio button).
    o TickBoxes can be grouped, allowing only one box per group to be on ( = ticked).
    o Frames for optically structuring the window. They can be drawn as rectangles or as single lines with and without text.
    o Frames without lines can be used to simply place text.
    o QueryBox$ - a predefined button window (similar to a MessageBox and Waitkey$) with Yes / No / Ok / Cancel buttons.
    The height of a QueryBox gets adapted to the number of lines passed over in the text string (# of $CRLF + 1).

    - A button (or TickBox) can be activated by any of the following means:

    o Click it with the left mouse button. When the mouse cursor moves over a button it changes its appearance (hover effect).
    o Move the selection (= button focus, a rectangle of dotted lines) to a button and hit Enter (CR) or Space (SPC).
    o The selection can be moved by the cursor keys up / right and down / left or by Tab / Shift Tab.
    o Press the key which is underlined in the button text. E.g. for "Quit" press Q.
    o Press the Hotkey assigned to a button:
    Hotkeys can have the prefix # for Shift, ^ for Ctrl, @ for Alt or nothing for the plain key.
    The hotkeys of the top GW are displayed in place of each button's text when Shift + Ctrl get pressed.

    - The activated button can cause a routine to be executed through the .OnClick pointer (no parameters, though). See UDT of Buttons.
    - The activation of a button can be checked in a loop using GraphicGetEvents() which returns the button's ID in case of success.
    - Keyboard events are detected no matter which window has the focus, the Console/BaseApplication or the button window!

    - A Function OpenFile() has been added in order to open or execute a file or type of file.
    - Special routines have been written to extend the PB/CC 5.0 command GRAPHIC INKEY$:
    o GW_Inkey() detects many more keys such as Alt F1-F12 etc.
    o GW_Inshift returns the state of the shift keys. Similar to the statement INSHIFT.

    Gert Voland.


    First demo program:
    Code:
    'Demo0_GrButtons.bas
    'Purpose:   A simple demonstration of the new function  "QueryBox$"  in GraphicButtons for PB/CC 5.0
    'Usage:     Provide GrButtons.inc for #INCLUDE
    
    'Author:    Gert Voland
    'Compiler:  PB/CC 5.0
    'OS:        Win XP
    'Date:      29. Oct. 2008
    'Placed in public domain by the author. Use at own risk.
    
    
    #COMPILE EXE
    #DIM ALL
    #CONSOLE ON
    #BREAK ON                                   'can be turned OFF. Then Console can only be ended by buttons or Task Manager!
    
    #INCLUDE "GrButtons.inc"                    'use V0.4 for PB/CC 5.0
    
    '----------------------------------------------------------------------------------
    
    FUNCTION PBMAIN
    
        PRINT " -------------------------"
        PRINT " Simple demo of QueryBox$:"
        PRINT " -------------------------"
        PRINT
        PRINT " To activate a button do one of the following things:"
        PRINT "     - move cursor over it and click left mouse button or"
        PRINT "     - press the underlined character as HotKey or"
        PRINT "     - use the cursor Keys or TAB / Shift TAB
        PRINT "       to move the button focus, then hit Enter or Space."
        PRINT
        PRINT "     Key events are detected in the Console and in the button window,
        PRINT "     which ever has the (window) focus!
        PRINT
        PRINT "     Note that QueryBox$ gets all the CPU while waiting (similar to WAITKEY$).
        PRINT
        PRINT "     Move the Console and see how the QueryBox is locked to it
        PRINT "     (i.e. as long as %UseCaption = 0).
        PRINT
        PRINT " Start by pressing any key ..."
        WAITKEY$
    
        DO
            QueryBox$ "Hello World!", "O"                                           'just an "OK" button
    
            IF QueryBox$("Is it a nice day today?", "YN") = "N" THEN ITERATE DO     '"Yes" and "No" buttons, button focus by default on first button (here: Yes)
    
            IF QueryBox$("Finish the program?", "OC", 2) = "O" THEN EXIT LOOP       '"OK" and "Cancel" (hot key: ESC), button focus on 2nd button
    
        LOOP
    
        QueryBox$ "Well, enjoy the nice day ..."                                    '"OK" button (and button focus) by default
    
        CONSOLE SET FOCUS
        CLS
        PRINT : PRINT " Have you looked at the source code of Demo0.bas ?
        PRINT : PRINT " ... as easy as using WAITKEY$, isn't it ?"
        WAITKEY$
    
    END FUNCTION
    
    '--- End of File --------------------------------------------------------------

    Second demo program:
    Code:
    'Demo1a_GrButtons.bas
    
    'Purpose: A simple demonstration of the Graphic Buttons, TickBoxes and Frames for PB/CC 5.0
    'using the built-in function QueryBox$ which waits for activation of a valid button each time and thus using all the CPU time.
    'See Demo1b_GrButtons.bas for the non-waiting routines.
    'Usage: Provide GrButtons.inc for #INCLUDE
    
    'Author:    Gert Voland
    'Compiler:  PB/CC 5.0
    'OS:        Win XP
    'Date:      29. Oct. 2008
    'Placed in public domain by the author. Use at own risk.
    
    
    #COMPILE EXE
    #DIM ALL
    #CONSOLE ON
    #BREAK ON                                   'can be turned OFF. Then programm can only be ended by buttons or Task Manager!
    
    #INCLUDE "GrButtons.inc"                    'use V0.4 for PB/CC 5.0
    
    ' Equates for the Button window (need only one here because the others are the QueryBox$
    %GW_Main        = 1
    
    ' Equates for button and frame IDs
    %GB_Up          = 10
    %GB_Down        = 11
    %GB_Quit        = 12
    %TB_1           = 20
    %TB_5           = 21
    %GF_Control     = 30
    %GF_Delta       = 31
    
    ' Colors
    %light_yellow   = &h00A0FFFF
    %medium_yellow  = &h0040FFFF
    
    '----------------------------------------------------------------------------
    
    SUB GrCountControl(BYVAL xpos AS LONG, ypos AS LONG, BYVAL w AS LONG, BYVAL h AS LONG)
    'Create the control window, create buttons and wait for Window events (mouse or keyboard) and supply the return values
        LOCAL Frame     AS GraphicFrame                         'data set for frame parameters
        LOCAL Button    AS GraphicButton                        'data set for button parameters
    
        'Create the control window
        CALL GraphicCreateWindow(%GW_Main, "Count Control", xpos, ypos, w, h)
    
        '--- The UDTs could be completely set for each button. But the repeated (identical) statements can be removed.
    
        '-------------------------------------------
        'Create frames next to or around the buttons
        '--- complete frame with text --------------
        Frame.x                 = 20
        Frame.y                 = 30
        Frame.Width             = 140
        Frame.Height            = 290
        Frame.Text              = "Counter increment"
        Frame.FontName          = "Tahoma"
        Frame.FontSize          = 10
        Frame.FontStyle         = 0
        Frame.TextColor         = %RED
        Frame.BorderColor       = %RED
        Frame.ID                = %GF_Delta
        CALL GraphicAddFrame(Frame)
    
        '--- just a line as separator
        Frame.x                 = 30
        Frame.y                 = 140
        Frame.Width             = 120
        Frame.Height            = 1                             'just a line with text
        Frame.Text              = "Flow  Control"
    ''    Frame.FontName          = "Tahoma"
    ''    Frame.FontSize          = 10
    ''    Frame.FontStyle         = 0
    ''    Frame.TextColor         = %RED
    ''    Frame.BorderColor       = %RED
        Frame.ID                = %GF_Control
        CALL GraphicAddFrame(Frame)
    
        '-----------------------------------------
        'Create TickBoxes /TB)
        '--- +/-1 TickBox ------------------------
        Button.x                = 60
        Button.y                = 60
    ''    Button.Width            = 0                             'not needed for tickbox
    ''    Button.Height           = 0                             'not needed for tickbox
        Button.Text             = "+/- 1"
        Button.nUnderChar       = 5
        Button.HotKey           = "^1"
        Button.FontName         = "Microsoft Sans Serif"
        Button.FontSize         = 9
        Button.FontStyle        = 0
        Button.TextColor        = %light_yellow
        Button.BackColor        = %GW_backColor
        Button.BorderColor      = %light_yellow
        Button.HoverFontStyle   = 1
        Button.HoverTextColor   = %medium_yellow
        Button.HoverBackColor   = %darker_gray
        Button.HoverBorderColor = %medium_yellow
        Button.Focus            = 1                             'preset
        Button.OnClick          = 0                             'no routine set up
        Button.Disable          = 0                             'enabled
        Button.ID               = %TB_1
        Button.Type             = %GW_TickBox
        Button.TBTick           = 1                             'preset
        Button.TBGroup          = 1                             'start of a group
        CALL GraphicAddButton(Button)
    
        '--- +/- 5 tickbox
    ''    Button.x                = 60
        Button.y                = 90
    ''    Button.Width            = 0                             'not needed for tickbox
    ''    Button.Height           = 0                             'not needed for tickbox
        Button.Text             = "+/- 5"
    ''    Button.nUnderChar       = 5
        Button.HotKey           = "^5"
    ''    Button.FontName         = "Microsoft Sans Serif"
    ''    Button.FontSize         = 9
    ''    Button.FontStyle        = 0
    ''    Button.TextColor        = %light_yellow
    ''    Button.BackColor        = %GW_backColor
    ''    Button.BorderColor      = %light_yellow
    ''    Button.HoverFontStyle   = 1
    ''    Button.HoverTextColor   = %medium_yellow
    ''    Button.HoverBackColor   = %darker_gray
    ''    Button.HoverBorderColor = %medium_yellow
        Button.Focus            = 0                             'preset
    ''    Button.OnClick          = 0                             'no routine set up
    ''    Button.Disable          = 0                             'enabled
        Button.ID               = %TB_5
    ''    Button.Type             = %GW_TickBox
    ''    Button.TBTick           = 1                             'preset
    ''    Button.TBGroup          = 1                             'start of a group
        CALL GraphicAddButton(Button)
    
        '-------------------------------------
        ' Create Graphic Buttons (GB)
        '--- Up button -----------------------
        Button.x                = 50
        Button.y                = 170
        Button.Width            = 80
        Button.Height           = 30
        Button.Text             = "Up"
        Button.nUnderChar       = 1
        Button.HotKey           = "@U"
    ''    Button.FontName         = "Microsoft Sans Serif"
    ''    Button.FontSize         = 9
    ''    Button.FontStyle        = 0
    ''    Button.TextColor        = %light_yellow
    ''    Button.BackColor        = %GW_backColor
    ''    Button.BorderColor      = %light_yellow
    ''    Button.HoverFontStyle   = 1
    ''    Button.HoverTextColor   = %medium_yellow
    ''    Button.HoverBackColor   = %darker_gray
    ''    Button.HoverBorderColor = %medium_yellow
    ''    Button.Focus            = 0                             'preset
    ''    Button.OnClick          = 0                             'no routine set up
    ''    Button.Disable          = 0                             'enabled
        Button.ID               = %GB_Up
        Button.Type             = %GW_Button
    ''    Button.TBTick           = 0                             'not needed for GB
    ''    Button.TBGroup          = 0                             'not needed for GB
        CALL GraphicAddButton(Button)
    
        '--- Down button
        Button.y                = 220
        Button.Text             = "Down"
        Button.HotKey           = "@D"
        Button.ID               = %GB_Down
        CALL GraphicAddButton(Button)
    
        '--- Quit button : here only the changed variables are set
        Button.y                = 270
        Button.Text             = "Quit"
        Button.nUnderChar       = 1
        Button.HotKey           = "ESC"
        Button.ID               = %GB_Quit
        CALL GraphicAddButton(Button)
    
    END SUB 'GrCountControl
    
    '----------------------------------------------------------------------------------------------
    
    FUNCTION PBMAIN
        LOCAL xcount        AS LONG                             'loop value
        LOCAL xsleep        AS LONG                             'use instead of SLEEP for delaying the display
        LOCAL x0, y0        AS LONG                             'coordinates of Console
        LOCAL xGW, yGW      AS LONG                             'coordinates of GW relative to Console
        LOCAL wGW, hGW      AS LONG                             'size of GW
        LOCAL delta         AS LONG                             'count by 1 or 5
        LOCAL dir           AS LONG                             '1 => incr or -1 => decr
        LOCAL sTxt          AS STRING                           'display text
        LOCAL retButton     AS LONG                             'ID of activated button/tickbox
    
        x0  = 300                                               'absolute pixel position of Console on screen
        y0  = 100
        xGW = 600                                               'relative position of GW to Console
        yGW =  70
        wGW = 180                                               'width and height of GW
        hGW = 350
    
        CONSOLE SET SCREEN 40, 100                               'set size of Console screen row, columns
        ShowWindow CONSHNDL, %SW_MAXIMIZE                       'set to maximized; there may cases under XP that start the Console with scroll bars
        CONSOLE SET LOC x0, y0                                  'place Console
        CONSOLE NAME "Demo1_GrButtons"
        CURSOR OFF                                              'Console line cursor (not Windows mouse cursor)
    
        CALL GrCountControl(x0 + xGW, y0 + yGW, wGW, hGW) 'open the control window with home made buttons
        CONSOLE SET FOCUS                                       'the console program is the main user program. We only switch
    
        GraphicSetFocus(%GB_Up)                                 'preset (could also be done in SUB GrCountControl)
                                                                'to the button window temporarily for polling keyboard and mouse events.
        'Presets
        xcount = 0
        xsleep = 0
        delta = 1
        dir = 1
        sTxt = "Count  -up-  by"
    
        'Main Console loop
        DO
            CALL GraphicGetEvents(retButton)                    'check for pressed key or mouse movement/click
    
            SELECT CASE retButton                               'here we check which button was hit
                                                                'there are no routines automaticallay executed (.OnClick = 0 for all buttons!)
                CASE %TB_1
                    IF delta <> 1 THEN
                        QueryBox("... now counting +/- 1")
                        delta = 1
                    END IF
    
                CASE %TB_5
                    IF delta <> 5 THEN
                        QueryBox("... now counting +/- 5")
                        delta = 5
                    END IF
    
                CASE %GB_Up
                    IF dir = -1 THEN                            'only check when counting down
                        IF QueryBox$(" Do you want to count  -up-  now ?" + $CRLF + "Watch counter on the Console (Wait !)", "YN", 2) <> "Y" THEN EXIT SELECT
                        dir = 1
                        sTxt = "Count  -up-  by"
                    END IF
                CASE %GB_Down
                    IF dir = 1 THEN
                        IF QueryBox$(" Do you want to count  -down-  now ?" + $CRLF + "Watch counter on the Console (Wait !)", "YN", 2) <> "Y" THEN EXIT SELECT
                        dir = -1
                        sTxt = "Count  -down-  by"
                    END IF
                CASE %GB_Quit
                    IF QueryBox("Do you want to quit the program ?", "YNC", 3) = "Y" THEN
                        IF QueryBox(" ... really ?", "YN", 2) = "Y" THEN EXIT LOOP
                    END IF
            END SELECT
    
    
            INCR xsleep
            SLEEP 1
            IF xsleep MOD 30 = 0 THEN                           'display and count after 30 * SLEEP 1
                xcount = xcount + delta * dir                   'do the calculation
                LOCATE 2,5                                      'display it
                PRINT sTxt + STR$(delta) + " : "; xcount; SPACE$(10)
                xsleep = 0
            END IF
    
        LOOP
    
        CALL GraphicDestroyWindow(%GW_Main)                     'close GW. The parameter is optional (see explanations in the destroy function)
    
    END FUNCTION    'PBMAIN
    
    '--- End of File ------------------------------------------------------------------------------
    Attached Files
    Last edited by Gert Voland; 1 Nov 2008, 04:20 AM.
    Gert Voland

  • #2
    Really nice work here Gert! Love those buttons.

    Did I see a version 5.0 posted yesterday? Can't seem to find it today, did it get withdrawn?

    Here are some bugs I found in 4.0

    In the GWCheckHotKeys, a problem with the conversion of 2 character ascii strings for function keys. Your existing code lets other keys do the hotkeys functions, like down arrow was the same as F11.

    here is my correction (your original code is the commented out line):

    Code:
                CASE 59 TO 88                                           ''' Keys: F1 - F12 (any shift key)
                    IF LEFT$(hotkey$, 1) <> "F" THEN GOTO ExitFunct:    ' Allow only Fxx
                    'IF nkey >68 THEN nkey = nkey - 18                   ' Correction for F11 and F12     use below 2 statements
                    IF nkey = 88 THEN nkey = 70 'f12
                    IF nkey = 87 THEN nkey = 69 'f11
    Also you need a sleep 1 statement in the QueryBox$ function Do Loop, otherwise it hogs the processer

    Thanks again.

    Comment


    • #3
      Larry, thanks for the feed back.

      Yes, the version 0.5 of the Graphic Buttons has been withdrawn.
      It will be re-posted when the update release PB/CC 5.01 is officially available.
      PB support has been very good in acknowledging problem reports.
      V5.01 will avoid almost all problems that I encountered with the buttons - or we found workarounds.

      I will take a look at your proposals and work them in.

      Gert.
      Gert Voland

      Comment


      • #4
        One more change I forgot to mention. In the GraphicCreateWindow and GWCheckFocus SUBS, I replaced %HWND_TOPMOST with %HWND_TOP. Otherwise I couldn't switch between windows in my main program, the buttons were always on top. I made sure the focus was correct in the main calling program.

        Comment


        • #5
          Larry,

          In the GWCheckHotKeys, a problem with the conversion of 2 character ascii strings for function keys. Your existing code lets other keys do the hotkeys functions, like down arrow was the same as F11.
          Probably a typo. It should have been > 86, rather than > 68. In any case it is better to limit the detection to the F-keys. So the CASE should be:

          Code:
                      CASE 59 TO 68, 87, 88                                   ''' Keys: F1 - F12 (any shift key)
                          IF LEFT$(hotkey$, 1) <> "F" THEN GOTO ExitFunct:    ' Allow only Fxx
                          IF nkey > 86 THEN nkey = nkey - 18                  ' Correction for F11 and F12
          
                          IF nkey - 58 <> VAL(RIGHT$(hotkey$, LEN(hotkey$) - 1)) THEN GOTO ExitFunct:
                          result = 1                                          ' ASC("F1") = (0, 59)

          Also you need a sleep 1 statement in the QueryBox$ function Do Loop, otherwise it hogs the processer
          Yes, it needs a SLEEP 1. The QueryBox may block the calling program while waiting, but not other processes!
          I will also introduce a SLEEP 0 in the GraphicGetEvents() routine in order to release the CPU if necessary.

          Thanks again,
          Gert.
          Gert Voland

          Comment


          • #6
            One more change I forgot to mention. In the GraphicCreateWindow and GWCheckFocus SUBS, I replaced %HWND_TOPMOST with %HWND_TOP. Otherwise I couldn't switch between windows in my main program, the buttons were always on top. I made sure the focus was correct in the main calling program.
            Larry, I am not sure that I understand your message correctly. What do you mean by: "Otherwise I couldn't switch between windows in my main program"?

            The intention is - and that way it works on my machines - that a button window gets created and stays on top of the console, no matter if it or the console has the focus.

            A soon as another window (not the console and not the button window) gets the focus, the button window and its task bar icon disappear (hide). The console could then be in the background or even iconized.
            When the console gets the focus back or gets maximized, the button window appears as "topmost" again.

            When I use %HWND_TOP, the button window hides behind the console unless it has the focus itself.

            Could you give an example?

            Gert.
            Gert Voland

            Comment


            • #7
              I am also using Console Tools message boxes and input boxes. Unless I use %HWND_TOP, the message boxes and input boxes get hidden behind the graphic button window, even though the message/input boxes have the focus.

              Comment


              • #8
                I am also using Console Tools message boxes and input boxes...
                Sorry, I can't make any judgement on those effects since I don't have Console Tools.
                Gert.
                Gert Voland

                Comment

                Working...
                X