我有一个简单的窗口应用程序,声明了主窗口回调过程:
WNDCLASSEXW wcx;
/* ... */
wcx.lpfnWndProc = MainWndProc;
在WinMain
之后我宣布LRESULT CALLBACK MainWndProc(HWND mainWindow, UINT msg, WPARAM wparam, LPARAM lparam) { /* ... */}
并且一切正常,但我想知道是否可以将此MainWndProc
作为lambda 置于 WinMain中?
答案 0 :(得分:7)
你可以使用lambda,只要它没有捕获,然后它就会隐式转换为函数指针:
#include <iostream>
typedef void (*func)();
static func some_func;
int global;
int main() {
some_func = [](){ std::cout << "Hello\n"; }; // Fine
some_func();
int local;
some_func = [&](){ local = 1; }; // Illegal - No conversion
some_func = [](){ global = 1; }; // Fine
}
问题实际上是你可以在lambda中作为没有捕获的回调有多少。您仍然可以使用“全局变量”,就像使用常规函数作为回调一样。
答案 1 :(得分:4)
您可以使用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。
答案 2 :(得分:2)
使用包装类,您可以使用旧的技术来存储&#34;这个&#34;指针作为HWND上的货物数据。
这种技术的一个限制是你不能处理在WM_CREATE之前到达的任何消息,这是带有创建参数的消息(这些早期消息中只有少数消息,它们是非常奇特)。
#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;
}