Source by Todd Nist, Protech Systems Inc.
Modified by Simon Sweetman
The library COMCTL32.DLL contains common controls like the Status Bar control. This example, provided by Todd Nist, shows how to use the Status Bar control in a Progress window. Simon Sweetman added the progressbar. The example will produce a window that looks like this:
The Status Bar in this example is divided in three parts: the first part contains a progressbar which displays the value of the slider, the second part is shown with SBT_POPOUT style so it appears raised.
Button WriteStatusBar results in sending window-messages to the Status Bar control, in this case message SB_SETTEXT. The control also accepts other messages like SB_SETPARTS (to change the size or count of parts), SB_SETICON (to show an icon in a part) or SB_SETTIPTEXT (to set a tooltip for a part). However SB_SETICON and SB_SETTIPTEXT are only available in comctl32.dll version 4.71 or newer.
/*------------------------------------------------------------------------ File: StatusExample.p Author: Todd Nist, Protech Systems Inc. Created: 5/19/98 Modifications: 28/11/00 Simon Sweetman - Added progress meter control ------------------------------------------------------------------------*/ &SCOP WINDOW-NAME C-Win &SCOP FRAME-NAME DEFAULT-FRAME CREATE WIDGET-POOL. /* *************************** Definitions ************************** */ /* Local Variable Definitions --- */ {windows.i} &SCOPE WM_USER 1024 &SCOPE SB_SETPARTS {&WM_USER} + 4 &SCOPE SB_SETTEXT {&WM_USER} + 1 &SCOPE SB_GETRECT {&WM_USER} + 10 &SCOPE PBM_SETRANGE {&WM_USER} + 1 &SCOPE PBM_SETPOS {&WM_USER} + 2 &SCOPE SBT_NORMAL 0 &SCOPE SBT_POPOUT 512 &SCOPE SBT_NOBORDERS 256 /* variables to hold handle control objects */ DEFINE VARIABLE hStatusBar AS INTEGER NO-UNDO. DEFINE VARIABLE progHWND AS INTEGER NO-UNDO. PROCEDURE CreateStatusWindow EXTERNAL "comctl32.dll": DEFINE INPUT PARAMETER lStyle AS LONG. DEFINE INPUT PARAMETER lpctStr AS CHARACTER. DEFINE INPUT PARAMETER hwndParent AS LONG. DEFINE INPUT PARAMETER wId AS LONG. DEFINE RETURN PARAMETER hStatusArea AS LONG. END PROCEDURE. PROCEDURE InitCommonControls EXTERNAL "comctl32.dll": END PROCEDURE. /* Standard preprocessor definitions */ &SCOPED-DEFINE PROCEDURE-TYPE WINDOW &SCOPED-DEFINE ENABLED-OBJECTS BtnCreateStatus BtnWriteStatus SLIDER-1 /* ************************ Function Prototypes ********************** */ FUNCTION CreateProgressArea RETURNS INTEGER ( INPUT phStatusBar AS INTEGER, INPUT piStatusArea AS INTEGER, INPUT piMaxValue AS INTEGER) FORWARD. FUNCTION CreateStatusBar RETURNS INTEGER ( /* parameter-definitions */ ) FORWARD. FUNCTION SetProgressArea RETURNS LOGICAL ( INPUT phProgressArea AS INTEGER, INPUT piValue AS INTEGER ) FORWARD. FUNCTION WriteStatusArea RETURNS LOGICAL ( INPUT phStatusBar AS INTEGER, INPUT piStatusArea AS INTEGER, INPUT piSBTextMode AS INTEGER, INPUT pcText AS CHARACTER ) FORWARD. /* *********************** Control Definitions ********************** */ /* Define the widget handle for the window */ DEFINE VARIABLE C-Win AS WIDGET-HANDLE NO-UNDO. /* Menu Definitions */ DEFINE SUB-MENU m_File MENU-ITEM m_Exit LABEL "E&xit" . DEFINE MENU MENU-BAR-C-Win MENUBAR SUB-MENU m_File LABEL "File" . /* Definitions of the field level widgets */ DEFINE BUTTON BtnCreateStatus LABEL "Create Status Bar" SIZE 25 BY 1. DEFINE BUTTON BtnWriteStatus LABEL "WriteStatusBar" SIZE 25 BY 1. DEFINE VARIABLE SLIDER-1 AS INTEGER INITIAL 0 VIEW-AS SLIDER MIN-VALUE 0 MAX-VALUE 100 HORIZONTAL SIZE 45 BY 2 NO-UNDO. /* ************************ Frame Definitions *********************** */ DEFINE FRAME {&FRAME-NAME} SLIDER-1 AT ROW 1 COL 7 NO-LABEL BtnCreateStatus AT ROW 6 COL 6 BtnWriteStatus AT ROW 6 COL 50 WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY SIDE-LABELS NO-UNDERLINE THREE-D AT COL 1 ROW 1 SIZE 80 BY 8. /* ************************* Create Window ************************** */ IF SESSION:DISPLAY-TYPE = "GUI":U THEN CREATE WINDOW C-Win ASSIGN HIDDEN = YES TITLE = "StatusBar Example" HEIGHT = 8 WIDTH = 80 MAX-HEIGHT = 8 MAX-WIDTH = 80 VIRTUAL-HEIGHT = 8 VIRTUAL-WIDTH = 80 RESIZE = YES SCROLL-BARS = NO STATUS-AREA = NO BGCOLOR = ? FGCOLOR = ? KEEP-FRAME-Z-ORDER = YES THREE-D = YES MESSAGE-AREA = NO SENSITIVE = YES. ELSE {&WINDOW-NAME} = CURRENT-WINDOW. ASSIGN {&WINDOW-NAME}:MENUBAR = MENU MENU-BAR-C-Win:HANDLE. /* *************** Runtime Attributes and UIB Settings ************** */ IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(C-Win) THEN C-Win:HIDDEN = NO. /* ************************ Control Triggers ************************ */ ON END-ERROR OF C-Win /* */ OR ENDKEY OF {&WINDOW-NAME} ANYWHERE DO: /* This case occurs when the user presses the "Esc" key. In a persistently run window, just ignore this. If we did not, the application would exit. */ IF THIS-PROCEDURE:PERSISTENT THEN RETURN NO-APPLY. END. ON WINDOW-CLOSE OF C-Win /* */ DO: /* This event will close the window and terminate the procedure. */ APPLY "CLOSE":U TO THIS-PROCEDURE. RETURN NO-APPLY. END. ON VALUE-CHANGED OF SLIDER-1 IN FRAME {&FRAME-NAME} /* Create Status Bar */ DO: IF ProgHWND NE 0 THEN SetProgressArea(progHWND, INT(SELF:SCREEN-VALUE) * 10). END. ON CHOOSE OF BtnCreateStatus IN FRAME {&FRAME-NAME} /* Create Status Bar */ DO: hStatusBar = CreateStatusBar(). END. ON CHOOSE OF BtnWriteStatus IN FRAME {&FRAME-NAME} /* WriteStatusBar */ DO: DEFINE VARIABLE i AS i NO-UNDO. DO i = 1 TO 2. WriteStatusArea(hStatusBar, i, IF i = 1 THEN {&SBT_POPOUT} ELSE {&SBT_NORMAL}, SUBSTITUTE('Message &1 here...', STRING(i,'9'))). END. progHWND = CreateProgressArea(hStatusBar, 0, 1000). END. ON CHOOSE OF MENU-ITEM m_Exit /* Exit */ DO: APPLY 'WINDOW-CLOSE':U TO {&WINDOW-NAME}. END. /* *************************** Main Block *************************** */ ASSIGN CURRENT-WINDOW = {&WINDOW-NAME} THIS-PROCEDURE:CURRENT-WINDOW = {&WINDOW-NAME}. ON CLOSE OF THIS-PROCEDURE RUN disable_UI. PAUSE 0 BEFORE-HIDE. MAIN-BLOCK: DO ON ERROR UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK: {win32/struct/rect.i} /* Used by CreateProgressArea function */ RUN enable_UI. IF NOT THIS-PROCEDURE:PERSISTENT THEN WAIT-FOR CLOSE OF THIS-PROCEDURE. END. /* ********************** Internal Procedures *********************** */ PROCEDURE disable_UI : /*----------------------------------------------------------------------------- Purpose: DISABLE the User Interface Parameters: Notes: Here we clean-up the user-interface by deleting dynamic widgets we have created and/or hide frames. This procedure is usually called when we are ready to "clean-up" after running. ------------------------------------------------------------------------------*/ /* Delete the WINDOW we created */ IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(C-Win) THEN DELETE WIDGET C-Win. IF THIS-PROCEDURE:PERSISTENT THEN DELETE PROCEDURE THIS-PROCEDURE. END PROCEDURE. PROCEDURE enable_UI : /*------------------------------------------------------------------------------ Purpose: ENABLE the User Interface Parameters: none Notes: Here we display/view/enable the widgets in the user-interface. In addition, OPEN all queries associated with each FRAME and BROWSE. These statements here are based on the "Other Settings" section of the widget Property Sheets. ------------------------------------------------------------------------------*/ ENABLE BtnCreateStatus BtnWriteStatus SLIDER-1 WITH FRAME {&FRAME-NAME} IN WINDOW C-Win. {&OPEN-BROWSERS-IN-QUERY-{&FRAME-NAME}} VIEW C-Win. END PROCEDURE. FUNCTION CreateProgressArea RETURNS INTEGER (INPUT phStatusBar AS INTEGER, INPUT piStatusArea AS INTEGER, INPUT piMaxValue AS INTEGER): /*------------------------------------------------------------------------------ Purpose: Create status bar progress meter control Notes: Return value is window handle of control ------------------------------------------------------------------------------*/ DEFINE VARIABLE hwndParent AS INTEGER NO-UNDO. DEFINE VARIABLE hInstance AS INTEGER NO-UNDO. DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO. DEFINE VARIABLE ReturnHwnd AS INTEGER NO-UNDO. SET-SIZE(lpRect) = 16. /* allocate space for rect object */ /* Get screen postion of required status bar area */ RUN SendMessageA IN hpApi(INPUT phStatusBar, INPUT {&SB_GETRECT}, INPUT piStatusArea, INPUT GET-POINTER-VALUE(lpRect), OUTPUT ReturnValue). RUN mem2buf_lpRect. SET-SIZE(lpRect) = 0. /* release allocated space */ RUN GetParent IN hpApi({&WINDOW-NAME}:HWND, OUTPUT hwndParent). RUN GetWindowLongA IN hpApi(hwndParent, -6, /* GWL_HINSTANCE */ OUTPUT hInstance). /* Create the progress meter window control and parent it to status window */ RUN CreateWindowExA IN hpApi( 8, /* extended style */ "msctls_progress32":U, /* progress meter class name */ "", /* window name */ 1073741824 /* = WS_CHILD */ + 1 /* = PBS_SMOOTH */ + 268435456, /* = WS_VISIBLE */ /* window styles */ lpRect.LEFT, lpRect.TOP, lpRect.RIGHT - lpRect.LEFT, lpRect.BOTTOM - lpRect.TOP, /* window position & size */ phStatusBar, /* parent window */ 0, /* menu pointer */ hInstance, /* instance */ 0, /* parameters */ OUTPUT ReturnHwnd). /* set maximum value of progress meter control */ RUN SendMessageA IN hpApi(INPUT ReturnHwnd, INPUT {&PBM_SETRANGE}, INPUT 0, INPUT piMaxValue * 65536, OUTPUT ReturnValue). RETURN ReturnHwnd. END FUNCTION. FUNCTION CreateStatusBar RETURNS INTEGER ( /* parameter-definitions */ ) : /*------------------------------------------------------------------------------ Purpose: Notes: ------------------------------------------------------------------------------*/ DEFINE VARIABLE hwndMenu AS INTEGER NO-UNDO. DEFINE VARIABLE hwndParent AS INTEGER NO-UNDO. DEFINE VARIABLE hInstance AS INTEGER NO-UNDO. DEFINE VARIABLE hWindowMenu AS INTEGER NO-UNDO. DEFINE VARIABLE hStatusArea AS INTEGER NO-UNDO. DEFINE VARIABLE lpParam AS MEMPTR NO-UNDO. DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO. /*--------------------------------------------------------------------- Allocate memory and define the array to support the segments of the status area. -----------------------------------------------------------------------*/ ASSIGN SET-SIZE(lpParam) = 256 PUT-LONG(lpParam,1) = 120 PUT-BYTE(lpParam,5) = 240 PUT-LONG(lpParam,9) = -1. /* extend to the right edge of the window */ /* find handle to the Parent handle of the Window */ RUN GetParent IN hpApi({&WINDOW-NAME}:HWND, OUTPUT hwndParent). RUN GetWindowLongA IN hpApi(hwndParent, -6, /* GWL_HINSTANCE */ OUTPUT hInstance). /* Call InitCommonControls to ensure that the comctl32.dll is loaded */ RUN InitCommonControls. /* hwndParent */ /* Create the status window control and parent it to the window */ RUN CreateStatusWindow ( 1073741824 /* = WS_CHILD */ + 268435456 /* = WS_VISIBLE */ /* window styles */ + 8388608, /* = WS_BORDER */ '', /* default text */ hwndParent, /* parent window */ 101, /* ID_STATUS */ OUTPUT hStatusArea). IF hStatusArea = 0 THEN MESSAGE 'Unable to create the status bar...' VIEW-AS ALERT-BOX. ELSE /* create the multiple segments based on the data in lpParam */ RUN SendMessageA IN hpApi( INPUT hStatusArea, INPUT {&SB_SETPARTS}, INPUT 3, /* number of parts */ INPUT GET-POINTER-VALUE(lpParam), OUTPUT ReturnValue). /* deallocate the memory */ ASSIGN SET-SIZE(lpParam) = 0. RETURN hStatusArea. /* Function return value. */ END FUNCTION. FUNCTION SetProgressArea RETURNS LOGICAL ( INPUT phProgressArea AS INTEGER, INPUT piValue AS INTEGER ) : /*------------------------------------------------------------------------------ Purpose: Update progress indicator value and redisplay Notes: ------------------------------------------------------------------------------*/ DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO. RUN SendMessageA IN hpApi(INPUT phProgressArea, INPUT {&PBM_SETPOS}, INPUT piValue, INPUT 0, OUTPUT ReturnValue). RETURN TRUE. END FUNCTION. FUNCTION WriteStatusArea RETURNS LOGICAL ( INPUT phStatusBar AS INTEGER, INPUT piStatusArea AS INTEGER, INPUT piSBTextMode AS INTEGER, INPUT pcText AS CHARACTER ) : /*------------------------------------------------------------------------------ Purpose: Write the text in the appropriat format to the appropriate area Notes: ------------------------------------------------------------------------------*/ DEFINE VARIABLE lpParam AS MEMPTR NO-UNDO. DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO. ASSIGN SET-SIZE(lpParam) = 256 PUT-STRING(lpParam,1) = pcText. RUN SendMessageA IN hpApi(INPUT phStatusBar, INPUT {&SB_SETTEXT}, INPUT piStatusArea + piSBTextMode, INPUT GET-POINTER-VALUE(lpParam), OUTPUT ReturnValue). /* deallocate the memory */ ASSIGN SET-SIZE(lpParam) = 0. RETURN TRUE. END FUNCTION.
message SB_SETTEXT has the following parameters:
* wParam = iPart + uType
* lParam = text. The text for each part is limited to 127 characters.
* iPart is the index of the part to set. If iPart=255 you will get a 'simple' status bar with only one part.
uType can be:
* {&SBT_NORMAL} : border, appears lower
* {&SBT_NOBORDERS} : no border, no 3D effect
* {&SBT_POPOUT} : border, appears higher
The Status Bar has a sizing grip because it is parented to the resizable window. It will not have a sizing grip when you parent it to the frame :
/* Create the status window control and parent it to the frame */ RUN CreateStatusWindow ( 1073741824 /* = WS_CHILD */ + 268435456 /* = WS_VISIBLE */ /* window styles */ + 8388608, /* = WS_BORDER */ '', /* default text */ FRAME {&frame-name}:HWND, /* parent */ 101, /* ID_STATUS */ OUTPUT hStatusArea).
This also solves the repaint problem: if the status bar is parented to the window, it will appear to be invisible after the window is repainted.
There's another way to solve the repaint problem, and to keep the StatusBar parented to the window (and therefore keep the "sizing grip").
Simply run:
RUN SendMessageA IN hpApi(INPUT phStatusBar, INPUT 5, /* WM_SIZE */ INPUT 0, INPUT 0, OUTPUT ReturnValue).
For instance, at the end of a WINDOW-RESIZED event (or after a "ShowScrollBar")
Comments
Can I add Panels to the Progress Status Area?
I just looked at this example, which in itself is great and very useful :) I was however wondering whether it is possible to add "panels" to the existing Progress Status area of a window. If that is possible one would not loose the existing "help" functionality offered by the Status Area while also being able to offer some additional information to the user.
Any help/information is appreciated!
Paul
Progress Status Area
Paul,
It is not possible to add panel to the progress status area. I looked at the example provided at OEhieve but decided to use window's MSCOMCTL OCX control. I found it easy to implement. The ProTools com control API can be used to implement this statusbar control.
Thanks
Shanker
Hi Shanker, Thanks for your
Hi Shanker,
Thanks for your reply. Yes, I know I can use that specific ActiveX control. However, using an ActiveX control means we'd loose the information that is normally shown in the Progress status area (for instance "help" defined on widgets would no longer be visible).
Paul
How can i create status bar using graphical object /ocx.
How can i create status bar using graphical object /oxc?
any one who can help me?
tnx.