Newsgroup: it.comp.programmare.win32
Titolo: Recuperare l'handle di un'altra finestra

ciao a tutti, sono nuovo del NG, e un newbie di programmazione in
windows.
Vorrei realizzare con VC++5.0 un programma che faccia quanto segue:
Leggere la porta joystick, da cui estrarre i valori dei 4 cursori
(fatto)
inviare i valori convertiti ai controlli TrackBar di un altro
programma in esecuzione (fatto)
quello che non so fare e' determinare per ogni esecuzione del mio
programma il valore di hWnd dei controlli TrackBar dell'altro
programma da dare alle SendMessage. Attualmente uso Spy++ per farmi
dire il valore, e poi lo inserisco manualmente.
Quello che vi chiedo e' come funziona Spy++?
Come posso fare la stessa cosa nel mio programma, cioe' determinare
l'handle del controllo semplicemente cliccandoci sopra con il mouse?
In sostanza voglio realizzare un programma che, mentre e' in
esecuzione un altro programma, non scritto da me, che e' una
sottospecie di mixer audio, mi legga il valore dei cursori del
joystick e mi comandi di pari passo i cursori di quel mixer.
grazie dell'aiuto
ciao
donCiccio

 l'handle del controllo semplicemente cliccandoci sopra con il mouse?
Beh, per ottenere l'handle del controllo sul quale è posizionato il mouse
puoi utilizzare WindowFromPoint(), attento ai remarks della funzione.
Per catturare tale valore nel "system onclick" avresti bisogno di uno hook
system-wide.
Le funzioni che ti permettono di risalire ai vari hwnd di finestre etc. sono
diverse, principalmente guarda
FindWindow(Ex),
EnumWindows (e affini)
Get(xxx)Window
--
- Carlo -
c.b...@libero.it

 puoi utilizzare WindowFromPoint(), attento ai remarks della
funzione.
ho usato WindowsFromPoint unito a SetCapture e ReleaseCapture, ed ha
funzionato egregiamente, grazie!
un'altra domanda:
ottenuto l'handle di quello che sta sotto il mouse, come posso fare a
capire che sia effettivamente un TrackBar?
il mio programma una volta recuperato l'handle non fa altro che
inviare messaggi TBM_SETPOS.
ciao
donCiccio

 capire che sia effettivamente un TrackBar?
puoi usare GetClassName()
Faber


