我可以有主窗口过程作为一个lambda在WinMain

can I have main window procedure as a lambda in WinMain?

本文关键字:一个 lambda WinMain 窗口 过程 我可以      更新时间:2023-10-16

我有一个简单的窗口应用程序,声明主窗口回调过程:

WNDCLASSEXW wcx;
/* ... */
wcx.lpfnWndProc = MainWndProc;

WinMain之后,我宣布LRESULT CALLBACK MainWndProc(HWND mainWindow, UINT msg, WPARAM wparam, LPARAM lparam) { /* ... */}和一切都工作正常,但我想知道是否有可能有这个MainWndProc作为lambda 内部 WinMain ?

你可以使用lambda,如果它没有捕获,那么它有一个隐式转换到函数指针:

#include <iostream>
typedef void (*func)();
static func some_func;
int global;
int main() {
  some_func = [](){ std::cout << "Hellon"; }; // Fine
  some_func(); 
  int local;
  some_func = [&](){ local = 1; }; // Illegal - No conversion
  some_func = [](){ global = 1; }; // Fine
}

真正的问题是,在没有捕获的情况下,你能在lambda中做多少有用的回调。您仍然可以使用"全局变量",就像您使用常规函数作为回调函数一样。

您可以使用lambda,但它不能捕获[]中的任何变量,例如:

wc.lpfnWndProc=[](HWND h, UINT m, WPARAM w, LPARAM l)->LRESULT
{
    if (m==WM_CLOSE)
        PostQuitMessage(0);
    else
        return DefWindowProc(h,m,w,l);
    return 0;
};

可在Visual c++ 2012中使用

对于包装类,您可以使用将"this"指针存储为HWND上的货物数据的老技术。

该技术的一个限制是,您不能处理在WM_CREATE之前到达的任何消息,WM_CREATE是携带creation参数的消息(只有少数这些早期消息,而且它们相当奇特)。

#pragma once
// LambdaWindow.h -- Lambda Window utility
#include <windows.h>
#include <tchar.h>
#include <functional>
class LambdaWindow
{
public:
    typedef 
       std::function<LRESULT(HWND h, UINT m, WPARAM w, LPARAM l)> 
       WindowProcFunction;
public:
    LambdaWindow(const WindowProcFunction &pfn) : fn(pfn)  { }
    virtual ~LambdaWindow() { }
    static LRESULT CALLBACK Stub(HWND h, UINT m, WPARAM w, LPARAM l)
    {
        LambdaWindow *pThis = (LambdaWindow *)GetWindowLongPtr(h, GWLP_USERDATA);
        if (pThis)
        {
            return pThis->fn(h, m, w, l);
        }
        else if (m == WM_CREATE)
        {
            pThis = (LambdaWindow *)(((CREATESTRUCT *)l)->lpCreateParams);
            SetWindowLongPtr(h, GWLP_USERDATA, (LONG_PTR)pThis);
            return pThis->fn(h, m, w, l);
        }
        return DefWindowProc(h, m, w, l);
    }
private:
    WindowProcFunction fn;
};

上面实用程序的示例使用:

#include "LambdaWindow.h"
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance, 
                   LPSTR lpCmdLine, 
                   int nCmdShow)
{
    HWND wnd;
    TCHAR testText[] = _T("Some Text");
    RECT textLocation = { 10, 10, 150, 30 };
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = LambdaWindow::Stub;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = L"minwindowsapp";
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    LambdaWindow wlambda =
        [&](HWND h, UINT m, WPARAM w, LPARAM l)->LRESULT
        {
            switch (m)
            {
            case WM_PAINT:
                {
                    PAINTSTRUCT ps;
                    HDC hdc;
                    hdc = BeginPaint(h, &ps);
                    DrawText(hdc, testText, -1,
                        &textLocation, DT_CENTER| DT_VCENTER );
                    EndPaint(h, &ps);
                }
                break;
            case WM_CLOSE:
                PostQuitMessage(0);
                break;
            default:
                return DefWindowProc(h, m, w, l);
            }
            return 0;
        };
    if (RegisterClass(&wc))
    {
        wnd = CreateWindow(wc.lpszClassName,
            L"Minimal Windows Application",
            WS_OVERLAPPEDWINDOW,
            0, 0, 640, 480, NULL, NULL, hInstance, &wlambda);
        if (wnd)
        {
            MSG msg;
            ShowWindow(wnd, nCmdShow);
            UpdateWindow(wnd);
            while (GetMessage(&msg, NULL, 0, 0) > 0)
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
    return 0;
}