"?" help button triggers WM_HELP _and_ WM_LBUTTONUP - c++

I have a Windows application that registers one CALLBACK procedure that handles WM_HELP messages for the dialog, and one CALLBACK procedure that handles WM_LBUTTONUP messages for a custom button.
Now, when the user clicks the "?" button, then clicks the custom button, the help opens up as expected (on mouse down), BUT if the help window is not occluding the button, a WM_LBUTTONUP message is triggered as well for the custom button (on mouse up). This causes the button to trigger when the user was only asking for help.
Is there any way to stop the WM_LBUTTONUP message from being sent if the button press is for help?
EDIT: The custom button is implemented using a STATIC control. I believe this is because it needs to have an image and no border. So, it does not send BN_CLICKED notifications. In fact, it does not seem to trigger WM_COMMAND in the parent at all.
Thanks

This is normal. Be sure to use the button's BN_CLICKED notification to see the difference. Generated when the user clicks the button, not generated when the user uses the help cursor. The button still sees the normal button up/down messages so that's not a good trigger to detect a click. Extra bonus is that the button can now also be clicked with the keyboard (space bar).
A good class library takes care of these nasty little details.

A better way would be to create ? as a custom control with BS_CHECKBOX | BS_PUSHLIKE style and capture the mouse. After that you will get all the WM_LBUTTONDOWN message to this custom control and then you can use WindowFromPoint to get the window where the WM_LBUTTONDOWN happened and can send a custom notification to the parent window. The parent window can then show a the tooltip or open the help doc or discard it.
The advantage is, you create the control only once and you can use it in multiple places.

Okay, I fixed it by creating the custom button (static control) with the SS_NOTIFY style, then handling the STN_CLICKED notification in the WM_COMMAND message. (SS_NOTIFY causes WM_COMMAND to trigger in the parent when it is clicked.) This does not trigger when using the "?" button. Thanks!

Related

Programmatically clicking toolbar button in parent of modal window