fatto!
ancora un aiutino....
come ho scritto nei post precedenti, ho usato SetCapture e ReleaseCapture
per farmi arrivare i messaggi del mouse anche quando e' fuori della mia
finestra, ma purtroppo non vale per il messaggio WM_MOUSEMOVE, perche'?
con LBUTTONxxx e RBUTTONxxx tutto bene, ma il MOUSEMOVE se il mouse e' fuori
dalla mia finestra non mi arriva!!
come posso fare?
in pratica io vorrei cambiare il puntatore del mouse quando sono sul tipo di
controllo giusto (cioe' trackbar) prima che l'utente clicchi.
ciao
donCiccio

 controllo giusto (cioe' trackbar) prima che l'utente clicchi.
Temo che the only way sia quella detta sopra.


Magari mi sbaglio ma secondo me non gli arriva un MOUSEMOVE semplicemente
perchè quando sei fuori dalla finestra arrivano dei NCMOUSEMOVE (non client
area)
Bye
Johnny

 ha scritto nel messaggio
news:Drj47.12426$m06.4...@news.infostrada.it...

accidenti, mi ero gia' illuso ma...:
"The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved
within the nonclient area of the window. This message is posted to the
window that contains the cursor. If a window has captured the mouse, this
message is not posted."
anche perche' il suggerimento di Bertuccini, non riesco a realizzarlo.
grazie lo stesso!
ciao
donCiccio

 anche perche' il suggerimento di Bertuccini, non riesco a realizzarlo.
Effettivamente il primo impatto con gli hooks può essere piuttosto duro, ma
una volta che capisci come funzionano il gioco è fatto.
Tutti gli hooks hanno una funzione di callback, ovvero una funzione che è
presente nel tuo codice ma che viene richiamata dal sistema operativo ogni
volta che si verifica un evento relativo al tipo di hook installato. Ad
esempio se hai installato un Mouse hook questa funzione verrà richiamata al
verificarsi di un qualsiasi evento relativo al mouse.
Il prototipo è il seguente:
LRESULT CALLBACK HookProc(
    int nCode,
    WPARAM wParam,
    LPARAM lParam)
Questa funzione deve essere situata in una DLL per poter intercettare eventi
relativi ad altre applicazioni come nel tuo caso.
Per poter caricare lo hook in memoria si usa SetWindowsHookEx() il cui
prototipo è:
HHOOK SetWindowsHookEx(
    int idHook, // type of hook to install
    HOOKPROC lpfn, // address of hook procedure
    HINSTANCE hMod, // handle of application instance
    DWORD dwThreadId  // identity of thread to install hook for
   );
Il primo parametro indica il tipo di hook da installare (WH_MOUSE), il
secondo è il puntatore alla callback che dicevamo prima. C'è poi l'hInstance
della DLL, ovvero un valore che identifica univocamente la DLL. Infine c'è
un parametro che ti permette di scegliere dove installare lo hook. Se
imposti 0 lo hook verrà installato in tutte le applicazioni (system-wide)
altrimenti se vuoi intercettare eventi relativi ad un solo thread imposta il
thread identifier del thread interessato. Il valore di ritorno è un HHOOK
(analogo ad hwnd) che devi dare in pasto alla UnHookWindowsHookEx() per
scaricare lo hook dalla memoria. Purtroppo non dispongo di esempi pronti di
hook per Visual C++, spero che qualche anima pia del ng voglia postare due
linee di codice a corredo di questa mia documentazione.
Se nessuno dovesse farlo posterò del codice in object pascal (Delphi) che è
il linguaggio che utilizzo.
Saluti!


 una volta che capisci come funzionano il gioco č fatto.
bhe, sai, io sono un principiante in fatto di programmazione in windows, e
ho esperienza solo di mini programmi SDI, che visualizzano una serie di dati
in stile finestra DOS (o editor se vogliamo fargli un complimento :-).
Detto questo il primo scoglio e':
come si crea una DLL?
come si usano le funzioni in essa contenute?
come puo' una funzione di una DLL modificare i dati del mio programma?
(immagino passandogleli per indirizzo)
Sempre leggendo i tuoi consigli ho provato ad usare la FindWindowEx, ma
purtroppo il programma di cui vorrei pilotare la TrackBar possiede piu'
controlli della stessa classe e non so come identificare quello che mi
serve.
ti ringrazio ancora per l'aiuto, ma tieni presente che quello che vorrei
fare non e' una cosa molto importante, anche se non ci riesco non fa nulla.
ciao
donCiccio

 anche perche' il suggerimento di Bertuccini, non riesco a realizzarlo.
non ho capito se il mio suggerimento ti è servito o meno ?
Bye
Johnny

 il linguaggio che utilizzo.
la teoria mi è chiarissima, però un esempio in Delphi sarebbe molto
gradito  :)
tia
Faber

 non ho capito se il mio suggerimento ti è servito o meno ?
no perche' i NonClient si riferiscono comunque alla mia finestra (titolo,
bordi, status, menu', etc), io vorrei ricevere i messaggi quando il mouse e'
su un'altra finestra, che non appartiene al mio programma.
In pratica con il mouse aldifuori della mia window non mi arriva nemmeno
NCMOUSEMOVE.
A te risulta il contrario?
ciao
donCiccio

 gradito  :)
Eccotelo! :-)
library Hooklib;
 uses  Windows,  Dialogs;
Var HookHandle: hHook;
{ Questa è la HookProc() }
Function KeyboardHook(Codice: Integer; Tasto: Wparam, Stato: LParam):
Integer; stdcall;
Begin
  if (codice = HC_ACTION) and (Tasto = VK_F1) then
      ShowMessage('Tasto F1 premuto!');
  Result := CallNextHookEx(HookHandle,Codice,Tasto,Stato);
