Para enviar pulsaciones ya sea del teclado o el ratón a una ventana minimizada, puedes usar la función
PostMessage de la API de Windows:
Pasos a seguir para enviar la pulsación del botón izquierdo del ratón a una ventana minimizada:
- Localizar la ventana que pretendes clickar, ya sea la ventana principal de un proceso, o una ventana hija ( ej. la ventana de un botón ). Para esto último deberás documentarte sobre las funciones FindWindowEx, EnumWindows, EnumChildWindows y relacionadas, o bien puedes recurrir a la API administrada de Microsoft UI Automation:
- Activar dicha ventana enviandole el mensaje de ventana WM_ACTIVATE.
- Enviarle a esa ventana el mensaje WM_LBUTTONDOWN seguido de WM_LBUTTONUP; o solamente el mensaje BM_CLICK en el caso de tratarse de la ventana de un botón.
No caigas en el típico error de enviarle el mensaje
WM_LBUTTONDOWN y
WM_LBUTTONUP a la ventana principal de un proceso posicionando las coordenadas sobre un control/ventana hija para clickarlo, por que en principio eso no te va a funcionar así; tienes que enviarle los mensajes a la ventana exacta que pretendas clickar, insisto.
Aquí tienes todo lo necesario:
( código extraido de mi librería comercial
DevCase for .NET Faamework y modificado para adaptarse a las circunstancias. )
NativeMethods.vb' ***********************************************************************
' Author : ElektroStudios
' Modified : 14-March-2019
' ***********************************************************************
#Region " Option Statements "
Option Strict On
Option Explicit On
Option Infer Off
#End Region
#Region " Imports "
Imports System.Diagnostics.CodeAnalysis
#End Region
#Region " NativeMethods "
' Namespace DevCase.Interop.Unmanaged.Win32
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Platform Invocation methods (P/Invoke), access unmanaged code.
''' <para></para>
''' This class does not suppress stack walks for unmanaged code permission.
''' <see cref="Global.System.Security.SuppressUnmanagedCodeSecurityAttribute"/> must not be applied to this class.
''' <para></para>
''' This class is for methods that can be used anywhere because a stack walk will be performed.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://msdn.microsoft.com/en-us/library/ms182161.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
Public NotInheritable Class NativeMethods
#Region " Constructors "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Prevents a default instance of the <see cref="NativeMethods"/> class from being created.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<DebuggerNonUserCode>
Private Sub New()
End Sub
#End Region
#Region " User32.dll "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Places (posts) a message in the message queue associated with the thread that created
''' the specified window and returns without waiting for the thread to process the message.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://msdn.microsoft.com/es-es/library/windows/desktop/ms644944%28v=vs.85%29.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <param name="hWnd">
''' Handle to the window whose window procedure will receive the message.
''' <para></para>
''' If this parameter is <see cref="WindowMessages.HWND_Broadcast"/>,
''' the message is sent to all top-level windows in the system,
''' including disabled or invisible unowned windows, overlapped windows, and pop-up windows;
''' but the message is not sent to child windows.
''' </param>
'''
''' <param name="message">
''' Specifies the message to be sent.
''' </param>
'''
''' <param name="wparam">
''' Specifies additional message-specific information.
''' </param>
'''
''' <param name="lparam">
''' Specifies additional message-specific information.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' If the function succeeds, the return value is <see langword="True"/>.
''' <para></para>
''' If the function fails, the return value is <see langword="False"/>.
''' <para></para>
''' To get extended error information, call <see cref="Marshal.GetLastWin32Error()"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible", Justification:="Visible for API users")>
<DllImport("User32.dll", SetLastError:=True)>
Public Shared Function PostMessage(ByVal hWnd As IntPtr,
ByVal message As Integer,
ByVal wparam As IntPtr,
ByVal lparam As IntPtr
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Sends the specified message to a window or windows.
''' <para></para>
''' The SendMessage function calls the window procedure for the specified window
''' and does not return until the window procedure has processed the message.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950%28v=vs.85%29.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <param name="hWnd">
''' A handle to the window whose window procedure will receive the message.
''' </param>
'''
''' <param name="msg">
''' The message to be sent.
''' </param>
'''
''' <param name="wParam">
''' Additional message-specific information.
''' </param>
'''
''' <param name="lParam">
''' Additional message-specific information.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The return value specifies the result of the message processing; it depends on the message sent.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible", Justification:="Visible for API users")>
<DllImport("User32.dll", SetLastError:=True)>
Public Shared Function SendMessage(ByVal hWnd As IntPtr,
ByVal msg As Integer,
ByVal wParam As IntPtr,
ByVal lParam As IntPtr
) As IntPtr
End Function
#End Region
End Class
' End Namespace
#End Region
NativeUtil.vb' ***********************************************************************
' Author : ElektroStudios
' Modified : 09-September-2017
' ***********************************************************************
#Region " Option Statements "
Option Strict On
Option Explicit On
Option Infer Off
#End Region
#Region " Imports "
#End Region
#Region " Native Util "
' Namespace DevCase.Interop.Unmanaged.Win32
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Contains win32 related utilites.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
Public NotInheritable Class NativeUtil
#Region " Constructors "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Prevents a default instance of the <see cref="NativeUtil"/> class from being created.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<DebuggerNonUserCode>
Private Sub New()
End Sub
#End Region
#Region " Public Methods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Creates a (32-Bit Unsigned Integer) DWORD value from a LOWORD and a HIWORD.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim value as UInteger = MakeDWord(UShort.MaxValue, UShort.MaxValue)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="loWord">
''' The low-order WORD.
''' </param>
'''
''' <param name="hiWord">
''' The high-order WORD.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting DWORD value.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Function MakeDWord(ByVal loWord As UShort, ByVal hiWord As UShort) As UInteger
Dim loBytes As Byte() = BitConverter.GetBytes(loWord)
Dim hiBytes As Byte() = BitConverter.GetBytes(hiWord)
Dim combined As Byte() = loBytes.Concat(hiBytes).ToArray()
Return BitConverter.ToUInt32(combined, 0)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Creates a lParam value from two <see cref="System.Int32"/> values.
''' <para></para>
''' You must call this method overload if you need to use negative values.
''' <para></para>
''' <seealso cref="Windows.Forms.Message.LParam"/>
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-makelparam"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim lParam as IntPtr = MakeLParam(Integer.MaxValue, Integer.MaxValue)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="lo">
''' The low-order <see cref="System.Int32"/> value.
''' </param>
'''
''' <param name="hi">
''' The high-order <see cref="System.Int32"/> value.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting lParam value.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Function MakeLParam(ByVal lo As Integer, ByVal hi As Integer) As IntPtr
Dim loBytes As Byte() = {BitConverter.GetBytes(lo)(0), BitConverter.GetBytes(lo)(1)}
Dim hiBytes As Byte() = {BitConverter.GetBytes(hi)(0), BitConverter.GetBytes(hi)(1)}
Dim combined As Byte() = loBytes.Concat(hiBytes).ToArray()
Return New IntPtr(BitConverter.ToInt32(combined, 0))
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Creates a lParam value from two <see cref="System.UInt16"/> values.
''' <para></para>
''' <seealso cref="Windows.Forms.Message.LParam"/>
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-makelparam"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example.
''' <code>
''' Dim lParam as IntPtr = MakeLParam(UShort.MaxValue, UShort.MaxValue)
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="loWord">
''' The low-order WORD.
''' </param>
'''
''' <param name="hiWord">
''' The high-order WORD.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting lParam value.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Function MakeLParam(ByVal loWord As UShort, ByVal hiWord As UShort) As IntPtr
Return New IntPtr(MakeDWord(loWord, hiWord))
End Function
#End Region
End Class
' End Namespace
#End Region
+
( código hecho al vuelo. )
Const WM_ACTIVATE As Integer = &H6 ' https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-activate
Const WM_LBUTTONDOWN As Integer = &H201 ' https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-lbuttondown
Const WM_LBUTTONUP As Integer = &H202 ' https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-lbuttonup
Const MK_LBUTTON As Integer = &H1 ' https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-lbuttondown
Const BM_CLICK As Integer = &HF5 ' https://docs.microsoft.com/en-us/windows/desktop/controls/bm-click
Public Shared Sub SendLeftClickToWindow(ByVal hWnd As IntPtr, ByVal pt As Point)
Dim wParam As IntPtr = New IntPtr(MK_LBUTTON)
Dim lParam As IntPtr = NativeUtil.MakeLParam(pt.X, pt.Y)
NativeMethods.SendMessage(hWnd, WM_ACTIVATE, IntPtr.Zero, IntPtr.Zero)
NativeMethods.PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam)
Thread.Sleep(100)
NativeMethods.PostMessage(hWnd, WM_LBUTTONUP, IntPtr.Zero, lParam)
End Sub
Public Shared Sub SendLeftClickToButton(ByVal hWnd As IntPtr)
NativeMethods.SendMessage(hWnd, WM_ACTIVATE, IntPtr.Zero, IntPtr.Zero)
NativeMethods.PostMessage(hWnd, BM_CLICK, IntPtr.Zero, IntPtr.Zero)
End Sub
Ejemplo para enviar la pulsación del botón izquierdo del ratón a la ventana principal de un proceso:
Dim hWnd As IntPtr = Process.GetProcessById(...).MainWindowHandle
Dim pt As New Point(0, 0)
SendLeftClickToWindow(hWnd, pt)
Ejemplo para enviar la pulsación del botón izquierdo del ratón a una ventana de tipo BUTTON:
Dim hWnd As IntPtr = New IntPtr(...)
SendLeftClickToButton(hWnd)
Si necesitas usar coordenadas negativas (Int32), en principio la sobrecarga de la función
NativeUtil.MakeLParam que he compartido debería funcionar correctamente (para ser sinceros no he testeado mucho esa sobrecarga), de lo contrario debes adaptar el código teniendo en cuenta lo siguiente:
Y aquí tienes algo más de info y ejemplos que publiqué en otra pregunta relacionada:
EDITO: acabo de darme cuenta de que eres el mismo usuario que publicó esa otra pregunta... joder entonces todo esto que expliqué ya deberías saberlo, jeje.
Eso es todo. Saludos.