C++ winapi pass mouse clicks on child windows to parent window - c++

I want to handle the clicks on child windows the same as clicks on parent window - how can I do that in winapi?
Currently, I can move the parent window by pressing anywhere on it but not on the child windows, because then it won't move. How can I change that?

The answer that works:
case WM_NCHITTEST:
if (hWnd==parent)
return HTCAPTION;
else return HTTRANSPARENT;

Capture the mouse click on the desired child controls(s), and then send a WM_SYSCOMMAND message with SC_DRAGMOVE (0xF012, aka SC_MOVE OR'ed with 2) as the wParam parameter to the parent window. That will invoke a drag operation on the parent window.
This is a widely known trick, and well documented online (just not by Microsoft) if you do a search for SC_DRAGMOVE.

Related

How to find out which window triggered WM_PARENTNOTIFY?

When I set the parent of a button (A) to another button (B), I found that it won't trigger the WM_COMMAND message of button A, and that there will be a WM_PARENTNOTIFY message received by the window (parent of button A). But after looking up the reference, I found no way to get the identity of button B, like HMENU or HWND. Could someone help me?
Yes, it's sure that it seems strange that somebody put a button into another button, or say set the parent of a button to another button, but it do has some realistic meaning when the parent button has a style of BS_GROUPBOX, just as the Frame in Visual Basic.
img_button_in_button
My solution to this problem is calling SetWindowSubClass after created a new control and so that the new callback function set in calling this API can receive the real hWnd of the control triggering this event.
Something to remark:
Use return DefSubclassProc(hWnd, uMsg, wParam, lParam); if that event is not to be handled by the control.
Remove WS_CHILD style for those controls calling SetWindowSubClass, or those controls can not be correctly displayed and the only thing displayed would be just an empty window.
Thanks for all who helped me in this question!

focus lost after double click in tree view

We use in several place a CTreeCtrl (TreeView) and accept a double click to open dialogs related to the double clicked node.
The opened dialog looses the focus after being opened, since the tree view seems to force to be focussed at the end of the double click handling.
Our scenario:
the user double clicks onto a node
the tree view gets focused and selects an item in its tree
the tree view containing window receives the NM_DBLCLK notification for the tree view and reacts on the double click by opening a dialog or a MDI child window in our MDI environment
the opened dialog/MDI child window gets focused after being opened
the tree view gets focused again
Even if we use in (3) (the notification handler) the result field returning a non zero value to prevent the rest of the default handling, (5) happens and the tree view gets focused again, the item selected again.
I'd really appreciate any hint about a way to resolve this issue, since it is really annoying, that a just opened dialog or window looses its focus right after opening.
Thanks in advance!
This behavior won't occur if you create a modal dialog box, because parent window is immediately disabled and dialog gains focus. But with mode-less dialog, flicker may occur, and dialog loses focus.
For mode-less dialog, use PostMessage or SetTimer so that the mode-less dialog is opened after TreeView message is processed. Example:
#define WM_USER_MSG1 WM_USER + 1
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_MESSAGE(WM_USER_MSG1, create_dialog)
...
END_MESSAGE_MAP()
void CMyWnd::OnDblClick(NMHDR*, LRESULT* pResult)
{
PostMessage(WM_USER_MSG1, 0, 0);
*pResult = 0;
}
LRESULT CMyWnd::create_dialog(WPARAM, LPARAM)
{
if(!m_dlg.GetSafeHwnd())
m_dlg.Create(IDD_DIALOG_X, this);
m_dlg.ShowWindow(SW_SHOW);
return 0;
}

How to kill focus of "edit" control on "Enter" key press

I have a main window created in main function. In procedure for the main window on WM_CREATE message I create a edit control which as a child of parent window using system "edit" window class. I want the focus to be transferred to main window when enter key is pressed in edit control. Since I used system class I don't have access to its procedure.
I am using C++ for this in Visual Studio 10
Since I'm new to win32 apps I want a simple solution no matter how long the code is
If your window has only one focusable control (such as an edit control), then that control will always have the focus. You cannot have a window with no focused controls, and the parent window itself is not focusable (i.e. cannot have the focus).
So you will first need to add another focusable control to your window, if you don't have one already (I couldn't tell from the question). For example, you might add an "OK" or "Cancel" button. That way, whenever you unfocus the edit control, the button can receive the focus.
Then, you will need to subclass the edit control so that you can process its key press events (e.g. WM_KEYDOWN and WM_KEYUP). To subclass a single window, call the SetWindowLongPtr function and pass the window handle along with the GWLP_WNDPROC flag and a pointer to your custom window procedure. This effectively replaces the default window procedure for that class of control with your custom window procedure. For example:
// Stores the old original window procedure for the edit control.
WNDPROC wpOldEditProc;
// The new custom window procedure for the edit control.
LRESULT CALLBACK CustomEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
{
if (wParam == VK_RETURN)
{
// The user pressed Enter, so set the focus to the other control
// on the window (where 'hwndOther' is a handle to that window).
SetFocus(hwndOther);
// Indicate that we processed the message.
return 0;
}
}
}
// Pass the messages we don't process here on to the
// original window procedure for default handling.
CallWindowProc(wpOldEditProc, hWnd, msg, wParam, lParam);
}
// ----- Add to the parent window's WM_CREATE: -----
// Create the edit control
HWND hwndEdit = CreateWindowEx(...);
// Subclass it.
wpOldEditProc = (WNDPROC)SetWindowLongPtr(hwndEdit,
GWLP_WNDPROC,
(LONG_PTR)CustomEditProc);
// Show it.
ShowWindow(hwndEdit, SW_SHOW);
// ... your other code (e.g. creating and showing the other control)
// ----- Add to the parent window's WM_DESTROY: -----
// Unsubclass the edit control.
SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)wpOldEditProc);
// ... your other code (e.g. calling PostQuitMessage(...) to close your app)
Further reading about subclassing windows is here on MSDN. The sample code there (and lots of other places on the web) assumes that you're subclassing an edit control in a dialog window. Because dialogs are special types of parent windows that handle a lot of keyboard processing automatically, you need to take extra steps to overcome this default processing done by the dialog. If you're using a regular window created with CreateWindowEx, that is not necessary.
If you want multiple edit controls that all behave the same way in response to certain key presses, it is much cleaner and better design to register a custom window subclass. Whereas the above code subclassed only a single edit control object, this approach would create a new type of custom edit control class. You could create as many instances of this new type of edit control as you wanted, and they would all behave the same way.
But I won't go into how to do that here. You can find the code online if you're interested, and your particular use case makes it a bit more complicated. In order to change the focus, the control has to know which other control it should set the focus to. This is difficult to handle globally. Using a dialog window as the parent might be advisable. It manages the Z order and setting the focus for you automatically.

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;
}

