使用SendMessage()模拟鼠标点击无法传递至某款模拟器窗口的问题
SendMessage() Mouse Clicks in Your Second Emulator Hey there, let's figure out why your second emulator isn't responding to those SendMessage() mouse events, even though Nox Player works perfectly. Since you've already confirmed the window handle and message delivery via Spy++, here are the most likely fixes to try:
1. Check if the target handle is actually the input-receiving window
Even if you have the main emulator window handle, some emulators route input to a child window (like a DirectX/OpenGL render surface) instead of the main window. Try these steps:
- Use Spy++ to drill down into the emulator's window hierarchy (look for child windows with class names like
WindowsForms10.Window.8.app.0.34f558_r11_ad1or similar render containers). - Use
EnumChildWindows()to iterate through all child windows of the main emulator handle, and test sending the mouse messages to each child until you find the one that responds.
Example snippet for enumerating child windows:
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { // Test sending WM_LBUTTONDOWN/UP to this hwnd here SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y)); SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(x, y)); return TRUE; } // Call this with your main emulator handle EnumChildWindows(emulatorMainHandle, EnumChildProc, 0);
2. Verify your coordinate system
MAKELPARAM() expects client-area coordinates relative to the target window, not screen coordinates. If you're passing screen coordinates directly, the emulator might be receiving clicks outside its visible area. Fix this by converting screen coords to client coords:
POINT clientPoint; clientPoint.x = screenX; clientPoint.y = screenY; ScreenToClient(targetHwnd, &clientPoint); // Now use clientPoint.x/y in MAKELPARAM SendMessage(targetHwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(clientPoint.x, clientPoint.y));
3. Check for permission mismatches
If your second emulator runs with administrator privileges but your sending program doesn't, Windows will block cross-privilege SendMessage() calls as a security measure. Try:
- Running your sending program as Administrator.
- Checking if the emulator has any elevated security settings that prevent external message injection.
4. Switch to SendInput() for hardware-level input simulation
Some emulators (especially those using custom input pipelines) ignore Windows message-based input and only respond to "real" hardware input events. SendInput() simulates physical mouse clicks, which is more likely to work:
// First activate the emulator window SetForegroundWindow(targetHwnd); Sleep(100); // Give time for the window to focus // Move mouse to the target position (screen coordinates converted to absolute input scale) INPUT input = {0}; input.type = INPUT_MOUSE; input.mi.dx = (LONG)((screenX * 65535.0f) / GetSystemMetrics(SM_CXSCREEN)); input.mi.dy = (LONG)((screenY * 65535.0f) / GetSystemMetrics(SM_CYSCREEN)); input.mi.mouseData = 0; input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; SendInput(1, &input, sizeof(INPUT)); // Left mouse down ZeroMemory(&input, sizeof(input)); input.type = INPUT_MOUSE; input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; SendInput(1, &input, sizeof(INPUT)); // Left mouse up ZeroMemory(&input, sizeof(input)); input.type = INPUT_MOUSE; input.mi.dwFlags = MOUSEEVENTF_LEFTUP; SendInput(1, &input, sizeof(INPUT));
5. Test with PostMessage() instead
Sometimes SendMessage() blocks or is rejected, while PostMessage() (which queues the message instead of waiting for a response) works better. Replace your SendMessage() calls with PostMessage() and see if that makes a difference:
PostMessage(targetHwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(clientX, clientY)); PostMessage(targetHwnd, WM_LBUTTONUP, 0, MAKELPARAM(clientX, clientY));
Start with checking the child windows and coordinate system first—those are the most common culprits when one app works and another doesn't.
内容的提问来源于stack exchange,提问作者user7346067




