I have an ATL control that I want to be Unicode-aware. I added a message handler for WM_UNICHAR:
MESSAGE_HANDLER( WM_UNICHAR, OnUniChar )
But, for some reason, the OnUniChar handler is never called.
According to the documentation, the handler should first be called with "UNICODE_NOCHAR", on which the handler should return TRUE if you want to receive UTF-32 characters. But, as I said, the handler is never called.
Is there anything special that needs to be done to activate this?
What are you doing that you think should generate a WM_UNICHAR message?
If your code (or the ATL code) ultimately calls CreateWindowW, then your window is already Unicode aware, and WM_CHAR messages will be UTF-16 format.
The documentation is far from clear on when, exactly, a WM_UNICHAR message gets generated, but from what I can gather in very limited poking around on Google Groups and on the Internet it looks like it gets sent by 3rd party apps and not by Windows itself, unless the Window is an ANSI window (CreateWindowA and all that). Have you tried manually sending a WM_UNICHAR message to your window to see what happens? If you get the message then there's nothing wrong with your message dispatch code and there's just nothing happening that would cause WM_UNICHAR. You can also check with Spy++ and see whether you're getting that message, though I suspect it's just not being sent.
My experience today is that Spy++ does not give correct results for WM_CHAR in a Unicode proc. I am getting ASCII translations or '?' showing in the Messages list, even if I view Raw (not Decoded) arguments. The debugger shows wParam to be the Unicode code point though.
void CMFCProView::OnUniChar (UINT xChar, UINT nRepCnt, UINT nFlags)
void CMFCProView::OnChar (UINT xChar, UINT nRepCnt, UINT nFlags)
The range of UINT (unsigned int) is 0 to 4294967295 decimal (16-bit).
OnChar can do whatever you want OnUniChar to do. Click an English
character A on the softkeyboard, then OnChar will receive 0x0041.
Click a CJKV δΈ€ (one), then OnChar will receive 0x4E00. So we don't
need OnUniChar in App.
Related
I have a legacy MFC application originally written in Visual C++ 6. I need to do some minor changes to it but MFC is a black box to me.
There is this apparently wizard-generated function that processes messages
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch (message)
{
case WM_CLOSE:
...;
...
etc.
}
For some messages I need to get the sender window handle (which is from a different process). In Windows API a standard WindowProc has this handle as the first argument, but where is it in MFC?
Edit: Thank you Raymond and Mark. I see that I misunderstood how it works.
This information isn't available. The first parameter in a standard window procedure is the receiver, not the sender. This makes sense, too, since SendMessage and PostMessage identify the receiver by window handle. The sender, on the other hand, can be any thread, including a thread that doesn't own any windows.
If you need to identify the sender of a message in the code receiving a message you will have to explicitly pass an ID along. When crossing process boundaries you're going to have to marshal any referenced memory. The system won't do that for custom messages.
EDIT:
Question is reduced and optimized in response to community's comments. The deleted part of the question will be posted as separate question.
QUESTION:
Is there any WM_SOMETHING or NM_SOMETHING message in Win32 API that can inform me about user changing the locale?
You see, I could use that message/notification to change my program's locale to the current locale.
Something like this pseudo-code:
case WM_SOMETHING: // in my main window procedure
_wsetlocale( LC_ALL, L"" );
Also, if there is such message, and I process it as in the pseudo-code above, will it adjust only main window's locale or will it also set locale for child dialog boxes and controls?.
MY EFFORTS TO SOLVE THIS:
After browsing through Internet, the only thing I found was WM_INPUTLANGCHANGE, WM_SETTINGCHANGE and WM_INPUTLANGCHANGEREQUEST messages, but I have never used them and do not know if they can solve my problem.
Thank you.
Best regards.
Windows sends a WM_SETTINGCHANGE message, with the wParam set to 0, and the lParam set to a character string containing the value intl. This is described in the documentation for WM_SETTINGCHANGE under the Parameters section:
wParam
...
When the system sends this message as a result of a change in locale settings, this parameter is zero.
lParam
...
When the system sends this message as a result of a change in locale settings, this parameter points to the string "intl".
Your application will need to respond to the message and make any necessary changes yourself in child dialogs and controls.
I have a program with an option to enable minimizing to the taskbar's notification area. In order for this to work, I need a reliable way of detecting when the user has minimized the application.
How can I do that using the Windows API in a C++ application?
When the user minimizes the window (either using the box on the title bar, or by selecting the "Minimize" option from the system menu), your application will receive a WM_SYSCOMMAND message. The wParam parameter of that message will contain the value SC_MINIMIZE, which indicates the particular type of system command that is being requested. In this case, you don't care about the lParam.
So you need to set up a message map that listens for a WM_SYSCOMMAND message with the wParam set to SC_MINIMIZE. Upon receipt of such a message, you should execute your code to minimize your application to the taskbar notification area, and return 0 (indicating that you've processed the message).
I'm not sure what GUI framework you're using. The sample code could potentially look very different for different toolkits. Here's what you might use in a straight Win32 C application:
switch (message)
{
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_MINIMIZE)
{
// shrink the application to the notification area
// ...
return 0;
}
break;
}
I think you are looking for WM_SIZE. When you get this, check the wParam to get the specifics. Here is the MSDN page.
WM_SIZE
You can check the area size returned from GetClientRect - if zero it's minimised, works for me but may not work in all cases.
That's what IsIconic is supposed to determine, but it doesn't work consistently for me. (Oh, for a consistent way to determine this...)
For completeness, there's also GetWindowPlacement. The window state is revealed in the showCmd member of the WINDOWPLACEMENT structure, and if the window is minimized it has a value of 2, or SW_SHOWMINIMIZED.
I was wondering if there is a way to intercept and modify mouse input before it gets to windows?
What I'm wanting to do is intercept mouse motion events, apply some custom scaling and acceleration to the values, and then continue passing them along. I'd need something that can do this before the inputs get to the raw input API or DirectInput.
In order to affect all mouse input, including DirectInput, during logon and the SAS screen, etc., you'll need to load a filter driver into the mouse driver stack.
Other people have done it, for example http://www.maf-soft.de/mafmouse/
There should be a moufiltr sample in the Windows DDK which you can use as a starting point. You will most likely want to use a virtual machine for development since errors in a driver on your development machine could be difficult to recover from.
Have you seen this method of intercepting mouse and keyboard input without having to make a filter driver or hook?
http://oblita.com/Interception.html
There is a LowLevelMouseProc hook procedure that you can use to get information on any mouse input entering the system, although I doubt if you can actually change this information (and the docs are silent on this).
If this fails, GetMsgProc is an alternative that lets you intercept all messages posted to any window. Though this hook does let you modify the message, it's probably too late to have any effect on APIs such as DirectInput.
You could try a windows hook - which are functions you set to receive windows messages before they get passed through to the rest of the system - a CBT hook (for computer based training) is what might get you best results.
I don't know Whether this will work with DirectInput or the other new stuff MS has added to break all the old internal consistency. Its easy to set up though, so try it and see.
As far as I know the best way is to hook to windows message loop, In your case you should pass HWND 0 (If I remember correctly this the HWND of the desktop) so all the messages will pass though your function first.
http://msdn.microsoft.com/en-us/library/ms633591%28VS.85%29.aspx
More on hooks : http://msdn.microsoft.com/en-us/library/ms644959%28VS.85%29.aspx
Use it as follows:
m_nOldWindowProc = ::SetWindowLong(0 /I think.../, GWL_WNDPROC, (LPARAM)(WNDPROC)WindowProcCallback);
and the callback:
LRESULT CALLBACK CStubWindow::WindowProcCallback(HWND hwnd,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_WINDOWPOSCHANGING:
((WINDOWPOS*)lParam)->cx = STATUS_BAR_WIDTH;
((WINDOWPOS*)lParam)->flags = SWP_NOOWNERZORDER | SWP_NOMOVE;
break;
default:
break;
}
return ::CallWindowProc(m_nOldWindowProc, hwnd, message, wParam, lParam);
}
When typing into a CRichEditCtrl, EN_CHANGE messages are generated. However MSDN says:
Rich Edit: Supported in Microsoft Rich
Edit 1.0 and later. To receive
EN_CHANGE notifications, specify
ENM_CHANGE in the mask sent with the
EM_SETEVENTMASK message. For
information about the compatibility of
rich edit versions with the various
system versions, see About Rich Edit
Controls.
The EN_CHANGE notification is not sent
when the ES_MULTILINE style is used
and the text is sent through
WM_SETTEXT.
I have several dialogs using a multi-line rich edit control, actually my custom CMyRichEdit class. That class automatically performs analysis when the text changes, but in the important case where the dialog is initially populated, no notification is seen.
The point is to avoid having to change our code-base more than absolutely necessary - the new control is being dropped in to replace existing ones. Chasing down every instance where getDlgItem(IDC_EDIT)->SetWindowText is used, or where DDX_Text(pDX, IDC_EDIT, m_strEdit) automatically links a string contents with the control, would mean a lot of trawling through code and re-testing everything altered.
Is there an easy way? Can MyRichEdit catch its own WM_SETTEXT messages?
ON_MESSAGE(WM_SETTEXT, OnSetText)
// fires every time someone calls SetWindowText
LRESULT MyRichEditCtrl::OnSetText(WPARAM wParam, LPARAM lParam)
{
return CWnd::Default();
}