C++/Win32 API - SetFocus to button does not work

HWND button = CreateWindowEx(0, "BUTTON", ...);
SetFocus(button); // Button no get focus! :(
Also, I have other controls on my form that I am able to SetFocus() to.
Thanks, Martin
It has been FOREVER since I've had to do this, but...
Were this a dialog, I would tell you to send a WM_NEXTDLGCTL via PostMessage(). The default dialog item message handler would take care of the rest for you setting keyboard focus and selection activation. However, this is a different case if I read this correctly. You're creating both parent and child windows raw on the fly. If this is the case, SetFocus() to the parent window, and handle WM_SETFOCUS on the parent window by bringing it to top, then setting focus on the child window. WM_SETFOCUS, and WM_KILLFOCUS were designed to allow you to switch the 'activated' state of your controls, and most handle it for you (unless your window is an owner draw control or some such). But in a raw window, when your base parent window is sent the focus, you need to appropriately ensure the proper child has it if you're hosting any (think of it as managing your own 'dialog'). Again, normally this is done by the default dialog procedure for you if this were a dialog, but being raw windows you're kind of stuck managing it all yourself.
Though I can't imagine how, I hope that helped somewhat.
SetFocus is a function, not a procedure. Call it as a function and check its returned value. Either the retuned value is null because you made an error in the CreateWindowEx() call and "button" isn't a valid handle or it's a window not associated with your thread's message queue, or the return value is not null (it's now the prior focused window's handle) and you do have the focus (but are somehow failing to detect it).
Try setting the WS_TABSTOP style on the button.
If you create that button in respond of the WM_INITDIALOG message you should return FALSE to prevent dialog box procedure to change the focus.