Premere a livello di programmazione un pulsante su un'altra applicazione (C, Windows)

StackOverflow https://stackoverflow.com/questions/1223872

  •  11-07-2019
  •  | 
  •  

Domanda

Sto cercando di utilizzare il seguente codice per premere un pulsante sull'altra mia applicazione:

HWND ButtonHandle;
if( (wnd = FindWindow(0, "Do you want to save?")) )
{   
   ButtonHandle = FindWindowEx(wnd, 0, "SaveButton", "&Save");
   SendMessage(wnd, WM_COMMAND, MAKEWORD(GetDlgCtrlID(ButtonHandle), BN_CLICKED ), (LPARAM)ButtonHandle);

}

Non funziona. Ho provato a passare diversi handle a MAKEWORD e a cambiare WPARM e LPARAM ma niente.

Qualche idea su come fare clic su un pulsante nella finestra di un'altra applicazione?

Il codice è apprezzato. Grazie.

EDIT: Il motivo per cui non sembra funzionare le autorizzazioni. Ho inviato un PostMessage () e il risultato è stato un errore con GetLastError () = 5 (o Accesso negato). Qualche idea?

EDIT2 Non intendo essere scortese, ma per favore, per favore, per favore, ho già cercato tutte le API tra cui ottenere e impostare le regioni per il pulsante e quindi inviare un pulsante in basso e un pulsante in alto, ottenendo l'ID di controllo, ottenendo l'ID di classe e altri mille. Il motivo per cui ho posto la domanda qui in primo luogo è perché ho già esaurito la mia ricerca su Internet. Se conosci la risposta PER FAVORE CODICE POSTALE , non suggerire un'API e basta, mostrami come l'API risolve il problema. Non è difficile. grazie.

MODIFICA 3: la risposta alla domanda è stata selezionata automaticamente al termine della taglia. La domanda rimane ancora senza risposta.

È stato utile?

Soluzione

  1. Sei sicuro che " SaveButton " il nome della classe è valido? Ottieni il pulsante gestire?
  2. Prova a inviare messaggi alla finestra ButtonHandle (direttamente al pulsante).

Aggiornamento: credo che dovrebbe funzionare,

SendMessage(ButtonHandle, BM_CLICK, 0, 0);

Altri suggerimenti

SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);
SendMessage(btnHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(btnHandle, WM_LBUTTONUP, 0, 0);

Devi inviare un pulsante due volte. Non so perché (forse il primo clic attiva solo la finestra del pulsante), ma sto usando questo codice da molto tempo e ha sempre funzionato per me.

Vedi la seguente soluzione, inoltre puoi usare

SendMessage(ButtonHandle, WM_LBUTTONDOWN, 0, 0);
SendMessage(ButtonHandle, WM_LBUTTONUP, 0, 0);

o

SendMessage(ButtonHandle, BM_CLICK, 0, 0);

HWND buttonHandle = 0;

BOOL CALLBACK GetButtonHandle(HWND handle, LPARAM)
{
 char label[100];
 int size = GetWindowTextA(handle,label,sizeof(label));
 if(strcmp(label,"&Save") == 0)
 {
  buttonHandle = handle;
  return false;
 }
 return true;
}
void main()
{
 HWND windowHandle = FindWindowA(NULL,"Do you want to Save?");
 if(windowHandle != 0)
 {
  BOOL ret = EnumChildWindows(windowHandle,GetButtonHandle,0);

  if(buttonHandle != 0)
  {
   LRESULT res = SendMessage(buttonHandle,BM_CLICK,0,0);
   //SendMessage(buttonHandle,WM_LBUTTONDOWN,0,0); 
   //SendMessage(buttonHandle,WM_LBUTTONUP,0,0);
  }

 }



}

Nota: Accertarsi dal testo della finestra, dal testo del pulsante (verificare se c'è spazio alla fine del titolo della finestra)

Gli errori di accesso negato su SendMessage o PostMessage non hanno senso a meno che il processo di invio del messaggio non sia eseguito a un livello di integrità inferiore rispetto al processo di destinazione.

Questo non dovrebbe accadere a meno che il processo che possiede la finestra di destinazione non sia in esecuzione " asAdministrator " o è un servizio. Ed è dannatamente difficile per i servizi creare finestre sul desktop interattivo con Windows 6 e versioni successive.

Puoi leggere alcune informazioni su Livelli di integrità qui se applicare anche in remoto a questa situazione. Internet Explorer riguarda l'unica altra applicazione che "aderisce" al modello di sicurezza dell'integrità abbassando di proposito il livello di integrità di se stesso al fine di eseguirne il sandbox in modo più efficace.

Se puoi alzare la finestra contenente il pulsante puoi inviare l'evento del mouse non elaborato in una posizione all'interno dei limiti del pulsante.

Esistono due funzioni per simulare l'evento del mouse SendInput e mouse_event . Consiglio di usare la funzione WM_CUSTOM. Per aprire una finestra è possibile utilizzare ShowWindow . Non so come ottenere la maniglia di un pulsante, ma se hai il suo hWnd è facile trovare la sua posizione assoluta usando GetWindowRect . Prova a usarli, se riscontri problemi saremo lieti di aiutarti.

O definisci una WM personalizzata nella finestra dell'applicazione per gestire la richiesta di salvataggio. WM_USER o <=> (non ricordo quale) segna l'inizio dei messaggi della finestra definiti dall'utente.

Quando devo fare questo tipo di cose uso SendKeys. È VB-ish e C # fornisce un'interfaccia piacevole da usare ma per C / C ++ dovrai farlo & Lt; in questo modo > ;. La cosa bella è che puoi scrivere script ed eseguirli invece di codificarli nel tuo codice.

Microsoft sta ora spingendo Accessibilità attiva (MSAA) per UI Automation, (È stato rinominato più volte nel corso degli anni)  vedi

Scusa, non ho & # 8217; non ho un semplice codice per iniziare. Come & # 8220; SendMessage () & # 8221; non sembra funzionare per te, non so & # 8217; t so di un'altra opzione oltre a & # 8220; UI Automation & # 8221;

Suppongo che tu abbia verificato con Spy ++ (installato con MsDev) che il tuo messaggio sia stato inviato al pulsante corretto ecc & # 8211; e che il pulsante è un normale pulsante di Windows. Il mio primo istante direbbe usare & # 8220; SendMessage () & Quot; oppure " PostMessage () & # 8221; ma dato il numero di risposte su & # 8220; SendMessage () & # 8221; e il fatto che non funziona per te. Mi aspetto che qualcuno stia succedendo su & # 8230;

Puoi usare sendkeys (come diceva tr3) per inviare clic del mouse, che è diverso dall'uso di SendMessage. È anche meno diretto e più hack-ish, ma è utile per l'automazione (in VBS).

Inoltre, solo un'ipotesi, ma il problema potrebbe essere che la gestione dei messaggi viene interrotta da qualche parte non chiamando il membro della classe base. Esempio:

void CMyClass::OnMessageY(CWnd *cwnd)
{
    CBaseClass::OnMessageY(cwnd);
    //... my code
}

se sei sicuro che ButtonHandle sia un handle valido, puoi utilizzare la coppia WM_LBUTTONDOWN e il messaggio WM_LBUTTONUP invece di BN_CLICKED

HWND ButtonHandle;
if( (wnd = FindWindow(0, "Do you want to save?")) )
{   
    SendMessage(ButtonHandle, WM_LBUTTONDOWN, MK_LBUTTON, 0);
    SendMessage(ButtonHandle, WM_LBUTTONUP, MK_LBUTTON, 0);
}

Un approccio non-C: usa Java e la classe java.awt.Robot per spostare il mouse in giro per fare clic reali (immagino che ci sia qualcosa anche nel mondo di Windows per questo). Problema: devi sapere dove si trova il tuo pulsante: D

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top