PDA

Visualizza la versione completa : [C] Subclassing HWND di altri thread


daniele_dll
12-05-2007, 22:55
Hola,

sto passando un po di tempo, anche se mi rendo conto che l'orario non è proprio il più adatto, e nemmeno il giorno :asd:, e stavo scrivendo un piccolo tool per subclassarmi la TrayClock (ergo dove ci sta l'orologio) per disegnarci qualcosa di carino

Dopo aver sviluppato tutto il codice necessario per subclassare l'hwnd, ergo il codice per la ricerca e l'acquisizione del nome della classe, provo ad avviare il programma e mi va in crash con l'errore accesso negato!

Mi vado a rileggere la pagina relativa a SetWindowLong e noto la nota (scusate il gioco di parole) , che posso fare? Per subclassare la TrayClock devo perforza iniettare del codice eseguibile dentro explorer? Non ci sono sistemi meno drastici?

oregon
12-05-2007, 23:02
Scusa, ma tu vuoi aggiungere una icona alla tray area?

daniele_dll
12-05-2007, 23:11
nono, voglio ridisegnare il boxino dell'orologio

:)

---

per ridisegnare intendo che voglio intercettare il WM_PAINT e ridisegnarlo, perché fino a prendere il dc ci arrivo, il problema e come intercettare i messaggi dato che viene eseguito in un altro thread :\

oregon
12-05-2007, 23:35
Ok ... devi seguire un'altra strada. Utilizza l'API

SetWindowsHookEx
http://msdn2.microsoft.com/en-us/library/ms644990.aspx

con l'idHook WH_GETMESSAGE e la funzione

GetMsgProc
http://msdn2.microsoft.com/en-us/library/ms644981.aspx

oppure con l'idHook WH_CALLWNDPROC e la funzione

CallWndProc
http://msdn2.microsoft.com/en-us/library/ms644975.aspx

Ovviamente il codice non e' semplicissimo ma abbastanza utilizzato e ci sono tantissimi esempi in giro ...

daniele_dll
12-05-2007, 23:56
quello è purtroppo un po difficile :\

E' vero che ho indicato il linguaggio C, perché a me sta senza problemi anche quello, ma il codice che attualmente sto scrivendo, per tagliare i tempi, è in C#, codice che se va dopo converto, quindi non ho codice da postare

Ho scritto al volo il seguente codice che "dovrebbe" funzionare a livello di logica, però al 99.99% ci saranno degli errori, probabilmente cretini, nel codice

Le varie API fanno uso della User32.dll



include <stdio.h>
include <stdlib.h>
include <string.h>
include <user32.h>

DWORD trayClockHWND;
WNDPROC oldWndProc;

int main()
{
// Acquisisce l'HWND
trayClockHWND = 0;
EnumWindows(EnumWindowsProcCallback, null);

// Verifica che l'operazione sia riuscita
if (trayClockHWND == 0)
{
printf("Acquisizione fallita!"\r\n");
getchar();
return -1;
}

printf("Acquisizione Riuscita\r\n");

// Subclassa la tray clock
WNDPROC oldWndProc = (WNDPROC)SetWindowLong(
trayClockHWND,
GWL_WNDPROC,
(LONG)newWndProc);

printf("Subclassing Riuscito\r\n");

// Ripristina il vecchio gestore
SetWindowLong(
trayClockHWND,
GWL_WNDPROC,
(LONG)oldWndProc);

printf("Subclassing Rimosso\r\n");

// Esce dal programma
return 0;
}

LRESULT newWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
}

BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
{
// Verifica se è già settato il valore che si sta cercando
if (trayClockHWND > 0)
{
return 0;
}

// Inizializza il valore di ritorno per il nome della classe
char* className = mallock(256);
memset(className, 0, 256);

// Acquisisce il nome della classe
GetClassName(hwnd, className, 255);

// Esegue il confronto
if (strcmp(className, "TrayClockWClass") == 0)
{
// Acquisisce l'HWND
trayClockHWND = hwnd;

// Libera la memoria
free(className);

// Blocca l'enumerazione
return FALSE;
}

// Libera la memoria
free(className);

// Procede con l'enumerazione delle finestre figlio
EnumChildWindows(EnumWindowsProcCallback, null);

// Fa proseguire l'enumerazione
return TRUE;
}

daniele_dll
12-05-2007, 23:57
Originariamente inviato da oregon
Ok ... devi seguire un'altra strada. Utilizza l'API

SetWindowsHookEx
http://msdn2.microsoft.com/en-us/library/ms644990.aspx

con l'idHook WH_GETMESSAGE e la funzione

GetMsgProc
http://msdn2.microsoft.com/en-us/library/ms644981.aspx

oppure con l'idHook WH_CALLWNDPROC e la funzione

CallWndProc
http://msdn2.microsoft.com/en-us/library/ms644975.aspx

Ovviamente il codice non e' semplicissimo ma abbastanza utilizzato e ci sono tantissimi esempi in giro ...

asd, grazie, mi ero decisamente bloccato :)

daniele_dll
13-05-2007, 00:40
purtroppo SetWindowHookEx non mi permette di definire un HWND e quindi non posso intercettare direttamente i messaggi del TrayClock, ergo di dove windows disegna l'orario

Comunque mi sa che, giustamente per motivi di sicurezza, windows non permette in alcun modo di modificare la catena dei gestori dei messaggi degli altri applicativi quindi l'unico metodo che mi rimane è iniettare una dll nel processo che gestisce quel dato HWND e quindi farci quello che devo farci

grazie comunque (ovviamente se hai/avete in mente altre soluzioni sono molto ben accette :D)

oregon
13-05-2007, 01:18
No ... non e' così.

Con la SetWindowHookEx ti inserisci nella catena dei messaggi e, una volta che sei a conoscenza dell' hwnd, lo confronti con quello che ti viene passato per agire prima che i messaggi arrivino.

daniele_dll
13-05-2007, 02:24
aaaaaaaahhhh

allora devo impostare un hook globale, giusto? devo mettere a zero il threadid e fare una libreria con dentro il codice che mi serve?

scusami, sono un idioma, sto dormendo in piedi e, anche avendolo letto, non l'avevo collegato al fatto che a me serviva esattamente quello :stordita:

oregon
13-05-2007, 10:08
Originariamente inviato da daniele_dll
aaaaaaaahhhh

allora devo impostare un hook globale, giusto? devo mettere a zero il threadid e fare una libreria con dentro il codice che mi serve?

Sì ... deve essere un hook globale, per superare il problema dei thread ...

Loading