PMGuide - Button Controls: Difference between revisions
Created page with "==About Button Controls== ===Button Types=== ====Push Buttons==== ====Radio Buttons==== ====Check Boxes==== ====Three-State Check Boxes==== ====Application-defined Buttons====..." |
|||
(4 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{IBM-Reprint}} | |||
{{PMGuide}} | |||
A button is a type of control window used to initiate an operation or to set the attributes of an operation. This chapter describes how to create and use buttons in PM applications. | |||
==About Button Controls== | ==About Button Controls== | ||
A button control can appear alone or with a group of other buttons. When buttons are grouped, the user can move from button to button within the group by pressing the Arrow keys. The user also can move among groups by pressing the Tab key. | |||
A user can select a button by clicking it with the mouse, pressing the spacebar when the button has the keyboard focus, or sending a BM_CLICK message. In most cases, a button changes its appearance when selected. | |||
A button control is always owned by another window, usually a dialog window or an application's client window. A button control posts WM_COMMAND messages or sends WM_CONTROL notification messages to its owner when a user selects the button. For further information on messages generated, see Button Notification Messages. The owner window receives messages from a button control and can send messages to the button to alter its position, appearance, and enabled/disabled state. | |||
To use a button control in a dialog window, an application specifies the control in a dialog template in the application's resource-definition file. The application processes button messages in the dialog-window procedure. | |||
An application creates a button control in a client window by calling WinCreateWindow, specifying a window class of WC_BUTTON, and identifying the client window as the owner of the button control. | |||
===Button Types=== | ===Button Types=== | ||
There are four main types of buttons: push buttons, radio buttons, check boxes, and three-state check boxes. A button's type determines how the button looks and behaves. | |||
A radio button, check box, or three-state check box controls an operation; a push button initiates an operation. For example, a user might set printing options (such as paper size, print quality, and printer type) in a print-command dialog window containing an array of radio buttons and check boxes. After setting the options, the user would select a push button to tell an application that printing should begin (or be canceled). Then, the application would query the state of each check box and radio button to determine the printing parameters. | |||
====Push Buttons==== | ====Push Buttons==== | ||
A push button is a rectangular window typically used to enable the user to start or stop an operation. When selected, a push button control posts a WM_COMMAND message to its owner window. | |||
The push button can contain a text string, an icon or mini-icon, or a combination of text and images. | |||
====Radio Buttons==== | ====Radio Buttons==== | ||
A radio button is a window with text displayed to the right of a small circular indicator. Each time the user selects a radio button, that button's state toggles between selected and unselected. This state remains until the next time the user selects the button. An application typically uses radio buttons in groups. | |||
Within a group, usually one button is selected by default, and the user can move the selection to another button by using the cursor keys; however, only one button can be selected at a time. Radio buttons are appropriate if an exclusive choice is required from a fixed list of related options. For example, applications often use radio buttons to allow the user to select the screen foreground and background colors. A radio-button control sends WM_CONTROL messages to its owner window. | |||
====Check Boxes==== | ====Check Boxes==== | ||
Check boxes are similar to radio buttons, except that they can offer multiple-choice selection as well as individual choice. Check boxes offer the user a fixed list of choices, with the option of selecting more than one, or even all. | |||
Check boxes also toggle application features on or off. For example, a word processing application might use a check box to let the user turn word wrapping on or off. A check-box control sends WM_CONTROL messages to its owner window. | |||
====Three-State Check Boxes==== | ====Three-State Check Boxes==== | ||
Three-state check boxes are similar to check boxes, except that they can be displayed in halftone as well as selected and unselected. An application might use the halftone state to indicate that, currently, the checkbox is not selectable. A three-state check-box control sends WM_CONTROL messages and posts WM_COMMAND messages to its owner window. | |||
====Application-defined Buttons==== | ====Application-defined Buttons==== | ||
In addition to using the four predefined button-control types, an application can create button controls that appear as defined by the owner window. When they must be drawn or highlighted, these button controls send WM_CONTROL messages with BN_PAINT as the notification code to their owner windows. | |||
===Button Styles=== | ===Button Styles=== | ||
The following table describes the button styles an application can use when creating button controls: | |||
{| class="wikitable" | |||
|+ Button Styles and Descriptions | |||
|- | |||
! Style !! Description | |||
|- | |||
| BS_3STATE || Creates a three-state check box (see also BS_CHECKBOX). When the user selects the check box, it sends a WM_CONTROL message to the owner window. The owner should set the check box to the appropriate state: selected, unselected, or halftone. | |||
|- | |||
| BS_AUTO3STATE || Creates an auto-three-state check box (see also BS_CHECKBOX). When the user selects the check box, the system automatically sets the check box to the appropriate state: selected, unselected, or halftone. | |||
|- | |||
| BS_AUTOCHECKBOX || Creates an auto-check box (see also BS_CHECKBOX). The system automatically toggles the check box between the selected and unselected states each time the user selects the box. | |||
|- | |||
| BS_AUTORADIOBUTTON || Creates an auto-radio button (see also BS_RADIOBUTTON). When the user selects an auto-radio button, the system automatically selects the button and removes the selection from the other auto-radio buttons in the group. | |||
|- | |||
| BS_AUTOSIZE || Creates a button that is sized automatically to ensure that the contents fit. Note: The cx or cy parameter of WinCreateWindow must be specified as -1 to implement the autosize feature. | |||
|- | |||
| BS_BITMAP || Creates a push button containing a bit map instead of text. This style can only be implemented with BS_PUSHBUTTON. | |||
|- | |||
| BS_CHECKBOX || Creates a check box-a small square that has text displayed to its right. When the user selects a check box, the check box sends a WM_CONTROL message to the owner window. The owner window should toggle the check box between selected and unselected states. | |||
|- | |||
| BS_DEFAULT || Creates a push button that has a heavy black border. The user can select this push button by pressing the spacebar. This style is useful for letting the user quickly select the most likely set of options in a dialog window. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. | |||
|- | |||
| BS_HELP || Creates a push button that posts a WM_HELP message (instead of a WM_COMMAND message) to its owner window when the user selects the button. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. | |||
|- | |||
| BS_ICON || Creates a push button containing an icon instead of text. | |||
|- | |||
| BS_MINIICON || Creates a push button containing a mini-icon instead of text. | |||
|- | |||
| BS_NOBORDER || Creates a push button that has no border. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. | |||
|- | |||
| BS_NOCURSORSELECT || Creates an auto-radio button that will not be selected automatically when the user moves the cursor to the button using the cursor-movement keys. This style is valid only in combination with the BS_AUTORADIOBUTTON style or the AUTORADIOBUTTON statement in a resource-definition file. | |||
|- | |||
| BS_NOPOINTERFOCUS || Creates a radio button or check box that does not receive the keyboard focus when the user selects it. This style is valid in combination with the BS_AUTORADIOBUTTON, BS_RADIOBUTTON, BS_3STATE, BS_AUTO3STATE, BS_AUTOCHECKBOX, and BS_CHECKBOX styles, or the AUTORADIOBUTTON, RADIOBUTTON, AUTOCHECKBOX, or CHECKBOX statements in a resource-definition file. | |||
|- | |||
| BS_NOTEBOOKBUTTON || Creates a notebook button, which is identical to a pushbutton except that when it is created as a child of a notebook page it becomes a button in the common button area of the notebook page. If the button is not in a notebook page it will be indistinguishable from a pushbutton. | |||
|- | |||
| BS_PUSHBUTTON || Creates a push button-a round-cornered rectangle with text displayed inside it. When selected, the push button posts a WM_COMMAND message to its owner window. | |||
|- | |||
| BS_RADIOBUTTON || Creates a radio button-a small circle that has text displayed to its right. Radio buttons usually are used in groups of related, but exclusive, choices. When the user selects a radio button, the button sends a WM_CONTROL message to its owner window. The user should select the button and remove the selection from the other radio buttons in the group. | |||
|- | |||
| BS_SYSCOMMAND || Creates a button that posts a WM_SYSCOMMAND message (instead of a WM_COMMAND message) to the owner window when the user selects the button. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. | |||
|- | |||
| BS_TEXT || Creates a push button containing both text and icons/mini-icons. | |||
|- | |||
| BS_USERBUTTON || Creates a user-defined button that sends a WM_CONTROL message to the owner window when the button needs to be drawn, highlighted, or disabled. A user-defined button also posts WM_COMMAND messages to the owner window when the user selects the button. | |||
|} | |||
===Default Button Behavior=== | ===Default Button Behavior=== | ||
Following are the messages processed by the predefined button-control window class (WC_BUTTON). Each message is described in terms of how a button control responds to that message. | |||
{| class="wikitable" | |||
|+ Button Messages and Descriptions | |||
|- | |||
! Message !! Description | |||
|- | |||
| BM_AUTOSIZE || Causes the buttons in a new-style notebook to automatically size to fit their contents. | |||
|- | |||
| BM_CLICK || Sends a WM_BUTTON1DOWN and WM_BUTTON1UP message to itself to simulate a user button selection. | |||
|- | |||
| BM_QUERYCHECK || Returns the checked state of the button. | |||
|- | |||
| BM_QUERYCHECKINDEX || Returns the 0-based index to the selected button in a group. Returns -1 if no button in the group is selected or if the button receiving the message is not a radio button or an auto-radio button. | |||
|- | |||
| BM_QUERYHILITE || Returns the highlighted state of the button. | |||
|- | |||
| BM_SETCHECK || Sets the checked state of the button and returns the previous checked state. | |||
|- | |||
| BM_SETDEFAULT || Sets the default button state and redraws the button. | |||
|- | |||
| BM_SETHILITE || Sets the highlighted state of the button and returns the previous highlighted state. | |||
|- | |||
| WM_BUTTON1DBLCLK || Highlights the button and sends a BN_DBLCLICKED notification code when the button-up message arrives. | |||
|- | |||
| WM_BUTTON1DOWN || Sets the button window so it can capture mouse input. | |||
|- | |||
| WM_BUTTON1UP || If the button window is set to capture mouse input, and if the mouse pointer is inside the button window when the mouse button is released, this message releases the mouse and sends a notification message to the owner window. If the button is a push button, the push button control posts a WM_COMMAND message; otherwise, the button control sends a WM_CONTROL message with the BN_CLICKED notification code. | |||
|- | |||
| WM_CHAR || Sets the button window so it can capture mouse input when the spacebar is pressed; releases the mouse when the spacebar is released. Passes other key messages to the default window procedure. | |||
|- | |||
| WM_CREATE || Validates the requested button style and sets the window text. | |||
|- | |||
| WM_DESTROY || Frees the memory containing the window's text. | |||
|- | |||
| WM_ENABLE || Sent when an application changes the enabled state of a window. | |||
|- | |||
| WM_MATCHMNEMONIC || Returns TRUE if mp1 matches a mnemonic in the control window's text. | |||
|- | |||
| WM_MOUSEMOVE || Sets the default mouse pointer. If the button has the mouse captured, the button's highlighted state changes as the mouse pointer moves in and out of the button boundary. | |||
|- | |||
| WM_PAINT || Draws the button according to its style and current state. | |||
|- | |||
| WM_QUERYDLGCODE || Returns the DLGC_BUTTON code combined with other DLGC_ codes that designate the button's type. | |||
|- | |||
| WM_QUERYWINDOWPARAMS || Returns the requested window parameters. | |||
|- | |||
| WM_SETFOCUS || Creates a cursor if the button-control window is receiving the focus. Destroys the cursor if the button-control window is losing the focus. | |||
|- | |||
| WM_SETWINDOWPARAMS || Sets the requested window parameters and redraws the button, including the cursor, if the button-control window has the focus. | |||
|} | |||
===Button Notification Messages=== | ===Button Notification Messages=== | ||
A button, regardless of its style or type, posts a message to its owner when selected by the user. The message posted by push buttons is ordinarily WM_COMMAND. However, for buttons created with the BS_PUSHBUTTON or BS_USERBUTTON style, the message posted can be changed to WM_HELP or WM_SYSCOMMAND by additionally specifying either the BS_HELP or BS_SYSCOMMAND styles, respectively, when creating the button. A button control that has a style other than BS_PUSHBUTTON or BS_USERBUTTON sends WM_CONTROL messages to its owner when the user selects it. | |||
When the user selects a push button using the mouse pointer, the system automatically highlights the button. The button's window procedure tracks the movement of the pointer until the user releases the button. If the user moves the pointer so that it is outside the button boundary, the system turns off the highlight. The push button control does not post a WM_COMMAND message until the user releases the pointer button, and then, only if the button is released inside the push button boundary. When the owner window receives a WM_COMMAND message from a push button, the low word of the first parameter in the message contains the identifier of the button as specified either in the dialog template or in the WinCreateWindow function when the button was created. | |||
An application should avoid duplicating identifiers for menu items and button controls, because both the items and the controls post identifiers to owner windows as WM_COMMAND messages. However, the application can determine whether a WM_COMMAND message came from a menu or a push button control by looking for the value CMDSRC_MENU or CMDSRC_PUSHBUTTON in the low word of the message's second parameter. | |||
When the user selects any button other than a push button, that button sends a WM_CONTROL message. The application can examine SHORT1FROMMP(mp1) in the WM_CONTROL message to find the button identifier, and can examine SHORT2FROMMP(mp1) to determine the notification code for the control message. The notification code can be one of the following: | |||
{| class="wikitable" | |||
|+ Button Notification Codes and Descriptions | |||
|- | |||
! Code !! Description | |||
|- | |||
| BN_CLICKED || The user selected the button. | |||
|- | |||
| BN_DBLCLICKED || The user double-clicked the button. | |||
|- | |||
| BN_PAINT || A user-defined button needs to be drawn. Buttons with the BS_USERBUTTON style send this notification code to instruct the owner window to draw the button control. The second message parameter of the WM_CONTROL message contains a pointer to a USERBUTTON structure that contains the information necessary for drawing the button. | |||
|} | |||
When the user selects a check box or radio button, the button control sends the WM_CONTROL message with the BN_CLICKED notification code to the owner window. In response, the owner window should set the display state of the button by sending the appropriate message back to the button. | |||
An application need not respond to WM_CONTROL messages sent by an auto-check box or an auto-radio button; the system automatically sets the states of these buttons. | |||
===Button States=== | ===Button States=== | ||
An application can query and set the highlighted and checked states of its buttons by sending messages to them. An application can obtain the handle of a button by calling WinWindowFromID, using the parent window handle and the identifier of the button. In the case of a dialog window, the parent window would be the dialog window, and the identifier would be the button identifier from the dialog template. | |||
Button-control text is stored as window text. An application can set and retrieve this text by using the WinSetWindowText and WinQueryWindowText functions. To set the size, position, and visibility of a button control, an application uses the standard window functions. | |||
===Custom Buttons === | ===Custom Buttons === | ||
An application can customize the appearance of a button by using the BS_USERBUTTON style in combination with other button styles. The owner window receives WM_CONTROL messages for these custom buttons whenever they must be drawn, highlighted, or disabled. | |||
When a button must be drawn, the owner window receives a WM_CONTROL message with the high word of the first parameter equal to BN_PAINT. The second parameter is a pointer to a USERBUTTON structure that contains information the application needs to draw the button. | |||
An application uses the hwnd member of the USERBUTTON structure in a call to the WinQueryWindowRect function to find the bounding rectangle for the button. The hps member is used as a presentation space for any drawing. The fsState member contains flags that tell an application how to draw the button: highlighted, unhighlighted, or disabled. The fsStateOld member contains flags that describe the current highlighted, unhighlighted, or disabled state of the button. | |||
==Using Button Controls== | ==Using Button Controls== | ||
This section explains how to perform the following tasks: | |||
* Create a dialog template for a button resource | |||
* Create a button for a client window | |||
An application creates a group by setting the WS_GROUP style bit for the first member of the group. | |||
===Using Buttons in a Dialog Window=== | ===Using Buttons in a Dialog Window=== | ||
You can define dialog-window buttons as part of a dialog template in a resource-definition file, as shown in the following Resource Compiler source-code fragment. | |||
<PRE> | |||
DLGTEMPLATE IDD_BUTTON | |||
BEGIN | |||
DIALOG "", 2, 10, 10, 235, 180, WS_VISIBLE, FCF_DLGBORDER | |||
BEGIN | |||
AUTORADIOBUTTON "Radio~1", ID_RADIO1, 15, 80, 45, 12, WS_GROUP | |||
AUTORADIOBUTTON "Radio~2", ID_RADIO2, 15, 60, 45, 12 | |||
AUTORADIOBUTTON "Radio~3", ID_RADIO3, 15, 40, 45, 12 | |||
AUTORADIOBUTTON "Radio~4", ID_RADIO4, 15, 20, 45, 12 | |||
PUSHBUTTON "Button 1", ID_PUSH1, 20 100, 50, 14, WS_GROUP | |||
PUSHBUTTON "Button 2", ID_PUSH2, 75, 100, 50, 14, WS_GROUP | |||
PUSHBUTTON "Button 3", ID_PUSH3, 130, 100, 50, 14, WS_GROUP | |||
CHECKBOX "Check Box 1", ID_CHECK1, 150, 65, 65, 12, WS_GROUP | |||
CHECKBOX "no toggle", ID_CHECK2, 150, 40, 58, 12, WS_GROUP | |||
AUTOCHECKBOX "Check Box 3", ID_CHECK3, 150, 20, 65, 12, WS_GROUP | |||
DEFPUSHBUTTON "OK", DID_OK, 75, 26, 46, 20, WS_GROUP | |||
END | |||
END | |||
</PRE> | |||
Each button in a dialog window has an identifier (for example, ID_RADIO1) that allows an application to identify the source of the WM_COMMAND and WM_CONTROL messages. An application can use the identifier as the second argument of the WinWindowFromID function to retrieve the button-window handle. | |||
The dialog template also contains the text for each button. For push buttons, this text is displayed in a rectangular box. If the text is too long to fit in the box, the text is clipped. For radio buttons and check boxes, text is displayed to the right of the button. A user selects the button by clicking either the button or the text itself. | |||
The WS_GROUP style identifies the beginning of each new group of buttons. In the preceding example, the four auto-radio buttons are in the same group, and each of the other buttons is in its own group. The auto-radio buttons in the first group can be selected one at a time only. An application must ensure that only one check box in a group is selected at a time. The order in which items can be selected in the group can wrap around from the end of the item list to its beginning. | |||
Notice that the DEFPUSHBUTTON style in the preceding example has the identifier DID_OK. It is customary to include an OK button with this identifier in most dialog windows to provide a uniform user interface. The DEFPUSHBUTTON style draws a thick border around a button and allows a user to select the button by pressing the spacebar. | |||
The dialog-window procedure for a dialog window that contains buttons must respond to WM_COMMAND and WM_CONTROL messages. A common strategy is to use auto-radio buttons and auto-check boxes to let the user set a list of capabilities for a command, and, then, let the user execute the command by choosing an OK push button. With this strategy, the dialog-window procedure ignores all WM_CONTROL messages that come from auto-radio buttons and auto-check boxes. When the dialog-window procedure receives a WM_COMMAND message for the OK push button, the procedure should query the auto-radio buttons and auto-check boxes to determine which options have been selected. | |||
===Using Buttons in a Client Window=== | ===Using Buttons in a Client Window=== | ||
An application can create a button control using an application client window as the owner. The following code fragment shows how an application can use buttons in client windows: | |||
<PRE> | |||
#define ID_PBWINDOW 110 | |||
HWND hwndButton,hwndClient; | |||
/* Create a button window. */ | |||
hwndButton = WinCreateWindow(hwndClient, /* Parent window */ | |||
WC_BUTTON, /* Class window */ | |||
"Test Button" /* Button text */ | |||
WS_VISIBLE | /* Visible style */ | |||
BS_PUSHBUTTON, /* Button style */ | |||
10, 10, /* x, y */ | |||
70, 60, /* cx, cy */ | |||
hwndClient, /* Owner window */ | |||
HWND_TOP, /* Top of z-order */ | |||
ID_PBWINDOW, /* Identifier */ | |||
NULL, /* Control data */ | |||
NULL); /* parameters */ | |||
</PRE> | |||
Once created in the client window, the button control posts a WM_COMMAND message or sends a WM_CONTROL message to the client-window procedure. This window procedure should examine the message identifier to determine which button posted or sent the message. | |||
An application that has client-window buttons can move and size the buttons when the client window receives a WM_SIZE message. An application can move and size a window by using the WinSetWindowPos function. An application can obtain a window handle for a button control by calling the WinWindowFromID function, specifying the handle of the parent window and the window identifier for each button. | |||
===Creating Buttons with Icons and Icon/Text Combinations=== | ===Creating Buttons with Icons and Icon/Text Combinations=== | ||
The following styles generate buttons containing images or icons: | |||
* BS_ICON | |||
* BS_MINIICON | |||
* BS_BITMAP | |||
The image or icon is activated by specifying the image ID in the button text string. For example, to load an icon (#define ICON_ID 300) and display it with the button, the button text string is set to "#300". | |||
Where text is to be combined with an image, BS_TEXT is selected. To display an icon (#define ICON_ID 300) with the words "My button", the button text string is set to "#300\tMy button". Notice that "\t" is used to separate text from the image ID. | |||
The following code example creates a customized button with text. | |||
<PRE> | |||
// presparm.c -- demonstrates presentation parameters// creates a button as a child window | |||
// and sets its text color | |||
#define INCL_WIN | |||
#define INCL_GPI | |||
#include <os2.h> | |||
#include <string.h> | |||
#include "presparm.h" | |||
#include "migrate.h" | |||
int main ( int argc, char *argv[]); | |||
// Internal function prototypes | |||
MRESULT EXPENTRY MyWindowProc( HWND hwnd, MSGID msg | |||
, MPARAM mp1, MPARAM mp2 ); | |||
int main ( int argc, char *argv[]); | |||
// global variables | |||
HAB hab; // Anchor block handle | |||
int main ( int argc, char *argv[]) | |||
{ | |||
HMQ hmq; // Message queue handle | |||
HWND hwndFrame; // Frame window handle | |||
HWND hwndClient; // Client window handle | |||
QMSG qmsg; // Message from message queue | |||
ULONG flCreate; // Window creation control flags | |||
hab = WinInitialize( 0 ); | |||
hmq = WinCreateMsgQueue( hab, 0 ); | |||
WinRegisterClass( hab, "presparm", MyWindowProc, 0L, 0 ); | |||
flCreate = FCF_SYSMENU | FCF_SIZEBORDER | FCF_TITLEBAR | | |||
FCF_MINMAX | FCF_SHELLPOSITION | FCF_TASKLIST; | |||
hwndFrame = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE, &flCreate, | |||
"presparm", "", 0L, 0, ID_WINDOW, &hwndClient ); | |||
while( WinGetMsg( hab, &qmsg, 0, 0, 0 ) ) | |||
WinDispatchMsg( hab, &qmsg ); | |||
WinDestroyWindow( hwndFrame ); | |||
WinDestroyMsgQueue( hmq ); | |||
WinTerminate( hab ); | |||
return 0; | |||
} | |||
// | |||
MRESULT EXPENTRY MyWindowProc( HWND hwnd, MSGID msg | |||
, MPARAM mp1, MPARAM mp2 ) | |||
{ | |||
HPS hps; // PS handle | |||
BTNCDATA btn; | |||
typedef struct _FORECOLORPARAM | |||
{ | |||
ULONG id; | |||
ULONG cb; | |||
ULONG ulColor; | |||
} FORECOLORPARAM; | |||
typedef struct _FONTPARAM | |||
{ | |||
ULONG id; | |||
ULONG cb; | |||
CHAR szFontNameSize[20]; | |||
} FONTPARAM; | |||
struct _PRES // pres. params | |||
{ | |||
ULONG cb; // length | |||
FORECOLORPARAM fcparam; // foreground color | |||
FONTPARAM fntparam; // font name & size | |||
} pres; | |||
static HWND hwndButton; // button window handle | |||
static POINTL pt; // window size | |||
switch( msg ) | |||
{ | |||
case WM_CLOSE: | |||
WinPostMsg( hwnd, WM_QUIT, 0L, 0L ); | |||
return ( (MRESULT) 0 ); | |||
case WM_CREATE: | |||
// set the foreground color to CLR_RED in | |||
// the button's presentation parameters | |||
pres.fcparam.id = PP_FOREGROUNDCOLORINDEX; | |||
pres.fcparam.cb = sizeof ( pres.fcparam.ulColor ); | |||
pres.fcparam.ulColor = CLR_RED; | |||
// set the font used by the button to 12 point Courier | |||
pres.fntparam.id = PP_FONTNAMESIZE; | |||
pres.fntparam.cb = 20; | |||
strcpy ( pres.fntparam.szFontNameSize, "24.Helv" ); | |||
pres.cb = sizeof ( pres.fcparam ) + sizeof ( pres.fntparam ) | |||
hwndButton = WinCreateWindow ( hwnd // parent | |||
, WC_BUTTON // class | |||
, "#300\tNumber One" // window text | |||
, BS_PUSHBUTTON | | |||
BS_ICON | BS_TEXT // style | |||
, 100, 100 // x, y | |||
, 400, 400 // cx, cy | |||
, hwnd // owner | |||
, HWND_TOP // sibling | |||
, 255 // ID | |||
, NULL // ctrl data | |||
, &pres ); // pres. params | |||
// pmassert | |||
( hwndButton, hab ); | |||
return (MRESULT)FALSE; | |||
case WM_SIZE: | |||
pt.x = (LONG) SHORT1FROMMP ( mp2 ); | |||
pt.y = (LONG) SHORT2FROMMP ( mp2 ); | |||
WinSetWindowPos ( hwndButton, HWND_TOP | |||
, (SHORT)pt.x / 3 | |||
, (SHORT)pt.y / 2 | |||
, (SHORT)pt.x / 2 | |||
, (SHORT)pt.y / 3 | |||
, SWP_SIZE | SWP_MOVE | SWP_SHOW ); | |||
return (MRESULT)0; | |||
case WM_PAINT: | |||
hps = WinBeginPaint ( hwnd , 0 , NULL ); | |||
GpiErase ( hps ); | |||
WinEndPaint ( hps ); | |||
return ( (MRESULT) 0 ); | |||
default: | |||
return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) ); | |||
} | |||
return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) ); | |||
</PRE> | |||
[[Category:PM Guide]] |
Latest revision as of 04:47, 19 April 2025
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
A button is a type of control window used to initiate an operation or to set the attributes of an operation. This chapter describes how to create and use buttons in PM applications.
About Button Controls
A button control can appear alone or with a group of other buttons. When buttons are grouped, the user can move from button to button within the group by pressing the Arrow keys. The user also can move among groups by pressing the Tab key.
A user can select a button by clicking it with the mouse, pressing the spacebar when the button has the keyboard focus, or sending a BM_CLICK message. In most cases, a button changes its appearance when selected.
A button control is always owned by another window, usually a dialog window or an application's client window. A button control posts WM_COMMAND messages or sends WM_CONTROL notification messages to its owner when a user selects the button. For further information on messages generated, see Button Notification Messages. The owner window receives messages from a button control and can send messages to the button to alter its position, appearance, and enabled/disabled state.
To use a button control in a dialog window, an application specifies the control in a dialog template in the application's resource-definition file. The application processes button messages in the dialog-window procedure.
An application creates a button control in a client window by calling WinCreateWindow, specifying a window class of WC_BUTTON, and identifying the client window as the owner of the button control.
Button Types
There are four main types of buttons: push buttons, radio buttons, check boxes, and three-state check boxes. A button's type determines how the button looks and behaves.
A radio button, check box, or three-state check box controls an operation; a push button initiates an operation. For example, a user might set printing options (such as paper size, print quality, and printer type) in a print-command dialog window containing an array of radio buttons and check boxes. After setting the options, the user would select a push button to tell an application that printing should begin (or be canceled). Then, the application would query the state of each check box and radio button to determine the printing parameters.
Push Buttons
A push button is a rectangular window typically used to enable the user to start or stop an operation. When selected, a push button control posts a WM_COMMAND message to its owner window.
The push button can contain a text string, an icon or mini-icon, or a combination of text and images.
Radio Buttons
A radio button is a window with text displayed to the right of a small circular indicator. Each time the user selects a radio button, that button's state toggles between selected and unselected. This state remains until the next time the user selects the button. An application typically uses radio buttons in groups.
Within a group, usually one button is selected by default, and the user can move the selection to another button by using the cursor keys; however, only one button can be selected at a time. Radio buttons are appropriate if an exclusive choice is required from a fixed list of related options. For example, applications often use radio buttons to allow the user to select the screen foreground and background colors. A radio-button control sends WM_CONTROL messages to its owner window.
Check Boxes
Check boxes are similar to radio buttons, except that they can offer multiple-choice selection as well as individual choice. Check boxes offer the user a fixed list of choices, with the option of selecting more than one, or even all.
Check boxes also toggle application features on or off. For example, a word processing application might use a check box to let the user turn word wrapping on or off. A check-box control sends WM_CONTROL messages to its owner window.
Three-State Check Boxes
Three-state check boxes are similar to check boxes, except that they can be displayed in halftone as well as selected and unselected. An application might use the halftone state to indicate that, currently, the checkbox is not selectable. A three-state check-box control sends WM_CONTROL messages and posts WM_COMMAND messages to its owner window.
Application-defined Buttons
In addition to using the four predefined button-control types, an application can create button controls that appear as defined by the owner window. When they must be drawn or highlighted, these button controls send WM_CONTROL messages with BN_PAINT as the notification code to their owner windows.
Button Styles
The following table describes the button styles an application can use when creating button controls:
Style | Description |
---|---|
BS_3STATE | Creates a three-state check box (see also BS_CHECKBOX). When the user selects the check box, it sends a WM_CONTROL message to the owner window. The owner should set the check box to the appropriate state: selected, unselected, or halftone. |
BS_AUTO3STATE | Creates an auto-three-state check box (see also BS_CHECKBOX). When the user selects the check box, the system automatically sets the check box to the appropriate state: selected, unselected, or halftone. |
BS_AUTOCHECKBOX | Creates an auto-check box (see also BS_CHECKBOX). The system automatically toggles the check box between the selected and unselected states each time the user selects the box. |
BS_AUTORADIOBUTTON | Creates an auto-radio button (see also BS_RADIOBUTTON). When the user selects an auto-radio button, the system automatically selects the button and removes the selection from the other auto-radio buttons in the group. |
BS_AUTOSIZE | Creates a button that is sized automatically to ensure that the contents fit. Note: The cx or cy parameter of WinCreateWindow must be specified as -1 to implement the autosize feature. |
BS_BITMAP | Creates a push button containing a bit map instead of text. This style can only be implemented with BS_PUSHBUTTON. |
BS_CHECKBOX | Creates a check box-a small square that has text displayed to its right. When the user selects a check box, the check box sends a WM_CONTROL message to the owner window. The owner window should toggle the check box between selected and unselected states. |
BS_DEFAULT | Creates a push button that has a heavy black border. The user can select this push button by pressing the spacebar. This style is useful for letting the user quickly select the most likely set of options in a dialog window. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. |
BS_HELP | Creates a push button that posts a WM_HELP message (instead of a WM_COMMAND message) to its owner window when the user selects the button. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. |
BS_ICON | Creates a push button containing an icon instead of text. |
BS_MINIICON | Creates a push button containing a mini-icon instead of text. |
BS_NOBORDER | Creates a push button that has no border. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. |
BS_NOCURSORSELECT | Creates an auto-radio button that will not be selected automatically when the user moves the cursor to the button using the cursor-movement keys. This style is valid only in combination with the BS_AUTORADIOBUTTON style or the AUTORADIOBUTTON statement in a resource-definition file. |
BS_NOPOINTERFOCUS | Creates a radio button or check box that does not receive the keyboard focus when the user selects it. This style is valid in combination with the BS_AUTORADIOBUTTON, BS_RADIOBUTTON, BS_3STATE, BS_AUTO3STATE, BS_AUTOCHECKBOX, and BS_CHECKBOX styles, or the AUTORADIOBUTTON, RADIOBUTTON, AUTOCHECKBOX, or CHECKBOX statements in a resource-definition file. |
BS_NOTEBOOKBUTTON | Creates a notebook button, which is identical to a pushbutton except that when it is created as a child of a notebook page it becomes a button in the common button area of the notebook page. If the button is not in a notebook page it will be indistinguishable from a pushbutton. |
BS_PUSHBUTTON | Creates a push button-a round-cornered rectangle with text displayed inside it. When selected, the push button posts a WM_COMMAND message to its owner window. |
BS_RADIOBUTTON | Creates a radio button-a small circle that has text displayed to its right. Radio buttons usually are used in groups of related, but exclusive, choices. When the user selects a radio button, the button sends a WM_CONTROL message to its owner window. The user should select the button and remove the selection from the other radio buttons in the group. |
BS_SYSCOMMAND | Creates a button that posts a WM_SYSCOMMAND message (instead of a WM_COMMAND message) to the owner window when the user selects the button. This style is valid only in combination with the BS_PUSHBUTTON style or the PUSHBUTTON statement in a resource-definition file. |
BS_TEXT | Creates a push button containing both text and icons/mini-icons. |
BS_USERBUTTON | Creates a user-defined button that sends a WM_CONTROL message to the owner window when the button needs to be drawn, highlighted, or disabled. A user-defined button also posts WM_COMMAND messages to the owner window when the user selects the button. |
Default Button Behavior
Following are the messages processed by the predefined button-control window class (WC_BUTTON). Each message is described in terms of how a button control responds to that message.
Message | Description |
---|---|
BM_AUTOSIZE | Causes the buttons in a new-style notebook to automatically size to fit their contents. |
BM_CLICK | Sends a WM_BUTTON1DOWN and WM_BUTTON1UP message to itself to simulate a user button selection. |
BM_QUERYCHECK | Returns the checked state of the button. |
BM_QUERYCHECKINDEX | Returns the 0-based index to the selected button in a group. Returns -1 if no button in the group is selected or if the button receiving the message is not a radio button or an auto-radio button. |
BM_QUERYHILITE | Returns the highlighted state of the button. |
BM_SETCHECK | Sets the checked state of the button and returns the previous checked state. |
BM_SETDEFAULT | Sets the default button state and redraws the button. |
BM_SETHILITE | Sets the highlighted state of the button and returns the previous highlighted state. |
WM_BUTTON1DBLCLK | Highlights the button and sends a BN_DBLCLICKED notification code when the button-up message arrives. |
WM_BUTTON1DOWN | Sets the button window so it can capture mouse input. |
WM_BUTTON1UP | If the button window is set to capture mouse input, and if the mouse pointer is inside the button window when the mouse button is released, this message releases the mouse and sends a notification message to the owner window. If the button is a push button, the push button control posts a WM_COMMAND message; otherwise, the button control sends a WM_CONTROL message with the BN_CLICKED notification code. |
WM_CHAR | Sets the button window so it can capture mouse input when the spacebar is pressed; releases the mouse when the spacebar is released. Passes other key messages to the default window procedure. |
WM_CREATE | Validates the requested button style and sets the window text. |
WM_DESTROY | Frees the memory containing the window's text. |
WM_ENABLE | Sent when an application changes the enabled state of a window. |
WM_MATCHMNEMONIC | Returns TRUE if mp1 matches a mnemonic in the control window's text. |
WM_MOUSEMOVE | Sets the default mouse pointer. If the button has the mouse captured, the button's highlighted state changes as the mouse pointer moves in and out of the button boundary. |
WM_PAINT | Draws the button according to its style and current state. |
WM_QUERYDLGCODE | Returns the DLGC_BUTTON code combined with other DLGC_ codes that designate the button's type. |
WM_QUERYWINDOWPARAMS | Returns the requested window parameters. |
WM_SETFOCUS | Creates a cursor if the button-control window is receiving the focus. Destroys the cursor if the button-control window is losing the focus. |
WM_SETWINDOWPARAMS | Sets the requested window parameters and redraws the button, including the cursor, if the button-control window has the focus. |
Button Notification Messages
A button, regardless of its style or type, posts a message to its owner when selected by the user. The message posted by push buttons is ordinarily WM_COMMAND. However, for buttons created with the BS_PUSHBUTTON or BS_USERBUTTON style, the message posted can be changed to WM_HELP or WM_SYSCOMMAND by additionally specifying either the BS_HELP or BS_SYSCOMMAND styles, respectively, when creating the button. A button control that has a style other than BS_PUSHBUTTON or BS_USERBUTTON sends WM_CONTROL messages to its owner when the user selects it.
When the user selects a push button using the mouse pointer, the system automatically highlights the button. The button's window procedure tracks the movement of the pointer until the user releases the button. If the user moves the pointer so that it is outside the button boundary, the system turns off the highlight. The push button control does not post a WM_COMMAND message until the user releases the pointer button, and then, only if the button is released inside the push button boundary. When the owner window receives a WM_COMMAND message from a push button, the low word of the first parameter in the message contains the identifier of the button as specified either in the dialog template or in the WinCreateWindow function when the button was created.
An application should avoid duplicating identifiers for menu items and button controls, because both the items and the controls post identifiers to owner windows as WM_COMMAND messages. However, the application can determine whether a WM_COMMAND message came from a menu or a push button control by looking for the value CMDSRC_MENU or CMDSRC_PUSHBUTTON in the low word of the message's second parameter.
When the user selects any button other than a push button, that button sends a WM_CONTROL message. The application can examine SHORT1FROMMP(mp1) in the WM_CONTROL message to find the button identifier, and can examine SHORT2FROMMP(mp1) to determine the notification code for the control message. The notification code can be one of the following:
Code | Description |
---|---|
BN_CLICKED | The user selected the button. |
BN_DBLCLICKED | The user double-clicked the button. |
BN_PAINT | A user-defined button needs to be drawn. Buttons with the BS_USERBUTTON style send this notification code to instruct the owner window to draw the button control. The second message parameter of the WM_CONTROL message contains a pointer to a USERBUTTON structure that contains the information necessary for drawing the button. |
When the user selects a check box or radio button, the button control sends the WM_CONTROL message with the BN_CLICKED notification code to the owner window. In response, the owner window should set the display state of the button by sending the appropriate message back to the button.
An application need not respond to WM_CONTROL messages sent by an auto-check box or an auto-radio button; the system automatically sets the states of these buttons.
Button States
An application can query and set the highlighted and checked states of its buttons by sending messages to them. An application can obtain the handle of a button by calling WinWindowFromID, using the parent window handle and the identifier of the button. In the case of a dialog window, the parent window would be the dialog window, and the identifier would be the button identifier from the dialog template.
Button-control text is stored as window text. An application can set and retrieve this text by using the WinSetWindowText and WinQueryWindowText functions. To set the size, position, and visibility of a button control, an application uses the standard window functions.
Custom Buttons
An application can customize the appearance of a button by using the BS_USERBUTTON style in combination with other button styles. The owner window receives WM_CONTROL messages for these custom buttons whenever they must be drawn, highlighted, or disabled.
When a button must be drawn, the owner window receives a WM_CONTROL message with the high word of the first parameter equal to BN_PAINT. The second parameter is a pointer to a USERBUTTON structure that contains information the application needs to draw the button.
An application uses the hwnd member of the USERBUTTON structure in a call to the WinQueryWindowRect function to find the bounding rectangle for the button. The hps member is used as a presentation space for any drawing. The fsState member contains flags that tell an application how to draw the button: highlighted, unhighlighted, or disabled. The fsStateOld member contains flags that describe the current highlighted, unhighlighted, or disabled state of the button.
Using Button Controls
This section explains how to perform the following tasks:
- Create a dialog template for a button resource
- Create a button for a client window
An application creates a group by setting the WS_GROUP style bit for the first member of the group.
Using Buttons in a Dialog Window
You can define dialog-window buttons as part of a dialog template in a resource-definition file, as shown in the following Resource Compiler source-code fragment.
DLGTEMPLATE IDD_BUTTON BEGIN DIALOG "", 2, 10, 10, 235, 180, WS_VISIBLE, FCF_DLGBORDER BEGIN AUTORADIOBUTTON "Radio~1", ID_RADIO1, 15, 80, 45, 12, WS_GROUP AUTORADIOBUTTON "Radio~2", ID_RADIO2, 15, 60, 45, 12 AUTORADIOBUTTON "Radio~3", ID_RADIO3, 15, 40, 45, 12 AUTORADIOBUTTON "Radio~4", ID_RADIO4, 15, 20, 45, 12 PUSHBUTTON "Button 1", ID_PUSH1, 20 100, 50, 14, WS_GROUP PUSHBUTTON "Button 2", ID_PUSH2, 75, 100, 50, 14, WS_GROUP PUSHBUTTON "Button 3", ID_PUSH3, 130, 100, 50, 14, WS_GROUP CHECKBOX "Check Box 1", ID_CHECK1, 150, 65, 65, 12, WS_GROUP CHECKBOX "no toggle", ID_CHECK2, 150, 40, 58, 12, WS_GROUP AUTOCHECKBOX "Check Box 3", ID_CHECK3, 150, 20, 65, 12, WS_GROUP DEFPUSHBUTTON "OK", DID_OK, 75, 26, 46, 20, WS_GROUP END END
Each button in a dialog window has an identifier (for example, ID_RADIO1) that allows an application to identify the source of the WM_COMMAND and WM_CONTROL messages. An application can use the identifier as the second argument of the WinWindowFromID function to retrieve the button-window handle.
The dialog template also contains the text for each button. For push buttons, this text is displayed in a rectangular box. If the text is too long to fit in the box, the text is clipped. For radio buttons and check boxes, text is displayed to the right of the button. A user selects the button by clicking either the button or the text itself.
The WS_GROUP style identifies the beginning of each new group of buttons. In the preceding example, the four auto-radio buttons are in the same group, and each of the other buttons is in its own group. The auto-radio buttons in the first group can be selected one at a time only. An application must ensure that only one check box in a group is selected at a time. The order in which items can be selected in the group can wrap around from the end of the item list to its beginning.
Notice that the DEFPUSHBUTTON style in the preceding example has the identifier DID_OK. It is customary to include an OK button with this identifier in most dialog windows to provide a uniform user interface. The DEFPUSHBUTTON style draws a thick border around a button and allows a user to select the button by pressing the spacebar.
The dialog-window procedure for a dialog window that contains buttons must respond to WM_COMMAND and WM_CONTROL messages. A common strategy is to use auto-radio buttons and auto-check boxes to let the user set a list of capabilities for a command, and, then, let the user execute the command by choosing an OK push button. With this strategy, the dialog-window procedure ignores all WM_CONTROL messages that come from auto-radio buttons and auto-check boxes. When the dialog-window procedure receives a WM_COMMAND message for the OK push button, the procedure should query the auto-radio buttons and auto-check boxes to determine which options have been selected.
Using Buttons in a Client Window
An application can create a button control using an application client window as the owner. The following code fragment shows how an application can use buttons in client windows:
#define ID_PBWINDOW 110 HWND hwndButton,hwndClient; /* Create a button window. */ hwndButton = WinCreateWindow(hwndClient, /* Parent window */ WC_BUTTON, /* Class window */ "Test Button" /* Button text */ WS_VISIBLE | /* Visible style */ BS_PUSHBUTTON, /* Button style */ 10, 10, /* x, y */ 70, 60, /* cx, cy */ hwndClient, /* Owner window */ HWND_TOP, /* Top of z-order */ ID_PBWINDOW, /* Identifier */ NULL, /* Control data */ NULL); /* parameters */
Once created in the client window, the button control posts a WM_COMMAND message or sends a WM_CONTROL message to the client-window procedure. This window procedure should examine the message identifier to determine which button posted or sent the message.
An application that has client-window buttons can move and size the buttons when the client window receives a WM_SIZE message. An application can move and size a window by using the WinSetWindowPos function. An application can obtain a window handle for a button control by calling the WinWindowFromID function, specifying the handle of the parent window and the window identifier for each button.
Creating Buttons with Icons and Icon/Text Combinations
The following styles generate buttons containing images or icons:
- BS_ICON
- BS_MINIICON
- BS_BITMAP
The image or icon is activated by specifying the image ID in the button text string. For example, to load an icon (#define ICON_ID 300) and display it with the button, the button text string is set to "#300".
Where text is to be combined with an image, BS_TEXT is selected. To display an icon (#define ICON_ID 300) with the words "My button", the button text string is set to "#300\tMy button". Notice that "\t" is used to separate text from the image ID.
The following code example creates a customized button with text.
// presparm.c -- demonstrates presentation parameters// creates a button as a child window // and sets its text color #define INCL_WIN #define INCL_GPI #include <os2.h> #include <string.h> #include "presparm.h" #include "migrate.h" int main ( int argc, char *argv[]); // Internal function prototypes MRESULT EXPENTRY MyWindowProc( HWND hwnd, MSGID msg , MPARAM mp1, MPARAM mp2 ); int main ( int argc, char *argv[]); // global variables HAB hab; // Anchor block handle int main ( int argc, char *argv[]) { HMQ hmq; // Message queue handle HWND hwndFrame; // Frame window handle HWND hwndClient; // Client window handle QMSG qmsg; // Message from message queue ULONG flCreate; // Window creation control flags hab = WinInitialize( 0 ); hmq = WinCreateMsgQueue( hab, 0 ); WinRegisterClass( hab, "presparm", MyWindowProc, 0L, 0 ); flCreate = FCF_SYSMENU | FCF_SIZEBORDER | FCF_TITLEBAR | FCF_MINMAX | FCF_SHELLPOSITION | FCF_TASKLIST; hwndFrame = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE, &flCreate, "presparm", "", 0L, 0, ID_WINDOW, &hwndClient ); while( WinGetMsg( hab, &qmsg, 0, 0, 0 ) ) WinDispatchMsg( hab, &qmsg ); WinDestroyWindow( hwndFrame ); WinDestroyMsgQueue( hmq ); WinTerminate( hab ); return 0; } // MRESULT EXPENTRY MyWindowProc( HWND hwnd, MSGID msg , MPARAM mp1, MPARAM mp2 ) { HPS hps; // PS handle BTNCDATA btn; typedef struct _FORECOLORPARAM { ULONG id; ULONG cb; ULONG ulColor; } FORECOLORPARAM; typedef struct _FONTPARAM { ULONG id; ULONG cb; CHAR szFontNameSize[20]; } FONTPARAM; struct _PRES // pres. params { ULONG cb; // length FORECOLORPARAM fcparam; // foreground color FONTPARAM fntparam; // font name & size } pres; static HWND hwndButton; // button window handle static POINTL pt; // window size switch( msg ) { case WM_CLOSE: WinPostMsg( hwnd, WM_QUIT, 0L, 0L ); return ( (MRESULT) 0 ); case WM_CREATE: // set the foreground color to CLR_RED in // the button's presentation parameters pres.fcparam.id = PP_FOREGROUNDCOLORINDEX; pres.fcparam.cb = sizeof ( pres.fcparam.ulColor ); pres.fcparam.ulColor = CLR_RED; // set the font used by the button to 12 point Courier pres.fntparam.id = PP_FONTNAMESIZE; pres.fntparam.cb = 20; strcpy ( pres.fntparam.szFontNameSize, "24.Helv" ); pres.cb = sizeof ( pres.fcparam ) + sizeof ( pres.fntparam ) hwndButton = WinCreateWindow ( hwnd // parent , WC_BUTTON // class , "#300\tNumber One" // window text , BS_PUSHBUTTON | BS_ICON | BS_TEXT // style , 100, 100 // x, y , 400, 400 // cx, cy , hwnd // owner , HWND_TOP // sibling , 255 // ID , NULL // ctrl data , &pres ); // pres. params // pmassert ( hwndButton, hab ); return (MRESULT)FALSE; case WM_SIZE: pt.x = (LONG) SHORT1FROMMP ( mp2 ); pt.y = (LONG) SHORT2FROMMP ( mp2 ); WinSetWindowPos ( hwndButton, HWND_TOP , (SHORT)pt.x / 3 , (SHORT)pt.y / 2 , (SHORT)pt.x / 2 , (SHORT)pt.y / 3 , SWP_SIZE | SWP_MOVE | SWP_SHOW ); return (MRESULT)0; case WM_PAINT: hps = WinBeginPaint ( hwnd , 0 , NULL ); GpiErase ( hps ); WinEndPaint ( hps ); return ( (MRESULT) 0 ); default: return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) ); } return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );