2015-01-28 2 views
1

Когда вы, например, создать окно на экране в окнах, вы создаете функцию обратного вызова для приема сообщения из оконМожет ли функция windows proc/callback быть функцией-членом класса?

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 

Вы можете сделать эту функцию функции члена класса? Если да, то как мне это сделать? Причина, по которой я хотел бы, чтобы функция обратного вызова была членом класса, должна иметь доступ к определенным переменным, но при этом все переменные инкапсулируются. Например, когда я сохраняю ширину и высоту окна, поэтому, если они когда-либо будут заменены, я могу напрямую их изменить в функции обратного вызова.

Если нет, есть ли у вас какие-либо предложения относительно того, как я буду решать эту проблему, предоставляя функцию обратного вызова доступным к инкапсулированным переменным?

+2

Это может быть статическая функция-член, а не то, что она помогает. Существует множество разных трюков для связывания экземпляра класса с дескриптором «HWND» - см., Например, ['SetProp'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633568.aspx) или' SetWindowLongPtr' –

+0

Элементы-члены 'static' могут использоваться как функции обратного вызова без особых усилий , Создание функции 'non-static' member как функции обратного вызова требует создания функций-оболочек. –

+0

hmm okay. Ну, в основном, он получает доступ к ширине и высоте, после чего, без необходимости делать некоторые уродливые работы с использованием глобальных переменных. Я хочу создать компактный и инкапсулированный класс окон –

ответ

3

Как и в комментариях к комбинату, подходит как static member и SetWindowLongPtr.

Вот пример декларации класса, который определяет статическую WindowProc как функцию-член.

class MyClass 
{ 
public: 
    void MainThreadProc(); 

private: 
    static LRESULT CALLBACK WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 
    LRESULT _WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 
}; 

Метод MainThreadProc создаст окно. Обязательно перейдите в this в CreateWindowEx, так как вы получите доступ к своим ученикам.

void MyClass::MainThreadProc() 
{ 
    MSG msg;  
    HINSTANCE hinstance = GetModuleHandle (NULL);  
    WNDCLASSEX wcx = {0}; 
    HWND hwnd = NULL; 

    wcx.cbSize = sizeof wcx; 
    wcx.hInstance = hinstance; 
    wcx.hCursor = LoadCursor (NULL, IDC_NO); 
    wcx.style = CS_HREDRAW | CS_VREDRAW; 
    wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); 
    wcx.hIcon = LoadIcon (NULL, IDI_APPLICATION); 
    wcx.lpfnWndProc = WindowProc; 
    wcx.lpszClassName = L"MyWindowClass"; 

    RegisterClassEx (&wcx); 

    hwnd = CreateWindowEx (WS_EX_APPWINDOW, 
          L"MyWindowClass", 
          L"MyWindow", 
          WS_OVERLAPPEDWINDOW, 
          CW_USEDEFAULT, 
          CW_USEDEFAULT, 
          CW_USEDEFAULT, 
          CW_USEDEFAULT, 
          NULL, 
          NULL, 
          hinstance, 
          this); 

    ShowWindow (hwnd, SW_SHOWDEFAULT);  

    while (GetMessage(&msg, NULL, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

В WindowProc вы храните this объект, используя SetWindowLongPtr для будущего использования.

LRESULT MyClass::WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    if (WM_NCCREATE == uMsg) 
    { 
     SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) ((CREATESTRUCT*) lParam)->lpCreateParams); 
     return TRUE; 
    } 

    return ((MyClass*) GetWindowLongPtr (hwnd, GWLP_USERDATA))->_WindowProc (hwnd, uMsg, wParam, lParam); 
} 

И для полноты, вот последняя функция члена для обработки оконных сообщений, и вы будете иметь доступ ко всем членам класса в этой точке.

LRESULT MyClass::_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (uMsg) 
    { 
    case WM_DESTROY: 
     PostQuitMessage (S_OK); 
     break; 
    default: 
     return DefWindowProc (hwnd, uMsg, wParam, lParam); 
    } 

    return 0; 
} 
+0

Это также работает для обратного вызова DialogBox? – Matthias

+0

Он работает с DialogBoxParam вместо DialogBox (см. Https://www.gamedev.net/forums/topic/691392-windows-callbacks-as-class-members/?tab=comments#comment-5352706) – Matthias

Смежные вопросы