end;
Function KeyboardHook(Codice: Integer; Tasto: Wparam, Stato: LParam):
Integer; stdcall;
Begin
  if (codice = HC_ACTION) and (Tasto = VK_F1) then
      ShowMessage('Tasto F1 premuto!');
  Result := CallNextHookEx(HookHandle,Codice,Tasto,Stato);
end;
Procedure CaricaHook; stdcall;
Begin
   HookHandle := SetWindowsHookEx(WH_KEYBOARD,@KeyboardHook,hInstance,0);
end;
Procedure RimuoviHook; stdcall;
Begin
   UnHookWindowsHookEx(HookHandle);
end;
Exports  CaricaHook,RimuoviHook;
end.
Questa è la DLL ... ora crea un EXE che richiami (staticamente o
dinamicamente) i metodi CaricaHook/RimuoviHook ed il gioco è fatto!
Ciao!


 fare non e' una cosa molto importante, anche se non ci riesco non fa
nulla.
Se il "se non ci riesco non fa nulla" è sinonimo di "mi arrendo" non è ben
accetto! :-)


 A te risulta il contrario?
hai ragione.... ero stato ingannato dal fatto che io avevo lavorato su una
applicazione un po' particolare e l'invio dei messaggi lo determinavo io....
il NCMOUSEMOVE non viene mandato se ti muovi sulla finestra attiva (nemmeno
se ti muovi nella sua non client area) e non viene mandato quando sei sul
desktop.... viene inviato solo quando sei nella non client area delle
finestre INATTIVE
bye
Johnny

 Eccotelo! :-)
[cut]
grazie mille, funziona alla grande  :)
Faber


un tentativo l'ho fatto, ma....
Seguendo anche l'esempio che hai scritto a Faber, sempre in questo thread,
ho creato una DLL con 3 funzioni:
MouseHook          -> privata
SetMouseHook       -> export
ReleaseMouseHook   -> export
La SetMouseHook richiama la SetWindowsHookEx che installa la mia funzione di
hook MouseHook. L'handle ritornato da SetWindowsHookEx viene salvato in una
variabile globale della DLL, per la successiva UnhookWindowsHookEx. In una
variabile globale della DLL salvo anche un pointer a char (passato alla
SetMouseHook), che uso poi per scrivere il nome della classe della finestra
su cui e' posizionato il cursore.
Ottengo uno strano comportamento, e cioe' va tutto bene se il cursore e'
sulla mia finestra, mentre se lo sposto su di un'altra, ottengo la
segnalazione "questo programma ha eseguito un'istruzione non valida, etc..."
riferita la programma su cui ho spostato il cursore, mentre il mio programma
continua ad esistere, e se mi sposto ancora, "ammazzo" pure tutte le altre
finestre aperte su cui riesco a mettere il cursore.
Tutto cio' avviene anche se la mia MouseHook richiama solo la
CallNextHookEx.
riesci a darmi qualche dritta con queste informazioni?
ti posto il codice della DLL che e' molto semplice:
-------------
LPSTR ClassName;
HHOOK hhook;
LRESULT CALLBACK MouseHook ( int nCode, WPARAM wParam, LPARAM lParam )
{
  if( nCode==HC_ACTION )
  {
    MOUSEHOOKSTRUCT *mhs=(MOUSEHOOKSTRUCT *)lParam;
    HWND h=::WindowFromPoint( mhs->pt );
    if( h ) ::GetClassName( h,ClassName,80 );
    else strcpy( ClassName,"none" );
  }
  return CallNextHookEx( hhook,nCode,wParam,lParam );
}
__declspec( dllexport ) void SetMouseHook ( LPSTR pClassName )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 // normal function body here
 ClassName = pClassName;
 if( ClassName ) hhook = SetWindowsHookEx(WH_MOUSE,MouseHook,NULL,0);
}
__declspec( dllexport ) void ReleaseMouseHook ( void )
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 // normal function body here
 if( hhook )
 {
  UnhookWindowsHookEx( hhook );
  hhook=0;
 }
}
------------------
ciao
donCiccio