checkbox - change notification - windows

What notification code is sent with the wm_command message to the dialog box procedure when a check box changes state?
And more importantly, where would I look in the msdn to find the notification codes for various controls?

Note that Check boxes and Radio buttons are Buttons. So they send click and double click messages, BN_CLICKED and BN_DOUBLECLICKED.
If you use MFC, then you can examine the check state with CButton::GetCheck method.
Otherwise you send the BM_GETCHECK message to the control: SendMessage(button_handle, BM_GETCHECK, 0, 0);
SendMessage can return
BST_CHECKED Button is checked.
BST_INDETERMINATE Button is grayed, indicating an indeterminate state
(applies only if the button has the BS_3STATE or BS_AUTO3STATE style).
BST_UNCHECKED Button is cleared
If the button has a style other than those listed, the return value is zero.
If you use the Visual Studio, the easiest way to get a list of events/messages a control can send is to go to Resource/Design view, right click a control and select Events.
For a list of common controls see: Control Library
(in the page you'll see a popup menu with the controls if you hover the cursor on the Control Library link)

It's BN_CLICKED. The bottom of the page links to the button messages.

Related

Do I have the right idea with using SetCapture() for a windowless checkbox?

My Table control uses windowless checkboxes (because there can be an arbitrary number of checkboxes here). Right now, I use TrackMouseEvent(TME_LEAVE) and manually checking if the mouse is in the checkbox rect during a WM_LBUTTONUP. I have TODOs marked in my code for the edge cases that this causes, such as a missing WM_LBUTTONUP when the mouse has left the client area.
Now I notice today's The Old New Thing says buttons use mouse captures. This got me thinking, and after looking into it, mouse captures would fit what I need more appropriately; if my assumptions are correct it would handle the various edge cases I mentioned above and be more correct in general.
In particular, the assumptions I make are: I should abandon any capture-related operations on a WM_CAPTURECHANGED even if every other condition is met. I will get a WM_CAPTURECHANGED after a ReleaseCapture(). After a SetCapture(), I will always end with either a WM_LBUTTONUP or a WM_CAPTURECHANGED, whichever comes first.
I've read both MSDN and a few articles I've found by Googling "setcapture correct use"; I just want to make sure I've got the right idea and will be implementing this correctly. Do I?
on WM_LBUTTONDOWN
if the button is in a checkbox
SetCapture()
mark that we're in checkbox clicking mode
on WM_MOUSEMOVE
if we are in checkbox clicking mode
draw the checkbox in the pressed state
on WM_LBUTTONUP
if we are in checkbox clicking mode
leave checkbox clicking mode
THEN call ReleaseCapture(), so we can ignore its WM_CAPTURECHANGED
if the mouse was released in the same checkbox
toggle it
on WM_CAPTURECHANGED
if we are in checkbox clicking mode
abandon checkbox clicking mode and leave the checkbox untoggled, even if the mouse is hovering over the checkbox
Do I have the right idea here? And in particular, is my order of operations for WM_LBUTTONDOWN correct? Thanks.
What you have said is basically right, although a real checkbox tracks WM_MOUSEMOVE while in "clicking mode" and displays the checkbox in its original state if the mouse moves off of it. So to emulate that you should have:
on WM_MOUSEMOVE
if we are in checkbox clicking mode
if mouse is over the checkbox
draw the checkbox in the pressed (toggled) state
else
draw the checkbox in the original state

Win32, How to access button on toolbar

Let's say I have a compiled binary program that runs and exposes some GUI on the screen.
I need from another program in Win32 to access its toolbar, find a button and click on it.
I know how to find Hwnd of the toolbar, but I don't really know how to enumerate the buttons on it.
Any ideas how to do it in Win32 calls?
Is there any tool like Spy++ that is capable of showing button handles under toolbar?
Spy++ doesn't do it.
Thanks
If it is a standard Win32 Toolbar control, then you send the toolbar a TB_BUTTONCOUNT message to determine how many buttons are on the toolbar, then send a TB_GETBUTTON message to retrieve information about a button at a given index.
The tricky part is that the TBBUTTON structure that receives the button info needs to be allocated in the same process that owns the toolbar, so you will have to:
call GetWindowThreadProcessId() to retrieve the toolbar's process ID
call OpenProcess() to get a HANDLE to that process
call VirtualAllocEx() to allocate the structure inside of that process
send the TB_GETBUTTON message(s) to the toolbar, specifying the pointer returned by VirtualAllocEx()
call ReadProcessMemory() to copy the structure data back into your own process so you can process it as needed
call VirtualFreeEx() to free the allocated memory.
When the button is clicked it sends a WM_COMMAND message to the main window. Simulating a click on a toolbar button is not very practical. A better approach is to use Spy++ to find the WM_COMMAND message and its parameters. Then in your program send this same WM_COMMAND message.
AFAIR you can get the HWND of a toolbar button by calling GetDlgItem. The first parameter is the HWND of the toolbar, the second parameter is the ID of the button (the one you set in its TBBUTTON structure). You need to have the button ID to use this approach.
=== EDIT ===
In addition to EnumChildWindows, suggested by #graham.reeds, you can try SendInput. Move the target window to the foreground, calculate the screen coordinates of the upper-left corner of the toolbar (using its HWND), add the X-Y offset of the middle of the target button, and send a mouse click to that position. (I used this approach successfully to click on Flash and Silverlight objects rendered inside the IE window.)
Off the top of my head:
Use EnumChildWindows to find the child controls of the toolbar.
Then use GetWindowText to see if it is a button.
If it is PostMessage to it to invoke it's operation.

return key generates IDOK for button with focus

I did a SetFocus to a button in a dialog. The button gets the dashed outline. When the user presses the return key, the dialog get a IDOK message rather than a message from the button were I set the focus. The same thing happens under other circumstances.
Why is this happening? And how can I cause the return to act as a button press?
Plain c++ windows app, no MFC, no NET.
Feature, not a bug. The [Enter] key operates the button that's marked as the default button for a dialog. Either with the DEFPUSHBUTTON in the .rc file or the BS_DEFPUSHBUTTON style flag. Which is typically the "OK" button so getting IDOK back is expected. The [Escape] key is special that way too, typically the [Cancel] button. This is bound to ring a bell if you think back on how you used dialogs before.
You click a button that has the focus by pressing the space bar instead.
In another SO question I found KB article that might help you:
If a dialog box or one of its controls currently has the input focus,
then pressing the ENTER key causes Windows to send a WM_COMMAND
message with the idItem (wParam) parameter set to the ID of the
default command button. If the dialog box does not have a default
command button, then the idItem parameter is set to IDOK by default.
When an application receives the WM_COMMAND message with idItem set to
the ID of the default command button, the focus remains with the
control that had the focus before the ENTER key was pressed. Calling
GetFocus() at this point returns the handle of the control that had
the focus before the ENTER key was pressed. The application can check
this control handle and determine whether it belongs to any of the
edit controls in the dialog box. If it does, then the user was
entering data into one of the edit controls and after doing so,
pressed ENTER. At this point, the application can send the
WM_NEXTDLGCTL message to the dialog box to move the focus to the next
control.
According to MSDN,
Dialog Box Keyboard Interface
The system provides a special keyboard interface for dialog boxes that carries out special processing for several keys. The interface generates messages that correspond to certain buttons in the dialog box or changes the input focus from one control to another. Following are the keys used in this interface and their respective actions.
...
ENTER: Sends a WM_COMMAND message to the dialog box procedure. The wParam parameter is set to IDOK or control identifier of the default push button.
Since the system intercepts and processes ENTER key pressed directly through the dialog, you'll need to handle it in your dialog box procedure by calling GetFocus() to first see which control has the focus, and perform the appropriate action for that particular control.

wxPython Enter Button Event

I've seen plenty of information about this topic, but not the answer to this question exactly. I have the opposite problem of most. I want to prevent the Enter button from clicking a button when the button has focus. And to do this, I don't want to simply disable the button from accepting an Enter button press, but rather I want to conditionally capture the Enter button press in a callback method. Right now, I have bound the following event to all widgets in my python program:
parent.Bind(wx.EVT_CHAR, self.CharInputCallback)
The EVT_CHAR event is actually thrown when the enter button is pressed and I'm able to get the callback in my callback method. My problem is that the enter button's functionality of virtually clicking a button still goes through, despite purposely not skipping the event (which would forward on the event). Since this is happening, and I'm sure my callback method is not forwarding the event along (I've tested this by capturing characters going to a text box) I suspect that the enter button throws an additional event that I'm not capturing. I've tried binding and capturing the additional following events to prevent the "virtual click" from the enter button:
parent.Bind(wx.EVT_TEXT_ENTER, self.CharInputCallback)
parent.Bind(wx.EVT_KEY_UP, self.CharInputCallback)
parent.Bind(wx.EVT_KEY_DOWN, self.CharInputCallback)
Yet when I press enter, the button in focus is still clicked. To summarize, is there an additional event being thrown when I press the enter button? If so, which event in particular is "virtually clicking" the button? Most forums I've found have discussed how to recognize when the enter button is pressed, but I want to recognize it and disable it's default action when a button is in focus.
I tried binding all those events to different handlers and I also bound EVT_BUTTON. It appears that EVT_BUTTON always fires BEFORE the key and char events do. If you don't want your button to be clicked, then you'll probably have to either disable it, use a different widget (maybe one of the generic buttons) or create your own. I would also ask on the wxPython mailing list to see if they have any suggestions.
The only way to order the events in wxPython that I'm aware of is to use wx.CallAfter or wx.CallLater. I'm not sure how you'd use that in this context though.
The event that causes enter to click a button is the key up event. My code for my callback was messed up slightly. Capturing the key up event and not skipping it prevent the enter button from clicking a button in focus. On Windows 7 anyways.

