6

メインウィンドウのコールバックプロシージャが宣言された単純なウィンドウアプリケーションがあります。

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

WinMain宣言した後、すべてが正常に機能していますが、これをWinMainのラムダとしてLRESULT CALLBACK MainWndProc(HWND mainWindow, UINT msg, WPARAM wparam, LPARAM lparam) { /* ... */}持つことは可能でしょうか?MainWndProc

4

3 に答える 3

7

ラムダを使用できますが、キャプチャがなく、関数ポインターへの暗黙の変換があります。

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

問題は、実際には、キャプチャなしのコールバックとしてラムダでどれだけ便利にできるかということです。コールバックとして通常の関数を使用する場合と同じように、引き続き「グローバル」に頼ることができます。

于 2013-01-12T11:29:15.240 に答える
4

ラムダを使用できますが、[]内の変数をキャプチャしてはなりません。次に例を示します。

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で動作します。

于 2013-05-28T20:22:25.263 に答える
3

ラッピングクラスでは、「this」ポインタを貨物データとしてHWNDに格納するという古い手法を使用してそれを行うことができます。

この手法の制限の1つは、作成パラメーターを運ぶメッセージである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;
}
于 2017-02-02T01:43:24.007 に答える