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