How does Windows changes keyboard layout? - windows

The hotkeys for doing so are:
Alt+Shift - Windows 7 and Win button + Space in Win 8 and 10.
Programmatically I can do that using WM_INPUTLANGCHANGEREQUEST, but it is not the way Windows does that. I am trying to figure out how Windows changes the layout. Using spy++ I figured out that Windows sends WM_INPUTLANGCHANGE message which is changing layout, so I tried it myself:
SendMessage(myHWND, WM_INPUTLANGCHANGE, 0xCC, 0x4190419);
I have keyboard hook bind, when press f1 do the sendmessage to currently active window's active control.
but it didn't work, though the messages in spy++ are thes same:
first one using "Windows hotkey"/"Taskbar" to change layout, it works. Second my message, it did not work. Am I missing something, why message works for "Windows" but not for me.
The WM_INPUTLANGCHANGEREQUEST works, but it freezes some certain apps, and I would like to figure out the way Windows does the layout changing to avoid that.
-- update.
In DxO Photolab 3 it freezes when using WM_INPUTLANGCHANGE in "Export to Disk" Dialog:
When you change layout using "Windows" Method(Keyboard Hotkey/Taskbar):
Works normally, no freezing.
Posting the WM_INPUTLANGCHANGE:
Received the WM_INPUTLANGCHANGEREQUEST and froze:
Also similar freezing I've seen in Skype, MS Office, Adobe After Effects.

From WM_INPUTLANGCHANGEREQUEST,
When the DefWindowProc function receives the
WM_INPUTLANGCHANGEREQUEST message, it activates the new input locale
and notifies the application of the change by sending the
WM_INPUTLANGCHANGE message.
We can view the details through spy++.
Only after the application receives the WM_INPUTLANGCHANGEREQUEST message, it will activate the new input locale, and notifies the application of the change by sending the WM_INPUTLANGCHANGE message.
A simple test:
According to my understanding, what actually works is the WM_INPUTLANGCHANGEREQUEST message, but I have not found an alternative API to complete its work.
For the freezing problem of some certain apps you encountered, I found some similar cases.
Refer #Barmak Shemirani's answer,
Apparently WM_INPUTLANGCHANGEREQUEST fails if the target itself is a
dialog based application (I don't know why!) To solve the problem you
can post WM_INPUTLANGCHANGEREQUEST message to dialog's descendants (in
addition to WM_INPUTLANGCHANGEREQUEST message to the dialog itself)
Updated:
My test code:
#include <Windows.h>
int main()
{
HWND hwnd = (HWND)0x00070EBA; // hwnd of skype
while (1)
{
Sleep(1000);
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, 0);
}
return 0;
}
Result:

Related

SetWindowsHookEx(WH_SHELL, ...): What is the meaning of event HSHELL_WINDOWREPLACED?

If I register a hook via SetWindowsHookEx(WH_SHELL, ShellProc, ...), what is the meaning of event HSHELL_WINDOWREPLACED? (My Google-fu fails me. I have searched high and low!)
Win32 Docs:
SetWindowsHookEx(): https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw
ShellProc (callback): https://learn.microsoft.com/en-us/windows/win32/winmsg/shellproc
The offical docs read: A top-level window is being replaced. Weirdly, they also say: Windows 2000: Not supported. Does that mean only supported before or after Win2K?
I created a test driver to watch a Microsoft Windows session, but I was never able to trigger this mysterious event.
I also found a similar event here:
RegisterShellHookWindow: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registershellhookwindow
... that says:
HSHELL_WINDOWREPLACING: A handle to the window replacing the top-level window.
HSHELL_WINDOWREPLACED: A handle to the window being replaced.
Related:
How can I be notified when a new window is created on Win32?
Why HSHELL_WINDOWDESTROYED, HSHELL_WINDOWCREATED?
In this instance, the term "replace" refers to the occasions when a window stops responding to messages ("hangs") and, after a certain period, Windows hides it and replaces it on-screen with a faded-out copy (called a "ghost window").
Windows does this so that, even when the app is not processing messages, the user can interact with the ghost window to move it around and try to close it.
The wParam value is the handle of the hung window (the one being replaced) and the lParam value is the handle of the ghost window (its replacement).
If the window starts responding again, the notification is sent again, with the window handles swapped around.

