Class-classing ?

cs_Clem Messages postés 282 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 12 février 2007 - 18 août 2005 à 11:59
cs_Clem Messages postés 282 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 12 février 2007 - 18 août 2005 à 12:52
Bonjour,

je développe actuellement un petit programme en C (raisons personnelles
pour ce
choix), et j’ai besoin de rajouter une option sur la contrôle de base
"static", j'ai tout de suite pensé au sub-classing, mais il ne pointe
que vers un seul contrôle à la fois, j'ai donc recherché sur
RegisterClassEx/UnregisterClass/GetClassInfoEx pour modifier la classe
elle même, et pointer vers ma fonction, jusque la pas de problèmes,
seulement comme je n'ai pas envie de recoder tout le static pour une
petite fonctionnalité en plus, je pensais que dans ma fonction je
pourrais faire mon code, et puis apeller la vraie fonction si la
commande ne correspond pas a ma fonctionnalité rajoutée. Bon un code
vaut mieux qu'un long discours, même s'il n'est pas commenté il est
d'une simplicité enfantine :



enhanced_ctrls.c



#include "enhanced_ctrls.h"




ENHANCEDCTRL EnhancedCtrls[];




LRESULT CALLBACK EnhancedStatic_WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {


//WM_NCCREATE (129) first, and last WM_NCDESTROY (130)


int i;


for (i=0; EnhancedCtrls[i].NewWndProc==EnhancedStatic_WndProc; i++) break;


//EnhancedCtrls[i].OldWndProc(hWnd,
Msg, wParam, lParam); //ça m'aurait étonné, mais j'ai quand même
essayer...la WndProc des static serait elle virtuelle ?


return CallWindowProc(EnhancedCtrls[i].OldWndProc, hWnd, Msg, wParam, lParam);


//return DefWindowProc(hWnd, Msg, wParam, lParam);


}




ENHANCEDCTRL EnhancedCtrls[]={


{EnhancedStatic_WndProc, NULL, "static", "static"},


{NULL, NULL, NULL, NULL}


};




BOOL InitEnhancedCtrls() {


WNDCLASSEX WndClassEx1, WndClassEx2;


HINSTANCE hInstance=GetModuleHandle(0);




memset(&WndClassEx2, '\0', sizeof(WndClassEx2));


WndClassEx2.cbSize=sizeof(WndClassEx2);


WndClassEx2.style=CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;


WndClassEx2.hInstance=hInstance;


WndClassEx2.hbrBackground=(HBRUSH)(COLOR_BTNFACE+1);




int i;


for (i=0; EnhancedCtrls[i].NewWndProc; i++) {


GetClassInfoEx(hInstance, EnhancedCtrls[i].OldName, &WndClassEx1);


EnhancedCtrls[i].OldWndProc=WndClassEx1.lpfnWndProc;




WndClassEx2.lpszClassName=EnhancedCtrls[i].NewName;


WndClassEx2.lpfnWndProc=EnhancedCtrls[i].NewWndProc;




if (!UnregisterClass(EnhancedCtrls[i].OldName, hInstance)) return FALSE;


if (!RegisterClassEx(&WndClassEx2)) return FALSE;


}


}








enhanced_ctrls.h



#include "windows.h"


typedef struct {

WNDPROC NewWndProc; //la WndProc qui remplacera

WNDPROC OldWndProc; //la WndProc ancienne, appelée depuis la nouvelle eventuellement

char * OldName; //l'ancien nom de la classe

char * NewName; //le nouveau nom, le nom ne semble
pas poser de problèmes l'erreur renvoyée par RegistrerClassEx

} ENHANCEDCTRL;



BOOL InitEnhancedCtrls();








comme vous vous en doutez, si je poste ici c'est que mon idée ne marche pas...

le problème est que CallWindowProc ne semble pas apeller malgré tout
l'ancienne WndProc, vu que ma nouvelle fonction reçoit un message
"WM_NCCREATE", puis juste après "WM_NCDESTROY".

Un coup de débuger m'a permis de savoir que l'adresse de la fonction
était...01460582h, impossible de débuger plus loin (kernel et donc
protégé ? j'en sais trop rien je n'ai pas l'habitude de travailler en
adresses sous windows au dela de mon code source...) mais dans ce cas,
pourquoi CallWindowProc ne fait (presque) rien ?

voilà c'était ma question du moment, si quelqu'un a la réponse, il serait gentil de venir la poster ici
je préfère être sur avant de devoir me mettre au travail de recoder
entièrement le fonctionnement d'un static... merci d'avance^^

2 réponses

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
18 août 2005 à 12:21
pourquoi boucle et structure ?

oldProc = SetWindowLong(....)
"oldProc =" 1 seule fois et seulement SetWindowLong(...., newProc) pour les autres, chaque STATIC a la même windProc.

Tu peux différencier si besoin chaque static par son ID par GetWindowLong() avec GWL_ID dans la newProc.

ciao...
BruNews, MVP VC++
0
cs_Clem Messages postés 282 Date d'inscription dimanche 1 avril 2001 Statut Membre Dernière intervention 12 février 2007
18 août 2005 à 12:52
merci de répondre, mais ça aurait été trop simple :(



tout d'abord, la structure et la boucle c'est parce que plus tard je
risque d'avoir plusieurs contrôles de base à modifier, donc je n'aurais
qu'a rajouter ça dans la liste de struct, sans avoir à copier coller
10x tout le bordel pour intercepter.



SetWindowLong oui ça aurait été possible mais comme je l'ai dis le
sub-classing je préfère taper 200 lignes de codes pour refaire un
static à ma version, plutôt que de l'utiliser. en fait je voudrait que
l'interception ce fasse de manière transparente, le subclassing
implique un SetWindowLong à chaque static créé, ce qui complique tout
d'abord parce que certaines de mes fenêtres seront dans une dll externe
au programme, donc il va falloir rajouter un paramètre a la dll
contenant l'adresse de la nouvelle WndProc, et ensuite il se retrouve
surtout que chez les static, il arrive souvent qu'elles aient l'id
IDC_STATIC (-1), et je vois donc mal comment je pourrait récupérer
l'handle de la static sachant que la fenêtre mère aura été créé en
DialogBox par ressources...



la seule solution que j'envisage et donc soit de créér de nouveaux
contrôles faits maisons, soit de réussir à intercepter les messages des
contrôles de la class, pas d'un seul contrôle à la fois...oui je sais
je suis compliqué^^



@++

Clém
0
Rejoignez-nous