Press a button on a calculator with SendMessage WinApi

Andreyka_ 136 Reputation points
2020-08-30T18:20:45.797+00:00

Hello,

I'm trying to emulate a button click on the Window 10 calculator. Since there are no real buttons of the "Button class" in the calculator, then:
I look through spy ++ which messages are sent to the calculator window when I click, for example, on the number 8:

000201C6 S WM_PARENTNOTIFY fwEvent:WM_LBUTTONDOWN xPos:191 yPos:493

I am sending the same message to the Calculator window:

HWND calculator_HWND = FindWindowW(NULL, L"Calculator"); //Get HWND calculator

WPARAM my_wparam;

wchar_t* wchar_wparam = (wchar_t*)&my_wparam;
wchar_wparam[0] = WM_LBUTTONDOWN;  // LOWORD-left click
wchar_wparam[1] = 0;   //HIWORD(wParam) is undefined.                                           
                

LPARAM my_lparam; //Coordinate click

wchar_t* wchar_laparam = (wchar_t*)&my_lparam;
wchar_laparam[0] = 191;            //X                                         
wchar_laparam[1] = 493;            //Y                                      

SendMessage(calculator_HWND, WM_PARENTNOTIFY, my_wparam, my_lparam);
After completing the SendMessage, I see a message in the calculator window in SPY ++:

000201C6 S WM_PARENTNOTIFY fwEvent:WM_LBUTTONDOWN xPos:191 yPos:493
But the number 8 is not pressed. The calculator does not respond to this message in any way. :(((

Please tell me what am I doing wrong?

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,498 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Castorix31 82,751 Reputation points
    2020-08-30T19:48:59.357+00:00

    A way is with IUIAutomation

    I still cannot post code on those *$#@! forums, so I posted a test on Pastebin :
    Test IUIAutomation Calc


  2. Rita Han - MSFT 2,161 Reputation points
    2020-08-31T07:07:44.19+00:00

    Hello,

    Three possibilities:

    1. Before "click mouse button", move the cursor to the target position. (I can't see mouse movement operation in your code piece.)
    2. WM_LBUTTONDOWN use the coordinate is relative to the upper-left corner of the client area. So if you specify (x,y) as screen coordinate, you can convert it to window client coordinate using ScreenToClient.
    3. Push Button "8" is in a child window of calculator_HWND. You can find this child window like this: FindWindowEx(calculator_HWND, NULL, L"ApplicationFrameInputSinkWindow", NULL);

    SendMessage is not guaranteed to work for other types of applications. So even if you meet all above requirements but it still may not work like a case of Calculator. However the same code (SendMessageA(inputSinkWindow, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(clientpPoint.x, clientpPoint.y));) works for mspaint.exe.

    To synthesize keystrokes, mouse motions, and button clicks, use SendInput instead of SendMessage.

    The following is a code sample using SendInput, it works for me. You can have a try.

    HWND calculator_HWND = NULL;  
      
    while (!calculator_HWND)  
    {  
    calculator_HWND = FindWindowW(NULL, L"Calculator"); //Get HWND calculator  
    }  
      
    HWND inputSinkWindow = FindWindowEx(calculator_HWND, NULL, L"ApplicationFrameInputSinkWindow", NULL);  
      
    int x = 370, y = 516;  
      
      
    int sx = GetSystemMetrics(SM_CXSCREEN);  
    int sy = GetSystemMetrics(SM_CYSCREEN);  
      
    long x_calc = x * 65536 / sx;  
    long y_calc = y * 65536 / sy;  
      
    INPUT mi = { 0 };  
    mi.type = INPUT_MOUSE;  
    mi.mi.dx = x_calc;  
    mi.mi.dy = y_calc;  
    mi.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN;  
      
    UINT eventCount = SendInput(1, &mi, sizeof(mi));  
      
    mi.mi.dwFlags = MOUSEEVENTF_LEFTUP;  
      
    eventCount = SendInput(1, &mi, sizeof(mi));  
    

    Thank you!