in Delphi application.OnMessage does not receive WM_INPUTLANGCHANGEREQUEST in windows 10

I am using application.OnMessage to prevent keyboard layout change (writing text other than English) in some controls. But on Win7/Win10 message WM_INPUTLANGCHANGEREQUEST is never received. On windows XP it works fine.
Is there another way to catch and prevent user from switching the input language?

Modal dialogs opened by a fullscreen OpenGL window on Windows 7 are not showing

It seems that my problem may be the same as an unanswered related question (OpenGL with GLUT on windows 7, fullscreen mode not showing the message box).
Since I switched to Win7 as a development environment, and a possible target platform for my applications, I noticed a regression in their behaviour.
Whenever I have a fullscreen window containing a fullscreen OpenGL context, the applications have problems displaying modal dialog boxes (such as message boxes, file open dialog, etc.)
The window is just created with WS_POPUP style. The GL context is nothing fancy. And everything is fine with Windows XP.
The problem under Windows 7 is that the modal dialog boxes are invisible at their opening (maybe their appear behind the full screen window). You have to Alt-Tab the application to have the dialogs appear.
This is a major problem as the application appears to be frozen, while it in fact waits for user input.
Did anyone encounter this behaviour ? Does anyone know a workaround ?
I've quickly made up a sample test application ; its source code can be found at http://pastebin.com/K4v2NNDs. A simple MSVC8 project can be found here.
PS. I've also posted on opengl.org forums, sorry for those of you that follow both.
EDIT
Thanks to Chris comment, I've tested the modal dialog on various events, such as WM_TIMER or WM_RBUTTONUP, but the problem is still there.
I've also called 'DwmEnableComposition' with 'DWM_EC_DISABLECOMPOSITION' just to check : problem still there.
I've also tested the application by replacing the OpenGL bits by DirectX, and this way everything works as expected... It's really OpenGL causing the problem.
(updated pastebin http://pastebin.com/Rq1Ehm3w and my scratchpad)
EDIT
The problem also exists on Windows 8.
A workaround has been posted on opengl.org by Joseph Steel, so, for reference I put it here as well :
The solution I found for this problem was to ensure that the pixel format for the window uses the WGL_SWAP_COPY_ARB swap method rather than the WGL_SWAP_EXCHANGE_ARB.
I've noted that one must use 'wglChoosePixelFormatARB' to obtain the pixel format.
I tried with the classic 'ChoosePixelFormat' with the 'PFD_SWAP_COPY' flag, but it does not work on my system (Win7 x64 + NVidia GeFo 9600GT v196.21) as it always returns me a pixel format with 'PFD_SWAP_EXCHANGE' instead.
I'm only half-happy with the results, as it introduces some tearing in my display, but as least it works !
For reference, I've updated my test source code.
EDIT, dec.2013
This workaround does not work anymore, at least on my system (laptop, Optimus GeForce 650M). The WGL_SWAP_COPY_ARB is setup but the modal dialog does not show. So far, it seems that creating the window with a 1 pixel border (adding WS_BORDER to WS_POPUP style) does the trick, and prevents entering 'fullscreen' mode.
Solution on my system was pretty simple:
- DO NOT specify WS_POPUP style at the window creation time.
- Just after you obtain hwnd, re-set your windows styles to what you want (but no WS_POPUP again) using SetWindowLong(hwnd,GWL_STYLE, yr_styles);
I had the same problem with OpenGL under Win7 64 bit.
Modal dialog boxes and modal windows are not shown, also they are active in the background.
My project used stereo display (quad buffers).
In my case, the problem was due to an incorrect setting in the control panel of the display adapter (Nvidia Quadro FX3800).
The setting was "Stereo Enabled", which was incorrectly on "off".
Switching it on solved the problem.
when i want, for example, open a filedialog in OpenGL fullscreen (Windows10
or every Windows before), i call
RedrawWindow(hwnd, 0, 0, RDW_INTERNALPAINT);
( this causes a WM_PAINT message to be posted to the window regardless of whether any portion of the window is invalid )
and just after this i call the filedialog.
The filedialog will be shown now in OpenGL fullscreen.
In WndProc inside the case WM_PAINT: i do a SwapBuffers(hdc)
RedrawWindow(hwnd, 0, 0, RDW_INTERNALPAINT);
// important when fullscreen; forces a WM_PAINT message,
GLwin->Fileselect(s_fname); // or whatever dialog
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lparam)
{
switch(message)
{
case WM_PAINT:
SwapBuffers(hdc); // (same as in the render-loop)
break;

WM_POWERBROADCAST handler for CMainDlg in ATL app not invoked

I have an ATL app where I want to handle WM_POWERBROADCAST. I have a CMainDlg (CAxDialogImpl) in whose MSG_MAP I defined the handler.
BEGIN_MSG_MAP(CMainDlg)
...
MESSAGE_HANDLER(WM_POWERBROADCAST, OnPowerChange)
...
END_MSG_MAP()
However, the handler isn't invoked when I do things that should invoke it, for instance change power settings or put the machine to sleep.
Any ideas about what might be going on, and how to fix this? Does CMainDlg not get notified of power events, for some reason?
I suspect your dialog not being a top level window (WS_POPUP styled).
Just tested with a WTL AppWizard non modal dialog app that WM_POWERBROADCAST is received (without any registration) on AC plugged/unplugged.
Did you register to receive the power events?
To add to answers above, you might want to use Spy++ tool to make sure the messages of interest are posted to your application in first place. You will also see which windows they are posted to, and if it is your window where you are waiting for this message.

How do I send key strokes to a window without having to activate it using Windows API?

I have made an application already that sends commands to an activated window. I want to be able to use the computer while my process is running because as soon as I switch focus to another window the key strokes being sent via send keys will go to the window I just switched to.
Currently I use FindWindow, IsIconic, and ShowWindow from the Windows API. I have to check to see if the window is there with FindWindow and set my object to the specific window that is returned with that call, I then check if it's minimized with IsIconic and call ShowWindow if it is, and then finally I have to call Interaction.AppActivate to set focus to that window. All of this is done before I even send key strokes. Seems like there should be a way to just send key strokes without having to show the window and activate it. The big thing is while my application is running the key strokes I can't do anything on my computer.
Alright, this is kind of disappointing I'm sure, but you fundamentally cannot do this with 100% reliability.
Windows assumes that the active window is the one getting keyboard input. The proper way to fake keyboard input is with SendInput, and you'll notice that it sends messages to the active window only.
That being said, you can SendMessage WM_KEYUP, WM_CHAR, and WM_KEYDOWN messages and (depending on the WndProc receiving them) maybe get away with it. But remember, its going to break under some circumstances, period.
Sounds like you are using keybd_event() or SendInput(), which both send keystrokes to the currently active window. To direct keystrokes to a specific window, regardless of whether that widnow is focused or not, you need to find its HWND handle first, and then post appropriately-formatted WM_KEYUP/DOWN and WM_CHAR messages directly to it.
once you have the windows HWND, you can directly SendMessage() the WM_KEYDOWN and WM_KEYUP messages to its message queue. The window does not have to be active.
However, understand that this depends on how the target application processes keyboard input. There are several different ways to handle it.
WM_KEYUP/WM_KEYDOWN is most common and some applications only process one or the other (usually WM_KEYDOWN).
WM_CHAR is also fairly common
Some programs use GetAsyncKeyState, GetKeyState, or GetKeyboardState. This is extremely unusual, but effectively prevents keypress injection with SendMessage(). If this is the case fall back to keybd_event() which is directly handled by the keyboard driver. Of course the window will have to be active

Resources