Bon, finalement, j'ai trouvé une solution pour mon histoire
de fonction virtuelles dans une fonction statique.
Dans le présent cas, j'utilise GWL_USERDATA, mais bon, j'aurais pas tjrs ça sous la main !!
C'est pas grave, j'ai pigé le mécanisme !
Merci à ceux qui m'ont aidé!
Et voici le code qui posait problème:
#define CWINDOW_CLASSNAME "CWindowClass"// Classe de fenetre CWindow class CWindow
{
public:
HWND hWnd;
int ProcessMsg();
virtual BOOL Create(LPCTSTR lpszWindowName = "", DWORD dwX = CW_USEDEFAULT, DWORD dwY = CW_USEDEFAULT, DWORD dwWidth = CW_USEDEFAULT, DWORD dwHeight = CW_USEDEFAULT, LPCTSTR lpszClassName = CWINDOW_CLASSNAME, DWORD dwExStyle = 0, DWORD dwStyle = (WS_OVERLAPPEDWINDOW | WS_VISIBLE));// Cree la fenetre
CWindow();
virtual ~CWindow(); private:
// il faut définir la fonction comme static pour pouvoir la passer en tant que pointeur
static LRESULT CALLBACK MyWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); // Les hanlers pour chaque evt ds ma classe
virtual void OnKeyDown(int nVirtKey, long lKeyData);
}; // Dérivée de la classe CWindow
class CxDialog : public CWindow
{
public:
CxDialog();
virtual ~CxDialog();
protected:
// Un handler spécial pour cette classe
// Une fonction virtuelle car appelée depuis MyWindowProc
virtual void OnKeyDown(int nVirtKey, long lKeyData);
}; BOOL CWindow::Create(LPCTSTR lpszWindowName, DWORD dwX, DWORD dwY, DWORD dwWidth, DWORD dwHeight, LPCTSTR lpszClassName, DWORD dwExStyle, DWORD dwStyle)
{
WNDCLASSEX winclass;
DWORD resu = 0; // Initialiser la classe de fenetre
ZeroMemory(&winclass, sizeof(winclass));
winclass.cbSize = sizeof(winclass);
winclass.style = 0;
winclass.lpszMenuName = NULL;
winclass.lpszClassName = lpszClassName;
winclass.cbWndExtra = NULL;
winclass.cbClsExtra = NULL;
winclass.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH);
winclass.hInstance = GetModuleHandle(NULL);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
// Ici, on est obligé de passer un pointeur sur une fonction
// statique ( puisque pour obtenir un pointeur, il faut qu'elle soit
// statique ...CQFD)
// Et ce, même si on passe par un variable ( qu'il faudra bien
// initialiser => Idem!)
winclass.lpfnWndProc = (WNDPROC) MyWindowProc; resu = RegisterClassEx(&winclass); // Créer la fenetre
hWnd = CreateWindowEx( dwExStyle, lpszClassName,
lpszWindowName,
dwStyle, dwX, dwY, dwWidth, dwHeight,
NULL, NULL,
GetModuleHandle(NULL),
NULL);
// On enregistre l'instance de classe associée à cette fenetre
// sert ds MyWindowProc
SetWindowLong(hWnd, GWL_USERDATA, (LONG) this); return TRUE;
} LRESULT CALLBACK CWindow:: MyWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{ // La solution trouvée ds le source de VNC d'AT&T
// "This is a static method, so we don't know which instantiation we're
// dealing with. We use Allen Hadden's (ahadden@taratec.com) suggestion
// from a newsgroup to get the pseudo-this."
CWindow *CurrentObject = (CWindow *)GetWindowLong( hwnd, GWL_USERDATA);
if(!CurrentObject)
{return DefWindowProc(hwnd, uMsg,wParam,lParam);}// trop tôt! // Sinon, comment appeller les fonctions virtuelles
// d'une classe depuis une fonction statique ?
// Faut-il tjrs récupérer un pointeur sur l'instance ? switch(uMsg){
case WM_QUIT:
case WM_CLOSE:
PostQuitMessage(0);
return FALSE;
break;
case WM_KEYDOWN:// L'appui sur échap ferme la fenetre
CurrentObject->OnKeyDown((int)wParam, lParam);
return FALSE;
break;
}
// Le reste c'est windows qui s'en charge
return DefWindowProc(hwnd, uMsg,wParam,lParam) ; } int CWindow::ProcessMsg()
{
/*
*Un banale pompe à messages ...
*/
} void CWindow::OnKeyDown(int nVirtKey, long lKeyData)
{switch(nVirtKey){
case VK_ESCAPE:// ds un cas on sort
PostQuitMessage(0);
break;
}
} void CxDialog::OnKeyDown(int nVirtKey, long lKeyData)
{switch(nVirtKey){
case VK_ESCAPE:// ds l'autre on affiche une msgbox
MessageBox(NULL, "CxDialog::OnKeyDown","",0);
break;
}
} Tout ça parce que j'aime pas les MFC !!!