I have an application that hooks into another application via an API. My application launches a modal window which prevents keypresses to reach the parent as one would expect.
However due to limitations in the API I need to click one of the parents toolbar buttons from time to time (yes it's a kludge).
I wonder if this is possible while still having the modal window of my application active? Is it perhaps possible to send the required command directly into the parent command queue?
Clicking the button programmatically with no modal window should not be a problem, one could go by this link for example: http://forums.codeguru.com/showthread.php?307633-How-to-run-a-very-long-SQL-statement. But I would prefer not having to close my window each time I have to click the button.
Although the fifth answer is what I find interesting as I'm thinking this could make it possible to send the command without having to close my modal window first. Also it feels an ever so small bit less ugly.
First of all, when a modal dialog is shown, it runs its own message pump. So any attempt to fake input messages will land in the modal dialog message pump. Which is no good to you. So, you'd have to send a message rather than fake input.
However, when a modal dialog is shown, its owning windows are disabled. Which means that these windows will not respond to any messages you send. So I guess that means that you could:
Enable the owning top-level window that you hosts the toolbar in question.
Send the message to the toolbar button.
Disable the owning window again.
Not the prettiest way to go about things, but you did ask!

Keyboard messages from child controls

I am currently developing a user interface DLL that uses the WIN32 API. The DLL must work for numerous platforms, XP, WIN CE, etc. I have managed to incorporate docking, anchoring and so on but appear to have a problem regarding owner-drawn buttons. I can draw the button's correct state, focus, clicked, default. However, I cannot receive key notifications. I specifically want to perform a click operation on a button that currently has focus, should the user press enter.
Note that I am using a windows message loop rather than a dialog message loop. I use windows hooks to hook into the window creation and set the user data to 'point' to my control instance. If I test for WM_KEYDOWN in the main message loop I can get a handle to my button control instance and could forward the message to the relevant control. Unfortunately, I am dealing with a lot of legacy code and this may not be an ideal solution.
So, my question is what is the best way forward. Is subclassing the button control's window procedure a viable option or is there an easier way?
Many thanks in advance.
The comments above are correct. The button with focus should be getting the key messages. But buttons don't (by themselves) respond to Enter--they respond to Space. It sounds like what you're missing is the typical dialog keyboard navigation, like Tab key moving the focus and Enter activating the "default" button.
If you've got a typical Windows message pump, and you want the keyboard behavior normally associated with dialogs, then you need to use the IsDialogMessage API in your message loop. This means your window is essentially a "modeless dialog".
Looks like standard window proc subclassing should do the trick. See http://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx for details.

C++ Win32API WM_KEYDOWN and buttons

I'm having a problem receiving message in WM_KEYDOWN. WM_KEYDOWN works just fine until I click any button in my app. From that point it no longer receives my input from the keyboard. How to fix it?
If you are using Win32 controls such as CreateWindowEx(NULL, L"BUTTON", ... this is expected Each control is actually a child window and is capturing all of the window messages after it has focus.
Once the button is clicked you can capture the WM_COMMAND - BM_CLICK message to then call SetFocus(hwnd) to refocus on your window (as Giswin mentioned).
Probably your window has no focus before you click any button on your app. you can add code somewhere in your app to set focus programmatically:
yourwindow->SetFocus();
or use winapi:
::SetFocus(hWnd);
Just in case anyone is wondering, I (unsurprisingly) noticed the same behavior for handling WM_CHAR responses in my WindowProcedure callback as well. As soon as you click a button, the focus changes from the main window to the button control (which is a child window) and keyboard presses no longer have any effect.
As suggested by #NTSCCobalt, adding a simple SetFocus(main window handler) in your WM_COMMAND cases will solve the problem, e.g.
case DEL__BUTTON:{
<Button specific code>
SetFocus(hwnd);
return 0;
}

OnLButtonDown() is not fired if I click an item in my dialog (ListBox, CheckBox etc) but it fires ok if I click background or Static Text

If I click anywhere on the dialog window, like in the "background", or on a Static Text, the function OnLButtonDown() is fired. But if I click a ListBox/EditBox/Combo/Calendar/Checkbox etc is not fired.
I thought that because these have control variables atached to it, and the Static Text don't. But adding a new Listbox to my Dialog and testing, I see that it doesn't fire either, so now I am confused...
I added OnLButtonDown() with the Class Wizard, it appears in:
BEGIN_MESSAGE_MAP(CMFCTesting2Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
// other handlers, etc
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
My function:
void CMFCTesting2Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
AfxMessageBox(CString("BUTTON DOWN"));
CDialogEx::OnLButtonDown(nFlags, point);
}
I tried calling CDialogEx:: ... before AfxMessageBox... but same result.
The CListBox item, has the Notify option set to True, as I seen some advices in other posts.
I suspect that the WM notification message is captured somehow by the ListBox, and not sent "forward" to my CMFCTesting2Dlg, but I understood that this should happen with the Notify option set to True, on the ListBox, no? (well, obviously, not...)
Sorry, I am new to dealing with WM in MFC.
BTW, I use Visual Studio 2010 Ultimate, and this is a Visual C++ - MFC- MFC Application - Dialog Based project.
How can I capture this mouse down event if clicked on a listbox / combo / etc?
On the LONG STORY, I am actually trying to accomplish this issue:
I have two listboxes (lets say), and I want to scroll them synchronously, when user scrolls one of them, others must scroll the same (or update in the next moment). And I thought of using on mouse down to track the position of every Listbox (with the GetTopIndex), and on mouse up, to GetTopIndex again and compare with the previous ones. If a change was made, then a listbox was scrolled and then update all listboxes with SetTopIndex. The unfriendly solution for the user, but simpler for me, would be clicking a button that does this verification / update, but its not elegant at all, and it can only set them at the same level, but can't determine which one was scrolled last time. This automatically scrolling of the listboxes should be made just for displaying, it is not important the selections in the listboxes. I tried using the Message Type in the Add Event Handler for the Listbox, but none that are displayed work for my problem, KillFocus and SetFocus, are not fired if the scroll-bar is dragged, only if an item in the listbox is clicked... and I didn't succeed on the others message type either, from the Add Event Handler.
Once a window handles a message, it stops being sent to the other windows beneath it. A static window doesn't handle a mouse down, so it goes to the dialog. The other controls all handle it in some fashion (setting focus at least) so it never gets to the dialog.
You can override the OnLButtonDown handler in each of the controls to do something else once they've finished their default handling in the base class. You might also get to see the message in the PreTranslateMessage method of the dialog.
As far as getting the List Controls to sync scrolling goes, your best bet would be to intercept WM_VSCROLL by subclassing CListCtrl or perhaps by PreTranslateMessage, and then calling SetScrollInfo on the other list. If the number of items in the lists are the same, it should be fairly simple.

Making a groupbox button win32 C++

i have a button that is a rectangle how would i put words in it i want to make so ican click the word and it starts the progrma i know ShellExecute the style is BS_GROUPBOX
If you have more than one program you want to start, you need a button per program you want to start.
To start you external progrma, in the button parent window, you need to process the WM_COMMAND message with the BN_CLICKED notification.
To set the text of the button, you need to send WM_SETTEXT message to the button with the text you want shown.
Btw, BS_GROUPBOX is used for creating the rectangle around radio buttons. This style is not going to work for your scenario.
If you want an alternative to using multiple Button controls, you can use a Toolbar. In fact, it seems to me that a toolbar would be a better control for you. You can read more about creating a toolbar.