GUI: should a button represent the current state or the state to be achieved through clicking the button?

GUI: should a button represent the current state or the state to be achieved through clicking the button?
I've seen both and it sometimes misleads the user. what do you think?
The label on the button should reflect what the button does, i.e. it should describe the change the button makes.
For example, if you have a call logging system a button should say "Close Call" and the user can click it to close the call. The button should not have the label "Call is Open" and the user clicks to change the call status as that's very counter-intuitive, since the button is effectively doing the opposite to what it says on it.
In my opinion the label - and so the function - of a button should rarely, if ever, change. A button is supposed to be a like a physical button and they usually only do a single thing. (There are a few exceptions like play-pause on a media player where it's OK for the button label/icon to change, but at least this is copying a button from a real physical device.)
To carry on the example from above, I would say usually you would want two buttons, "Open Call" and "Close Call" and disable whichever one is not appropriate. Ideally you'd have a field elsewhere displaying the status of the call.
In summary, buttons are for doing things not for passing on information to the user.
The button should represent the action to be executed, not the state.
Some buttons are actions and are not ambiguous, like "Save", "Print" or "Enable user".
When a button represents a state that can be toggled, like Enable and Disable something, I do one of the following:
Change the button text, and make it always point to the state that will be achieved; (i.e. make the button point to actions, not states);
- Keep the button's text the same, but use one of those sticky buttons that will stay pressed, representing that the current state is "on" or "off". I prefer the former approach, though.
It should represent the action taken when clicking the button. States should always be presented by other means.
But I know what you mean. My car radio has buttons with text that shows the current state. It is really confusing.
This depends on the function which will be triggerd by the button click.
if the click changes the state of an entity i would suggest that the button represents the state the entity will enter after clicking the button
if the click triggers some kind of functionality the button should represent the function.
The appearance of the button is also a clue to its state. It should follow the standards of the environment if any exist (example, beveled edge / shadow appears on mouse click in Windows).

Resources