2009-04-30 13 views
6

Ho bisogno di simulare un keypress in un'applicazione di terze parti. Diciamo che ho un'applicazione C# che deve inviare un "8" all'applicazione Calcolatrice. Non posso usare SendKeys di .Net o keybd_event di win32 api perché entrambi richiedono che la finestra sia la più attiva, il che non è il caso nella mia situazione.Non riesco a capire come utilizzare le chiamate SendMessage o PostMessage

Quindi questo mi lascia con le chiamate sendMessage e postMessage. Ho provato nelle ultime tre ore a cercare di ottenere dei risultati ma in questo momento sono completamente senza speranza.

Ho il seguente:

 [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); 
    } 

Come potete vedere, io faccio quattro tentativi di comunicare con la calcolatrice. Utilizzare sendMessage e PostMessage per chiudere la finestra e anche per inviare la chiave 7. Niente funziona. Il metodo FindWindow funziona perché ottengo il gestore dell'app (ho persino provato a lanciare il processo da solo e ad accedervi con process.MainWindowHandler, ma senza fortuna). Non ci sono errori o eccezioni, ma semplicemente non fa nulla in Calcolatrice.

Ho provato anche le stesse identiche cose con il blocco note e non è cambiato nulla.

risposta

11

Qualche possibilità si sta eseguendo su una macchina a 64 bit? Se è così, credo che tutti quei valori "int" che sono in realtà hWnds (primo argomento di Send/Post, valore restituito da FindWindow) devono essere IntPtr.


Dopo un po 'più di controllo, sembra che sia SendMessage e PostMessage, il 1 °, 3 ° e 4 ° parametri deve essere IntPtr invece di int (così come i valori restituiti per tutti questi)

Così, le firme giusta sarebbe:

[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. Ha funzionato? Parla di una congettura fortunata. Non ho mai nemmeno usato quei due particolari metodi win32. –

+0

Im in realtà su 32 bit, ma ha funzionato comunque :) –

+0

Ehi, qualunque cosa funzioni :) –

3

C'è un buon articolo su questo su CodeProject: http://www.codeproject.com/KB/cs/SendKeys.aspx

SendKeys è in realtà l'idea corretta, ma è necessario ottenere l'HWND (handle della finestra) della finestra di destinazione. This MSDN sample mostra come utilizzare SendKeys in modo efficace, ma non come scoprire l'HWND di qualcosa di diverso dalla finestra più in alto.

Combinare le due tecniche, utilizzando l'esempio CodeProject per individuare l'HWND dell'applicazione che si desidera utilizzare, quindi utilizzare l'articolo MSDN per utilizzare SendKeys per inviare i tratti di chiave (o gli eventi del mouse) all'applicazione di destinazione.

2

Non direttamente alla tua domanda, ma la differenza tra SendMessage e PostMessage è che Send è una chiamata di blocco, Post restituisce immediatamente (prima che l'applicazione ricevente ha elaborato esso).

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

Anche se si è in vista, ma non su .NET 3.0 che potrebbe anche essere un problema:

La classe SendKeys è stato aggiornato per .NET Framework 3.0 per abilitarne l'uso in applicazioni eseguite su Windows Vista. La maggiore sicurezza di Windows Vista (nota come Controllo dell'account utente o Controllo dell'account utente) impedisce il corretto funzionamento dell'implementazione precedente.

1

Poiché si tratta di una finestra Modifica bambino all'interno della finestra del blocco note. Dovresti inviare messaggi alla finestra figlio giusta. È un esempio funzionante in 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); 
    } 
} 
Problemi correlati