In .Net there is a feature called KeyPreview. How can I do this in WinApi. Maybe I don't necessarily need this but my hWnd has WM_KEYDOWN, but it does not receive it when my Text Box has focus. How can I achieve this?
Thanks
*Using pure Win32API...
is there an alternative, how could I handle the Text Box's WM_KEYDOWN?
You can try subclassing the edit control. Either "instance subclassing", to trap messages for only one window, or "global subclassing" to trap messages for all windows of that class (in your application, not system-wide).
The example here (http://msdn.microsoft.com/en-us/library/ms997565.aspx) shows how to subclass an edit control and trap the WM_GETDLGCODE message -it wouldn't be that difficult to change it to WM_KEYDOWN.
You may have problems previewing the keys used for dialog commands, e.g. TAB or RETURN, as they may be trapped higher up the food chain. You may need to look at changing WM_GETDLGCODE as well.
If you use MFC you can look at PreTranslateMessage (I am not sure regarding to PreTranslateMessage, but you can easily to verify whether to enough to override the function).
You can set keyboard hook.
There is no such a possibility in WinAPI to catch the messages belonging to controls in window procedure of parent window (although some exceptions exist).
What .NET basically does is that it routes all messages of all controls including their parent window to a single window procedure. Then it's easy to catch all the messages in one place.
This is your way to go - to set window procedures of all the controls into single procedure and there to catch all the messages
As window procedure also receives hwnd parameter, it's then also easy to determine the control to which the message belongs.
Related
The documentation for WM_NEXTDLGCTL states, that this message is to be used with dialogs:
Sent to a dialog box procedure to set the keyboard focus to a different control in the dialog box.
If this message cannot be used with non-dialog control parents, it would be very tedious to subclass controls in a generic way (as illustrated in this question), since the window procedure would have to call either SetFocus or send a WM_NEXTDLGCTL message, based on not quite trivial to determine context.
Since other dialog-specific APIs can be used with non-dialog windows (e.g. IsDialogMessage), it would feel natural to be able to use WM_NEXTDLGCTL in this setup as well.
Question: Can WM_NEXTDLGCTL be used with non-dialog control parents?
Can WM_NEXTDLGCTL be used with non-dialog control parents?
I dont think you can use it in non dialog parent windows (at least with no changes to parent window), the cause is that it is implemented inside DefDlgProc. So your other non-dialog windows would have to call it to make this message work.
This is the quote I have found in The Old New Thing: Practical Development Throughout the Evolution of Windows: What happens inside DefDlgProc?
As the remarks for the WM_NEXTDLGCTL message observe, the DefDlgProc function handles the WM_NEXTDLGCTL message by updating all the internal dialog manager bookkeeping, deciding which button should be the default, all that good stuff.
Another reason why it is dialog only message is the fact that it (quote from msdn for WM_NEXTDLGCTL):
sets the default control identifier
to do it it must send DM_SETDEFID, which is defined as:
#define DM_SETDEFID (WM_USER+1)
so it is WM_USER, and as such it might be used for some other purpose on non dialog window (this fact is also mentioned in Raymond Chens book). The interesting thing is that according to this book IsDialogMessage also sends DM_SETDEFID/DM_GETDEFID to your window. So if you want to use TAB like navigation inside you non dialog window (using dialog code), you must adhere to some rules, you can read on them inside: What happens inside IsDialogMessage? of above book. This means among others to use following message loop:
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsDialogMessage(hwnd, &msg)) {
/* Already handled by dialog manager */
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
so if you dont want to do major changes to your parent windows code, then I am afraid you are out of luck.
I have "n" dialogs which have the same base dialog. Each dialog has its own controls
edit boxes
combo boxes
list controls
etc.
In base dialog, how do I set focus messages of each control and,for example, give a Message box with
text("Hello I got focus, my ID is %d")?
The easiest way is using the classical subclassing method. The problem is that WM_SETFOCUS is not pumped through the message Loop, so PreTranslateMessage will not help.
Thee are some nice classes that help to do additional subclassing without disturbing the MFC stuff.
Paul Di Lascia wrote CSubclassWnd. PJ Naughter wrote CHookWnd. And with the ATL has CWindowsImpl.
All this classes allow easy additional subclassing even if a window is already subclassed by the MFC.
You can use "standard subclassing" GetWindowLong/SetWindowLong too.
According to this SO article, you can hook the WM_SETFOCUS message.
You can get the Control ID by using GetDlgCtrlID with the hwnd returned by the hook.
But beware of popping up a MessageBox, that will change the focus and trigger your hook proc, making it go into a loop!
As Jerry already said make a hook, get parent window handler via GetParent() and SendMessage(hParentWND, WM_MESSAGE, lParam, wParam).
Of course, you should handle WM_MESSAGE in your parent window.
Btw, framework calls OnSetFocus function when window gained focus.
I am working on a MFC C++ application. I was working on a dialog that has SystemMenu property set to FALSE, so it does not have the ability to maximize. I want to handle the double-click message on the title bar. How can I do that?
EDIT:
I hope this time it will be clear for everybody. I have a dialog that does not have system menu (and system buttons or icon). When the user double-clicks the titlebar of that dialog, I want the program to call function x();.
Technically, you would have to handle WM_NCLBUTTONDBLCLK and check if the double click occurred in the caption area of the window, possibly by sending it WM_NCHITTEST and testing that the return value is HTCAPTION.
(Update: As JohnCz rightfully points out, sending WM_NCHITTESTis not actually necessary, since WM_NCLBUTTONDBLCLK already carries its result in wParam.)
Then you would only have to send WM_SYSCOMMAND with SC_MAXIMIZE in wParam to the window to maximize it.
In practice, however, it will not achieve much if your dialog box is not ready to handle size changes and layout its controls accordingly. This feature did not come out of the box in MFC last time I checked.
I think there is some kind of confusion here:
Frédéric Hamidi
You are correct, handling WM_NCLBUTTONDBLCLK message is the right way to go, however it is no necessary to call HitTest, since WM_NCLBUTTONDBLCLK message delivers hit information that MFC framework translates in the WM_NCLBUTTONDBLCLK handler.
Victor,
What is exactly that you are trying to achieve by handling WM_NCLBUTTONDBLCLK message?
Maybe there is some other way to fulfill your requirement once you make it clear to us.
The fact that you do not have system menu, does not prevent your app from receiving non-client area messages.
I am writing a fairly simple wrapper around Win32 controls/dialogs/windows.
The issue I have is that ListBox's and ComboBox's seem to behave rather differently.
In the base Widget class that I am inheriting from, I override the existing WNDPROC for the control and then handle messages in the new WNDPROC, primarily promoting them to boost::signal events.
The issue is that, while ComboBox's WndProc receives the CBN_SELCHANGE - as expected - ListBox's WndProc does not receive the LBN_SELCHANGE command.
I realize that the dialog/window that owns the control will likely receive this, but I've kind of gone down this rabbit hole already and it feels like a pretty neat solution. Need I back out and have the owners of the controls handle the WM_COMMAND messages (and from there promote it to an event on the control itself).
This is a learning exercise, so please don't remind me about MFC or comment on the value of doing this.
Notification messages are typically sent to a control's parent. Presumably all the windows (i.e. both parent windows and controls) are using the same window procedure? In this case the usual solution is: in the notification handler in your window procedure check if the notification came from the current window. If it did, raise an event; if it didn't resend the message back to the control it came from (where it will be raised as an event).
I'm creating a plugin framework, where my application loads a series of plugin DLL's, then creates a new window and pass this new window's handle to the plugin. The plugin can, then, use this handle to create their own GUI.
Everything seems to be working very well. The only problem is that when I press TAB on a plugin widget (An editbox, for example), it doen't jump to another widget. I figured out that some Windows messages are passed, and some others aren't. The WM_KEYDOWN is passed for other keys, because I can type on the editbox, but this message doesn't handle TAB key.
Hope somebody has a hint.
I'm using Borland VCL with CBuilder, but I think I could use any framework under WIN32 to create these plugins, since they never know how their parent windows were created.
It's very complex matter indeed.
When you hit TAB focus jumps to another control only when these controls belong to a Modal Dialog Box. In fact there are some buttons like ESC, LEFT, RIGHT, DOWN, UP, TAB which modal dialog message function treats in a special way. If you want these keys to behave in similar way with modeless dialog box or any other window you should change you message processing function and use IsDialogMessage inside. You'll find more information about IsDialogMessage function in MSDN also to better understand this stuff you may check as well Dialog Boxes section.
And, as was mentioned before, you should set WS_TABSTOP and WS_GROUP styles when needed.
Good luck!
I believe you'll have to take the following steps:
Subclass your edit controls (and other controls as needed).
Capture the WM_KEYDOWN message in your edit control's WndProc.
Check to see if the shift key is currently held down (using GetKeyState or similar).
Call GetWindow, passing in a handle to your edit control and either GW_HWNDPREV or GW_HWNDNEXT depending on whether shift is held down. This will give you the handle to the window that should receive focus.
Call SetFocus and pass in the window handle you got in step 4.
Make sure you handle the case where your edit controls are multiline, as you might want to have a real tab character appear instead of moving to the next control.
Hope that helps!
I believe you suffer from having a different instance of the VCL in each of your dlls and exes. Classes from the dll are not the same as the ones from your exe, even if they are called the same. Also global variables (Application, Screen) are not shared between them. Neither is the memory since they both have their own memory manager.
The solution is to have the dlls and the exe share the VCL library and the memory manager. I am not a BCB developer, but a Delphi developer. In Delphi we would just use the rtl and the vcl as runtime packages. Maybe you could do the BCB equivalent.
A DLL has its own TApplication object.
to provide uniform key handling. when the DLL Loads.
assign the DLL::TApplication to the EXE::TApplication
Be sure to do the reverse on exit.
--
Michael