Если вы хотите, чтобы WindowProc обрабатывался классом, вы делаете что-то вроде
class CWindow
{
static LRESULT WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
CWindow* self;
if(uMsg == WM_CREATE)
{
self = (CWindow*)((LPCREATESTRUCT)lParam)->lplpCreateParams;
}
else
self = GetWindowLong(hwnd,GWL_USERDATA);
if(self){
switch(uMsg){
case WM_CREATE:
return self->OnCreate(hwnd,(LPCREATESTRUCT)lParam);
case WM_CLOSE:
self->OnClose();
return 0;
// etc.
}
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
int OnCreate(HWND hwnd,LPCREATESTRUCT lpcs)
{
m_hwnd = hwnd;
SetWindowLong(m_hwnd,GWL_USERDATA,this);
return 0;
}
}
Обязательно передайте 'this' в качестве последнего параметра в CreateWindow (Ex).
Далее, в вашем цикле сообщений вы ДОЛЖНЫ проверять наличие сообщений WM_QUIT и использовать его как сигнал для выхода из цикла. Кроме того, НИКОГДА не делайте фильтр на hwnd, так как это предотвратит цикл вашего приложения от отправки сообщений для других окон в вашем потоке. И многие библиотеки окон создают окна сообщений в потоках, чтобы облегчить обмен данными между процессами (и потоками). Если вы не обрабатываете все сообщения Windows, то (а) вашей игре в конечном итоге не хватит памяти, и (б) вся система может начать работать смешно, поскольку ваше приложение сделает сообщения IPC тупиковыми или заблокированными.
Кроме того, WM_CLOSE (обычно) отправляется через SendMessage, а не PostMessage. Отправленные сообщения доставляются прямо в процесс окна и не могут быть отфильтрованы в цикле приложения.