La tecnica generale di permettere un'istanza della finestra per essere rappresentato da un'istanza di classe è quello di fare uso di SetWindowLongPtr e GetWindowLongPtr per associare il puntatore dell'istanza della classe all'handle della finestra. Di seguito è riportato un codice di esempio per iniziare. Potrebbe non essere compilato senza alcune modifiche. È solo pensato per essere un riferimento.
Personalmente, ho smesso di aggiornare le mie classi di finestre alcuni anni fa quando ho scoperto la classe di template CWindow e CWindowImpl di ATL. Si prendono cura di fare tutto questo codice banale per te, così possono concentrarsi solo sulla scrittura di metodi che gestiscono i messaggi della finestra. Vedere il codice di esempio che ho scritto su here.
Spero che questo aiuti.
class CYourWindowClass
{
private:
HWND m_hwnd;
public:
LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE: return OnCreate(wParam, lParam);
case wM_PAINT: return OnPaint(wParam, lParam);
case WM_DESTROY:
{
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, NULL);
m_hwnd = NULL;
return 0;
}
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
CYourWindowClass()
{
m_hwnd = NULL;
}
~CYourWindowClass()
{
ASSERT(m_hwnd == NULL && "You forgot to destroy your window!");
if (m_hwnd)
{
SetWindowLong(m_hwnd, GWLP_USERDATA, 0);
}
}
bool Create(...) // add whatever parameters you want
{
HWND hwnd = CreateWindow("Your Window Class Name", "Your Window title", dwStyle, x, y, width, height, NULL, hMenu, g_hInstance, (LPARAM)this);
if (hwnd == NULL)
return false;
ASSERT(m_hwnd == hwnd);
return true;
}
static LRESULT __stdcall StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CYourWindowClass* pWindow = (CYourWindowClass*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (uMsg == WM_CREATE)
{
pWindow = ((CREATESTRUCT*)lParam)->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (void*)pWindow);
m_hWnd = hwnd;
}
if (pWindow != NULL)
{
return pWindow->WndProc(uMsg, wParam, lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
};
};
Vedere [ Metodo migliore per l'archiviazione di questo puntatore per l'utilizzo in WndProc ] (http://stackoverflow.com/questions/117792/best-method-for-storing-this-pointer-for-use-in-wndproc). –
È per questo motivo che ho sempre desiderato che 'WndProc' avesse un parametro' void * user_data'. Renderebbe più semplice la creazione di un wrapper basato su oggetti. –
@Evan: sì, ma avrebbe anche richiesto a qualcuno * sane * di occuparsi della progettazione dell'API ... L'API Win32 sarebbe stata una bestia molto diversa, se così fosse stato. – jalf