WNDPROC处理事件更少的代码



我想知道我是否有一种方法可以缩短此代码。我检查是否已经设置了功能,如果有的话,我会打电话给它这只是我的wndproc的一方面,它更大

LRESULT Base::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    {
        switch (uMsg)
        {
        case WM_CREATE:
        {
            if (this->onCreate != NULL)
            {
                if (onCreate(hwnd, (LPCREATESTRUCT)lParam))
                    return 1;
            }
        }break;
        case WM_DESTROY:
        {
            if (onDestroy != NULL)
            {
                if (onDestroy(hwnd))
                    return 1;
            }
            this->Destroy();
        }break;
        case WM_SIZE:
        {
            if (onSize != NULL)
            {
                if (onSize(hwnd, wParam, lParam))
                    return 1;
            }
        }break;
        case WM_CLOSE:
        {
            if (onClose != NULL)
            {
                if (onClose(hwnd))
                    return 1;
            }
        }break;
        default:
        {
        }break;
        }
        return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

像这样定义的指针

LRESULT(*onCreate) (HWND, LPCREATESTRUCT);

我然后像这样添加它们

LRESULT onCreate(HWND, LPCREATESTRUCT)
{
    return true;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pCmdLine, int nCmdShow)
{
    Window mainWindow;
    mainWindow.onCreate = onCreate;
    return 0;
}

使用<WindowsX.h>中定义的消息 - 裂缝宏。这实际上不会使代码运行更快,并且并不会真正导致代码行的净损失,但是它肯定会使代码易于阅读,这是重要的部分。没有人愿意查看1000行开关语句。另外,这些宏从WPARAM和LPARAM提取每条消息的参数,增强可读性,减少错误并简化您必须记住的内容。

宏非常简单,除了高科技外(它们在16位Windows日期都起源):

#define HANDLE_MSG(hwnd, message, fn)    
    case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

,但它们是针对所有最常见消息的预定义(您可以为他们省略的两到三条消息添加,如果您发现您需要它们),因此您不必处理丑陋。您只会得到不错的,可读的代码:

#include <Windows.h>
#include <WindowsX.h>  // for the message cracker macros
...
void Base::OnClose(HWND hWnd)
{
   // ...
}
BOOL Base::OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
    // ...
   
   return TRUE;
}
void Base::OnDestroy(HWND hWnd)
{
    // ...
}
void Base::OnSize(HWND hWnd, UINT state, int cx, int cy)
{
    // ...
}
LRESULT Base::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   switch(uMsg)
   {
      HANDLE_MSG(hWnd, WM_CLOSE,   OnClose);
      HANDLE_MSG(hWnd, WM_CREATE,  OnCreate);
      HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy);
      HANDLE_MSG(hWnd, WM_SIZE,    OnSize);
      // TODO: Add more message crackers here to handle additional messages.
      
      default:
         return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}

标头文件还包含注释,显示了处理程序功能的签名。但是,请查看HernánDiPietro的信息Cracker向导,以使您的生活更加轻松。它列出了所有消息,允许您将它们过滤到所需的消息,并将自动将模板代码复制到剪贴板!

为了避免基类中所有可能的特定(虚拟)消息处理程序的定义,您可以拥有一个处理程序的地图:

#include <unordered_map>
// Mokup windows.h
typedef intptr_t HWND;
typedef intptr_t LRESULT;
typedef intptr_t WPARAM;
typedef intptr_t LPARAM;
typedef unsigned UINT;
enum {
    WM_CREATE
};
// Base
class WindowBase
{
    public:
    virtual ~WindowBase() {}
    LRESULT WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    {
        // The complexity of finding an element in an unordered map 
        // is amortized O(1).
        auto kv = window_procedures.find(uMsg);
        if(kv != window_procedures.end()) {
            auto procedure = kv->second;
            return (this->*procedure)(hwnd, uMsg, wParam, lParam);
        }
        return 0; //::DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    protected:
    typedef LRESULT (WindowBase::*window_procedure)(HWND, UINT msg, WPARAM, LPARAM);
    template <typename Procedure>
    void register_window_procedure(UINT msg, Procedure procedure) {
        window_procedures[msg] =  static_cast<window_procedure>(procedure);
    }
    private:
    std::unordered_map<UINT, window_procedure> window_procedures;
};
// Test
#include <iostream>
class Window : public WindowBase
{
    public:
    Window() {
        register_window_procedure(WM_CREATE, &Window::onCreate);
    }
    protected:
    LRESULT onCreate(HWND, UINT msg, WPARAM, LPARAM) {
        std::cout << "onCreaten";
        return 0;
    }
};
int main() {
    Window w;
    WindowBase* p = &w;
    p->WindowProc(0, WM_CREATE, 0, 0);
}

注意:这不是使用独立消息处理程序遵循您的示例。如果需要,可以typedef LRESULT (*window_procedure)(HWND, UINT msg, WPARAM, LPARAM);并相应地调整代码。但是,函数签名应包括一个额外的参数(例如:windowbase*),以保留上下文(除了hwnd之外),其中调用了该消息。

最新更新