Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>To detect a button press in another process, you have to hook that process. You have four choices for doing that:</p> <ol> <li><p>use <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowsHookEx()</code></a> to install a <code>WH_CALLWNDPROC</code> or <code>WH_GETMESSAGE</code> hook into the target process to catch the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb761825%28v=vs.85%29.aspx" rel="nofollow"><code>WM_COMMAND/BN_CLICKED</code></a> message that is sent to the button's parent window when the button is clicked. The message identifies the <code>HWND</code> and ID of the button that was clicked. The hook <strong>must</strong> be implemented in a DLL so it can be injected into another process.</p></li> <li><p>use <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx" rel="nofollow"><code>SetWinEventHook()</code></a> to catch the <code>EVENT_OBJECT_INVOKED</code> event when the button is clicked. The hook callback identifies the <code>HWND</code> and ID of the button that was clicked. The hook <strong>should</strong> be implemented in a DLL so it can be injected into the target process for better performance, but is not <strong>required</strong>. If you do not use a DLL, the hooking thread <strong>must</strong> have a message loop to receive the events as they will have to be passed across process boundaries.</p></li> <li><p>use <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowsHookEx()</code></a> or <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437%28v=vs.85%29.aspx" rel="nofollow"><code>CreateRemoteThread()</code></a> to inject code into the target process and have that code then subclass the button's parent window using <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644898%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowsLongPtr(GWL_WNDPROC)</code></a> or <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb762102%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowSubclass()</code></a> in order to catch the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb761825%28v=vs.85%29.aspx" rel="nofollow"><code>WM_COMMAND/BN_CLICKED</code></a> message that is sent to that parent window.</p></li> <li><p>use <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx" rel="nofollow">UI Automation</a>. Create an instance of the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee671406.aspx" rel="nofollow"><code>IUIAutomation</code></a> interface using the <code>CoCreateInstance()</code> function, then use the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee671534.aspx" rel="nofollow"><code>IUIAutomation::ElementFromHandle()</code></a> method to get an <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee671425.aspx%2a" rel="nofollow"><code>IUIAutomationElement</code></a> interface from the button's <code>HWND</code> (or obtain the button's <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee671425.aspx%2a" rel="nofollow"><code>IUIAutomationElement</code></a> interface through other means), then use the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee671508.aspx" rel="nofollow"><code>IUIAutomation::AddAutomationEventHandler()</code></a> method to subscribe to the <code>UIA_Invoke_InvokedEventId</code> event for that button.</p></li> </ol> <p>If you have the <code>HWND</code> of the target button, you can use <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms633522%28v=vs.85%29.aspx" rel="nofollow"><code>GetWindowThreadProcessId()</code></a> to retrieve the button's process ID and thread ID. You will need the button's parent window <code>HWND</code> (which you can get using <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms633510%28v=vs.85%29.aspx" rel="nofollow"><code>GetParent()</code></a> if needed) in order to use <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644898%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowsLongPtr(GWL_WNDPROC)</code></a> or <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb762102%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowSubclass()</code></a>.</p> <p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowsHookEx()</code></a> and <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx" rel="nofollow"><code>SetWinEventHook()</code></a> allow you to specify the specific thread ID to hook (and in the case of <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx" rel="nofollow"><code>SetWinEventHook()</code></a>, the specific process ID as well) so you can minimize overhead used in hooking. <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437%28v=vs.85%29.aspx" rel="nofollow"><code>CreateRemoteThread()</code></a> requires the target process handle, which you can get with <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx" rel="nofollow"><code>OpenProcess()</code></a> using the process ID.</p> <p>So, as you can see, what you are asking for is not going to be trivial to implement. In my opinion (not definitive), the order of techniques from easiest to hardest, in terms of coding, would be:</p> <ol> <li><p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx" rel="nofollow"><code>SetWinEventHook()</code></a> without a DLL (but at the cost of affecting performance).</p></li> <li><p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx" rel="nofollow">UI Automation</a>.</p></li> <li><p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowsHookEx()</code></a>, or <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx" rel="nofollow"><code>SetWinEventHook()</code></a> with a DLL.</p></li> <li><p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990%28v=vs.85%29.aspx" rel="nofollow"><code>SetWindowsHookEx()</code></a> because of the extra injection code and subclassing</p></li> </ol>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload