2009-04-30 24 views
6

Necesito simular una pulsación de tecla en una aplicación de un tercero. Digamos que tengo una aplicación C# que necesita enviar un "8" a la aplicación Calculadora. No puedo usar SendKeys de .Net o keybd_event de win32 api porque ambos requieren que la ventana sea la superior activa, lo que no es el caso en mi situación.No puedo entender cómo usar las llamadas a SendMessage o PostMessage

Eso me deja con las llamadas sendMessage y postMessage. He estado tratando en las últimas tres horas tratando de obtener algunos resultados, pero ahora mismo estoy completamente perdido.

Tengo el siguiente:

 [DllImport("user32.dll")] 
    public static extern int FindWindow(string lpClassName,string lpWindowName); 
    [DllImport("user32.dll")] 
    public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam); 

    [return: MarshalAs(UnmanagedType.Bool)] 
    [DllImport("user32.dll", SetLastError = true)] 
    public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam); 

    private void button1_Click(object sender, EventArgs e) 
    { 
     const int WM_KEYDOWN = 0x100; 
     const int WM_SYSCOMMAND = 0x018; 
     const int SC_CLOSE = 0x053; 

     int WindowToFind = FindWindow(null,"Calculator"); 

     int result = SendMessage(WindowToFind, WM_SYSCOMMAND, SC_CLOSE, 0); 
     Boolean result2 = PostMessage(WindowToFind, WM_SYSCOMMAND, SC_CLOSE, 0); 

     int result3 = SendMessage(WindowToFind, WM_KEYDOWN,((int)Keys.NumPad7), 0); 
     Boolean result4 = PostMessage(WindowToFind, WM_KEYDOWN, ((int)Keys.NumPad7), 0); 
    } 

Como se puede ver, hago cuatro intentos de comunicarse con la calculadora. Usar sendMessage y PostMessage para cerrar la ventana y también para enviar la clave 7. Nada funciona. El método FindWindow funciona porque obtengo el controlador de la aplicación (incluso he intentado iniciar el proceso yo mismo y acceder a él con process.MainWindowHandler, pero no tuve suerte). No hay errores o excepciones, pero simplemente no hace nada en la Calculadora.

También he intentado exactamente lo mismo con el bloc de notas y nada ha cambiado demasiado.

Respuesta

11

¿Hay alguna posibilidad de que esté ejecutando esto en una máquina de 64 bits? Si es así, creo que todos esos valores 'int' que en realidad son hWnds (primer argumento para Enviar/Publicar, devolver valor desde FindWindow) deben ser IntPtr.


Después de un poco más de cheques, parece que tanto SendMessage y PostMessage, el 1º, 3º y 4º parámetros debe IntPtr en lugar de int (así como los valores de retorno de todos ellos)

Así, las firmas correctas serían:

[DllImport("user32.dll")] 
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName); 
[DllImport("user32.dll")] 
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 
[DllImport("user32.dll")] 
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 
+0

Wow. ¿Eso funciono? Habla de una adivinación afortunada. Nunca he usado esos dos métodos particulares de win32. –

+0

Estoy realmente en 32bits, pero funcionó sin embargo :) –

+0

Oye, lo que funcione :) –

3

Hay un buen artículo sobre esto en CodeProject: http://www.codeproject.com/KB/cs/SendKeys.aspx

SendKeys es realmente la idea correcta, pero debe obtener HWND (identificador de ventana) de la ventana de destino. This MSDN sample muestra cómo utilizar SendKeys de manera efectiva, pero no cómo descubrir el HWND de otra cosa que no sea la ventana superior.

Combine las dos técnicas, utilizando el ejemplo de CodeProject para localizar el HWND de la aplicación que desea apuntar, luego use el artículo de MSDN para usar SendKeys para enviar los trazos de tecla (o eventos de mouse) a la aplicación de destino.

2

No directamente a su pregunta, pero la diferencia entre SendMessage y PostMessage es que Send es una llamada de bloqueo, Post vuelve inmediatamente (antes de la aplicación receptora ha procesado).

MSDN explica la diferencia: http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx

Además, si usted está en Vista, pero no en .NET 3.0, que también podría ser un problema:

La clase SendKeys se ha actualizado para .NET Framework 3.0 para permitir su uso en aplicaciones que se ejecutan en Windows Vista. La seguridad mejorada de Windows Vista (conocida como Control de cuentas de usuario o UAC) impide que la implementación anterior funcione como se esperaba.

1

Porque es una ventana Edit Child dentro de la ventana del bloc de notas. Debe enviar mensajes a la ventana secundaria derecha. Es un ejemplo de trabajo en C:

#include <windows.h> 
#include <stdio.h> 

void main(void) { 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 
    HWND mainwnd,editwnd; 
    char c; 
    si.cb=sizeof(si); 
    si.lpReserved=NULL; 
    si.lpDesktop=NULL; 
    si.lpTitle=NULL; 
    si.dwFlags=0; 
    si.cbReserved2=0; 
    si.lpReserved2=NULL; 
    if(!CreateProcess("c:\\windows\\notepad.exe",NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) { 
     printf("Failed to run app"); 
     return; 
    } 
    WaitForInputIdle(pi.hProcess,INFINITE); 
    mainwnd=FindWindow(NULL,"Untitled - Notepad"); 
    if(!mainwnd) { 
     printf("Main window not found"); 
     return; 
    } 
    editwnd=FindWindowEx(mainwnd,NULL,"Edit",""); 
    if(!editwnd) { 
     printf("Edit window not found"); 
     return; 
    } 
    for(c='1';c<='9';c++) { 
     PostMessage(editwnd,WM_CHAR,c,1); 
     Sleep(100); 
    } 
} 
Cuestiones relacionadas