Can I have the main window procedure as a lambda in WinMain?

I have a simple window application with the declared main window callback procedure:

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

and after WinMain I declared LRESULT CALLBACK MainWndProc(HWND mainWindow, UINT msg, WPARAM wparam, LPARAM lparam) { /* ... */} , and everything works fine, but I wonder if it is possible for this MainWndProc be a lambda inside WinMain ?

+6
source share
3 answers

You can use lambda if it has no captures, then it has an implicit conversion to function pointer:

 #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 } 

The problem is how much you can usefully make a lambda as a callback without capturing. You can still resort to "global variables", just like with a regular function as a callback.

+7
source

You can use lambda, but it should not capture any variable in [], for example:

 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; }; 

works in Visual C ++ 2012.

+4
source

With the packaging class, you can do this using the old technique of storing the "this" pointer as cargo data on the HWND.

One of the limitations of this method is that you cannot process any messages that arrive before WM_CREATE, this is a message that contains a creation parameter (there are only a few of these early messages, and they are quite exotic).

 #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; }; 

An example of using the utility above:

 #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; } 
+1
source

All Articles