I have created a small program which launches itself in a new desktop.
HDESK hDesktop = ::CreateDesktop(strDesktopName.c_str(),
NULL, // Reserved
NULL, // Reserved
0, // DF_ALLOWOTHERACCOUNTHOOK
GENERIC_ALL,
NULL); // lpSecurity
::SetThreadDesktop(hDesktop);
Later on, started another application on that desktop using the following lines:
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
si.lpDesktop = &strDesktop[0];
if (FALSE == ::CreateProcess(pathModuleName.file_string().c_str(), L"abc def", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
return false;
DWORD dwWaitRes = ::WaitForSingleObject(pi.hProcess, INFINITE);
pathModuleName is a self location obtained by GetModuleFileName(NULL).
The newly created application obtains a HWND to another window and sends window messages using the following commands:
// bring window to front
::SetForegroundWindow(hwnd);
// set focus so keyboard inputs will be caught
::SetFocus(hwnd);
::keybd_event(VK_MENU, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
...
So basically application A on desktop DEFAULT is starting application B on desktop X, which obtains an HWND to another application C started on the same desktop X.
My problem is that keyboard events coming from application B on desktop X are not being triggered in application C. Only if I use SwitchDesktop(B), then events are triggered and code is executed properly.
What am I missing?
You are trying to simulate user input on a desktop that is not active on the physical console (screen, mouse, keyboard), which is not likely to work, and why SwitchDesktop() makes it work. According to the documentation:
SwitchDesktop function
Makes the specified desktop visible and activates it. This enables the desktop to receive input from the user.
keybd_event(), mouse_event(), SendInput(), they all simply generate and store input messages into the same input queue that the physical mouse/keyboard post their messages to. The input system does not know the difference between user input and synthesized input when dispatching the input messages to applications.
Raymond Chen touched on that in his blog:
How do I simulate input without SendInput?
SendInput operates at the bottom level of the input stack. It is just a backdoor into the same input mechanism that the keyboard and mouse drivers use to tell the window manager that the user has generated input. The SendInput function doesn't know what will happen to the input. That is handled by much higher levels of the window manager, like the components which hit-test mouse input to see which window the message should initially be delivered to.
He also posted a nice little diagram in another blog article showing where SendInput() sits in relation to the input queue:
When something gets added to a queue, it takes time for it to come out the front of the queue
Related
I want to send the mouse and keyboard input, which is recieved from android client, to games running on windows.
SendInput works for almost all games I have worked so far. But for SendInput to work the game must be a foreground window.
To solve that I used PostMessage(hwnd,...) with hwnd being handle to the game window. But this does not work if game is using DirectInput. That was solved by hooking GetDeviceState. Now another game I started working on is using WM_INPUT or raw input and I have to create raw input to make it work.
According to this MSDN Article
DirectInput is a set of API calls that abstracts input devices on the
system. Internally, DirectInput creates a second thread to read
WM_INPUT data, and using the DirectInput APIs will add more overhead
than simply reading WM_INPUT directly.
directInput works using WM_INPUT.
The SendInput function inserts the events in the INPUT structures
serially into the keyboard or mouse input stream. These events are not
interspersed with other keyboard or mouse input events inserted either
by the user (with the keyboard or mouse) or by calls to keybd_event,
mouse_event, or other calls to SendInput.
So SendInput is also providing abstraction.
All I want is to send the input to application independently even when its window is not in focus. That way I will be able to send input to multiple games at once. Is there any way to achieve this using one higher level API call like SendInput? Can this be done with SendInput? Is there any C/C++ library for that?
When registering your input device using the RAWINPUTDEVICE structure,
set dwFlags = RIDEV_EXINPUTSINK to receive input when the process is in the background.
Example:
RAWINPUTDEVICE rid;
rid.usUsagePage = 1;
rid.usUsage = 4; // Joystick
rid.dwFlags = RIDEV_EXINPUTSINK;
rid.hwndTarget = window;
if (!RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)))
return -1;
I am developing an app where I am launching an Java application from within my MFC application. I want to display the wait cursor from the time process is carried out by the java application until it ends.
Here's the code I have Implemented.
void CDropboxSync::OnBnClickedDbxPcToCloud()
{
STARTUPINFOW siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
SetCursor(LoadCursor(NULL, IDC_WAIT));
if (CreateProcess(TEXT("C:\\Program Files\\Java\\jre7\\bin\\java.exe"), TEXT(" -jar DbxUpldDwnld.jar u"), NULL, NULL, false, CREATE_NO_WINDOW, NULL, NULL, (LPSTARTUPINFOA)&siStartupInfo, &piProcessInfo) == false) {
AfxMessageBox(_T("Please install Java Runtime Environment(JRE) on your PC\n Link: http://www.oracle.com/technetwork/java/javase/downloads/index.html"), MB_ICONERROR);
}
CloseHandle(piProcessInfo.hProcess);
CloseHandle(piProcessInfo.hThread);
// TODO: Add your control notification handler code here
}
I want to start the wait cursor as soon as the processing of java application starts and want to end the Wait cursor when the application process is done. How can this be done. I have tried to implement BeginWaitCursor and EndWaitCursor. But could get the desired output.Please point me to rite direction. Thanks in advance.
From the above code it seems your code does the following,
Set WAIT Cursor
Create the java process
Then closes process and thread handles
It is never setting normal cursor back. So your application would be displaying Hour glass even after finishing the java process.
This is what I have got in my mind,
Set Wait Cursor in OnBnClickedDbxPcToCloud()
Start a new thread which does the following
2.1) Create the java process
2.2) Wait for the java process to finish by calling WaitForSingleObject(piProcessInfo.hProcess)
2.3) Then notify UI thread by sending a custom message to the Window.
In the custom window message handler you set back the normal
(arrow) cursor.
I'm working on a messenging tool. The messaging window is part of a whole application. I need the window to go to the front when there are some messages coming. I'am using this code :
if( m_hwnd == NULL || !::IsWindow(m_hwnd) )
return E_UNEXPECTED;
if(::IsIconic(m_hwnd))
{
::ShowWindowAsync( m_hwnd, SW_RESTORE );
}
::SetWindowPos(m_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
::SetForegroundWindow(m_hwnd);
if( pvbProcessed != NULL )
*pvbProcessed = VARIANT_TRUE;
return S_OK;
I even tried to do a TOPMOST but still in some cases it does not work.
I also Tried a ::BringToFront().
Anyone can help or give an explanation on why it doen not work ? Is it a known microsoft limitation.
The system restricts which processes can set the foreground window. A
process can set the foreground window only if one of the following
conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.
See the SetForegroundWindow() docs for more details.
In the official document of Win32 API, there are remarks:
Remarks The system restricts which processes can set the foreground
window. A process can set the foreground window only if one of the
following conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The process is being debugged.
The foreground process is not a Modern Application or the Start Screen.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.
But there is a trick to force a window to foreground:
The trick is to make windows ‘think’ that our process and the target window (hwnd) are related by attaching the threads (using AttachThreadInput API) and using an alternative API: BringWindowToTop.
void CommonHelpers::forceForegroundWindow(HWND hwnd) {
DWORD windowThreadProcessId = GetWindowThreadProcessId(GetForegroundWindow(),LPDWORD(0));
DWORD currentThreadId = GetCurrentThreadId();
DWORD CONST_SW_SHOW = 5;
AttachThreadInput(windowThreadProcessId, currentThreadId, true);
BringWindowToTop(hwnd);
ShowWindow(hwnd, CONST_SW_SHOW);
AttachThreadInput(windowThreadProcessId,currentThreadId, false);
}
The original answer is here
P.S: I also dont think you should bring your message app to top if some message is coming up, but still ... this is the solution that working for my Qt App on Windows 10
I have an application that is essentially a "helper" application that wraps another app.
The app that the user interacts with is a process that is created by the "helper" app like so:
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
memset(&processInfo, 0, sizeof(processInfo));
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
startupInfo.dwFlags = STARTF_USESTDHANDLES;
startupInfo.cb = sizeof(startupInfo);
int retval = CreateProcess(cmd, cmdLine, NULL, NULL, false,
CREATE_NO_WINDOW, NULL, NULL, &startupInfo,
&processInfo);
This process is an executable that I do not have the source code to and cannot make changes to.
The "helper" application does a few things based mainly on network traffic from the other app. At one point I want to display a file browse dialog from the helper app based on something the user does in the started UI process.
When I show the file dialog from the helper app, it's shown behind the UI of the process that was created, which isn't ideal. I tried calling SetForegroundWindow() from the helper app but it fails the criteria specified for SetForegroundWindow in the MSDN docs ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539%28v=vs.85%29.aspx ), namely:
The process is not the foreground process.
The process was not started by the foreground process.
(even though the process created the foreground process).
Is there a way to call CreateProcess() with a flag or setting that works like calling AllowSetForegroundWindow() from that process? Or a flag that can be used to make Windows think the started process is "the same" as the process that started it for purposes of SetForegroundWindow permissions?
Or is there another way I can show the dialog generated by the helper app on top of the created process' dialogs?
The only solution I could think of off the top of my head would be to do remote thread injection into the child process, and then have your injected thread call AllowSetForegroundWindow with the appropriate parameters to allow the parent process to steal foreground-ness back.
I have not tested this though.
I'm adapting an application for touch screen interface and we want to use the tablet text input panel included in Windows Vista/7, specifically its keyboard. I want to show and hide it as appropriate for my app. Basically I want ShowKeyboard() and HideKeyboard() functions. What's the best way to control this?
I looked at the ITextInputPanel API but I was unable to control the keyboard directly with it (maybe I missed something?). I have also unsuccessfully tried to send window messages to its window.
The application is written in C++/MFC.
Any pointers at all are greatly appreciated.
I solved the problem. It turns out that Spy++ really is a Windows programmers best friend.
First, the window class of the input panel window turns out to be "IPTip_Main_Window". I use this to get the window handle like so:
HWND wKB = ::FindWindow(_TEXT("IPTip_Main_Window"), NULL);
It turns out that I can just post the same WM_COMMAND messages that its own menu is sending. Most of the operations are available from the menu: dock top, dock bottom and float. The code for sending those messages are:
::PostMessage(wKB, WM_COMMAND, MAKEWPARAM(X,0) , 0);
where X is 10021 for dock bottom, 10023 for dock top and 10020 for floating. The 0 in the high word indicates that the message is sent from a menu.
Finally, I wanted to be able to show and hide the input panel. I noticed that I could turn on a desk band which only includes a single button for toggling the visibility of the input panel. Spy++ing on the messages posted from this button revealed that it sends a global registered window message which is named "TabletInputPanelDeskBandClicked".
Sending this message to the input panel causes it to toggle its visibility.
The HideKeyboard() function now looks like this:
DWORD WM_DESKBAND_CLICKED =
::RegisterWindowMessage(_TEXT("TabletInputPanelDeskBandClicked"));
void HideKeyboard()
{
HWND wKB = ::FindWindow(_TEXT("IPTip_Main_Window"), NULL);
if(wKB != NULL && ::IsWindowVisible(wKB))
{
::PostMessage(wKB, WM_DESKBAND_CLICKED, 0, 0);
}
}
The ShowWindow() function is implemented similarly, but it will also start the keyboard if it is not running.
Update:
It seems that this inter-process messaging is disallowed in Windows Vista/7. When running this command in a non-elevated process it will fail with "access denied". My guess is that this is caused by User Interface Process Isolation (UIPI) protection found in Windows Vista/7. Since the Tablet PC Input Panel is running as a child process of a service it has higher integrity level than user programs, and thus cannot be sent any (or a very limited set of) messages to.
Update:
It turns out that the Tablet PC Input Panel is indeed running in high integrity level, whereas processes started by a limited user account is medium integrity level.
For Windows 8:
Note: Just like the Windows 7 solution, this requires an elevated process.
The input panel is not a descendant of HWND_DESKTOP. (It's probably some kind of Metro window.) In order to get the window handle, do a series of horizontal sweeps in a grid-like pattern testing with WindowFromPoint(). For each test, check the window class of the parent window to see if it is "IPTip_Main_Window".
To show the input panel, launch "C:\\Program Files\\Common Files\\microsoft shared\\ink\\tabtip.exe". To determine if it is already in docked mode, read registry key:
HKEY_CURRENT_USER\Software\Microsoft\TabletTip\1.7\EdgeTargetDockedState
A value of 0 indicates the input panel is in floating mode. If that was the case, post the following message to toggle the docked state:
DWORD WM_DOCK_BUTTON_PRESSED = ::RegisterWindowMessage(_TEXT("IPTipDockButtonPressed"));
PostMessage(hwndInputPanel, WM_DOCK_BUTTON_PRESSED, 0, 0);
To hide the keyboard, post the following:
PostMessage(hwndInputPanel, WM_SYSCOMMAND, SC_CLOSE, 0);