Newsgroup: it.comp.lang.delphi
Titolo: Intercettare pulsante senza caption (per megaesperti?)

buongiorno.
ho la necessita di creare un'applicazione che deve premere un pulsante che
si trova all'interno di un'altra applicazione, oppure rilevare quando il
pulsante č stato premuto.
Riporto quanto scritto da winsight, che ho usato per capire come funzionava
l'applicazione
....
Overlapped 0001017C {Afx:400000:b:10011:6:2013f} TH1394.exe
(31,-22)-(727,758) "TH71 data capture program"
....
--- child 0001020E {AfxControlBar42s} TH1394.exe (0,676)-(688,708) "Capture
control & Replay Control"
  |
  |__child 0001020E {#32770:Dialog} TH1394.exe (10,-2)-(586,32) "Capture
control & Replay Control"
     |
     |__Child 000101F2 {Button} TH1394.exe (12,4)-(37,30)
     |
     |__Child 000101F4 {Button} TH1394.exe (65,4)-(90,30)
     |
     |__Child 000101F8 {Button} TH1394.exe (hidden)
     |
     |__Child 000101FE {Button} TH1394.exe (39,4)-(64,30)
....
Il pulsante in questione dovrebbe essere il quarto.
Il pulsante non ha una caption, quindi come faccio a intercettarlo?
Vi ringrazio anticipatamente.

 Il pulsante non ha una caption, quindi come faccio a intercettarlo?
Non ho capito dove sia il tuo problema. Non sai come ottenere l' handle del
pulsante, come capire se l' handle che hai è quello corretto o che altro?
Se il problema è trovare l' handle del pulsante guarda la documentazione
circa FindWindow(), GetNextWindow() et similia.
Per "intercettare" il pulsante hai diverse alternative. La prima (più
semplice ma meno elegante) è quella di "interrogare" continuamente il
pulsante circa il suo stato (BM_GETSTATE) mentre la seconda è quella di
costruirti un hook che controlla le pressioni del mouse sull' applicazione
remota e scatena un evento nella tua applicazione. Per questa strada c'è un
esempio pronto nelle faq. Attento che le due soluzioni producono effetti
"simili" ma non uguali. Infatti nel primo caso ottieni un'
informazione_definitiva_a evento avvenuto, mentre nel secondo tu
"intercetti" un evento e potresti anche decidere di interromperlo.
--
- Carlo -

circa FindWindow(), GetNextWindow() et similia.
FindWindow() necessita che si conosca la classe (che può essere uguale
per tutti i pulsanti) o la caption (che è sconosciuta).
-- 
Andrea Laforgia
"640kb of memory should be enough for anyone." -- Bill Gates.

 per tutti i pulsanti) o la caption (che è sconosciuta).
Infatti deve usare FindWindow() sul parent del bottone e GetNextWindow() per
scorrere i pulsanti
--
- Carlo -

scorrere i pulsanti
E come fai a sapere quando sei arrivato ?


 E come fai a sapere quando sei arrivato ?
Potresti usare le coordinate del bottone
--
- Carlo -

Potresti usare le coordinate del bottone
Hmmm... dovrebbe funzionare, a meno che l'applicazione non si
comporti, per esempio, come WinZIP che, per precauzione, tutte le
volte sposta il bottone "I Agree".


 volte sposta il bottone "I Agree".
La gerarchia delle finestre rimane comunque invariata: cioč se localizzi il
bottone interessato dopo X chiamate a GetNextWindow() č certo che ogni volta
dovrai effettuare esattamente X chiamate a GetNextWindow() per riottenere l'
handle di quel bottone. Quindi basta effettuare qualche "tentativo" la prima
volta ed anche problemi come quello di WinZip son risolti
--
- Carlo -

La gerarchia delle finestre rimane comunque invariata: 
Non è affatto detto.
L'applicazione, a seconda dei casi, potrebbe creare o meno alcuni
controlli secondari a run-time, per esempio, e successivamente creare
il bottone stesso.  Inoltre, io potrei avere un controllo statico, ma
assegnare ad esso un evento in modo dinamico, etc... etc...


 il bottone stesso.
Parlavo, ovviamente, di applicazioni che non creano controlli a run-time.
Se introduci il discorso dei componenti creati a run-time cade la logica
della ricerca.
Un' applicazione potrebbe continuare a creare componenti con lo stesso
classname e magari senza caption il cui valore è solo "visivo" etc. -- a
questo punto non esiste funzione di ricerca che ti possa aiutare.
Ad ogni modo è possibile che i componenti creati successivamente vengano
"accodati" (parlo a livello di componenti "fratelli", ovvero figli di uno
stesso parent) in modo da non stravolgere l' ordine precedentemente
stabilito. Ma questo discorso cadrebbe gia' se si parlasse di componenti
distrutti a run-time e così via.
--
- Carlo -

Parlavo, ovviamente, di applicazioni che non creano controlli a run-time.
Il problema è che nessuno assicura che quella del nostro amico non lo
sia :( ...


 >Parlavo, ovviamente, di applicazioni che non creano controlli a run-time.
.

Secondo me, dovrebbe per prima cosa crearsi un qualcosa per controllare le
caratteristiche della finestra. Deve assicurarsi che esse non cambiano ogni
volta che avvia il software.
Assicuratosi di ciò, potrebbe anche basarsi, durante la ricerca dell'handle
del pulsante, sull'ID della finestra con un semplice getwindowlong.
Per la cattura dei messaggi non potrebbe poi hookare direttamente la window
procedure della finestra? Un handle, piuttosto che un indirizzo, potrebbe
essere possibile? O necessita che la window procedure appartenga al processo
proprietario del controllo?
A meno che non sia un pulsante vitale
alla sicurezza di tutto il software, credo che un programmatore non sia così
paranoico da perdere tempo a randomizzare le proprietà dei suoi controlli.
Ciao.
"Andrea Laforgia" <x@x.x> ha scritto nel messaggio
news:ul0i6v8apk90sltas...@4ax.com...


 proprietario del controllo?
Potrebbe subclassare la window procedure del controllo remoto iniettando un'
hook e richiamando SetWindowLong() da remoto, ma ciò significa complicare le
cose oltremodo.
Poichè non si tratterebbe di nulla più dell' intercettare il WM_LBUTTONDOWN
(che è posted, non sent) già lo hook svolge il lavoro egregiamente. Se poi a
lui non interessa "intercettare" la pressione del pulsante può mandare
periodicamente il messaggio BM_GETSTATE
--
- Carlo -

 va bene anche il sapere quando è stato premuto.
Si può premere dalla tua applicazione, devi inviare un messaggio all' handle
del bottone:
PostMessage(hWindow, WM_LBUTTONDOWN, 0, 0);
PostMessage(hWindow, WM_LBUTTONUP, 0, 0);
Oppure usare la mouse_event()
--
- Carlo -