winapi — ошибка C32 Win32

Я сделал класс для Win32, и я понятия не имею, почему эта ошибка происходит.

Это код:

main.cpp

using namespace std;
#include "WindowManager.h"
#define   WIDTH     700
#define   HEIGHT    500
#define   VERSION   0.1

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreviousInstance,LPSTR lpcmdline,int nCmdShow)
{
WindowManager window("TalkToMe", 100, 100, WIDTH, HEIGHT);

while(window.isWindowOpen())
{
window.PekMessage();
}

return 0;
}

WindowManager.h

#pragma once

#include <Windows.h>

class WindowManager
{
private:
MSG msg;
HWND window;

int stat;
public:
WindowManager(LPCTSTR title,int x, int y, int width, int height);
~WindowManager();
LRESULT CALLBACK WindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2);

inline bool isWindowOpen()   { return stat != -1; }
int  getStat()               { return stat; }
void PekMessage();
};

WindowManager.cpp

#include "WindowManager.h"
void WindowManager::PekMessage()
{
if(PeekMessage(&msg, window, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

LRESULT CALLBACK WindowManager::WindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)
{
switch(uint_Message)
{
case 16: // exit button
stat = -1;
break;
}

return DefWindowProc(winhan,uint_Message,parameter1,parameter2);
}

WindowManager::WindowManager(LPCTSTR title,int x, int y, int width, int height)
{
stat = 0;

WNDCLASSEX wnd;
wnd.cbSize = sizeof(wnd);
wnd.style  = CS_HREDRAW | CS_VREDRAW;
wnd.lpfnWndProc = WindowProcedure;
wnd.cbClsExtra  = 0;
wnd.cbWndExtra  = 0;
wnd.hInstance   = GetModuleHandle(NULL);
wnd.hIcon       = NULL;
wnd.hCursor     = LoadCursor(NULL,IDC_ARROW);
wnd.hbrBackground = GetSysColorBrush(NULL);
wnd.lpszClassName = "TalkToMe";
wnd.lpszMenuName  = NULL;
wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&wnd);

window = CreateWindowEx(WS_EX_CONTROLPARENT, wnd.lpszClassName, title,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, x, y, width, height,NULL, NULL,
GetModuleHandle(NULL), NULL);
}

WindowManager::~WindowManager()
{
DestroyWindow(window);
}

Это странная ошибка сборки:

1>------ Build started: Project: Client, Configuration: Debug Win32 ------
1>  WindowManager.cpp
1>c:\users\user\documents\visual studio 2012\projects\talktome\talktome\windowmanager.cpp(31): error C3867: 'WindowManager::WindowProcedure': function call missing argument list; use '&WindowManager::WindowProcedure' to create a pointer to member
1>c:\users\user\documents\visual studio 2012\projects\talktome\talktome\windowmanager.cpp(31): error C2440: '=' : cannot convert from 'LRESULT (__stdcall WindowManager::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
1>          There is no context in which this conversion is possible
1>  Generating Code...
1> Compiling...
1>  Main.cpp
1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

-7

Решение

Этого следовало ожидать. WindowManager::WindowManager имеет скрытый this аргумент, таким образом, он не уважает определение, требуемое для wnd.lpfnWndProc,

Чтобы обойти эту проблему, вам нужно определить вспомогательную функцию следующим образом:

LRESULT CALLBACK HelperWindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)
{
if (uint_Message == WM_CREATE)
{
/* Retrieve "this" sent through CreateWindowEx */
WindowManager *wm = (WindowManager *)(((LPCREATESTRUCT) lParam)->lpCreateParams);
/* And store it as window-private date */
SetWindowLongPtr(winhan, GWLP_USERDATA, wm);
}

/* Retrieve WindowManager from window-private data */
WindowManager *wm = (WindowManager *)GetWindowLongPtr(winhan, GWLP_USERDATA);
/* Forward window message to WindowManager */
wm->WindowProcedure(winhan, uint_Message, parameter1, parameter2);
}

WindowManager::WindowManager()
{
...
/* use helper window procedure */
wnd.lpfnWndProc = HelperWindowProcedure;
...
/* send "this" through WM_CREATE */
window = CreateWindowEx(WS_EX_CONTROLPARENT, wnd.lpszClassName, title,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, x, y, width, height,NULL, NULL,
GetModuleHandle(NULL), this);

}
4

Другие решения

Как упоминалось в user1202136, методы класса C ++ имеют неявный параметр, который передается в функцию при каждом вызове. Содержит указатель на экземпляр класса (this указатель) и позволяет получить доступ к переменным класса. Чтобы решить эту проблему, вы можете сделать WindowProcedure метод статический и использование GWL_USERDATA в памяти окна для хранения вашего экземпляра класса (this указатель). Уважать GetWindowLongPtr для дополнительной информации. При создании окна вам нужно будет пройти this указатель через lpParam параметр, и сохраните его, используя SetWindowLongPtr когда вы обрабатываете WM_CREATE сообщение.

1

проверить решения:

wnd.lpfnWndProc = (WNDPROC)WindowProcedure;

или же

LRESULT WNDPROC WindowManager::WindowProcedure(HWND winhan,UINT uint_Message,WPARAM parameter1,LPARAM parameter2)
-3