2013-01-12 5 views
6

私は宣言し、メインウィンドウのコールバックプロシージャを持つ単純なウィンドウアプリケーションを持っている:私はWinMainでラムダとしてメインウィンドウプロシージャを持つことができますか?

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

WinMain後、私はLRESULT CALLBACK MainWndProc(HWND mainWindow, UINT msg, WPARAM wparam, LPARAM lparam) { /* ... */}、すべてを宣言していないok取り組んでいるが、私は疑問に思うこと、それはラムダ内部としてこのMainWndProcを持つことが可能です WinMain?

答えて

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 
} 

問題は本当にあなたが有効に捕獲せずにコールバックとしてラムダで行うことができますどのくらいです。あなたはコールバックとしての通常の機能と同じように、 "グローバル"に頼ることができます。

+0

は、彼は大丈夫かもしれウィンドウインスタンス/ウィンドウクラスのバイト数。 –

+0

ラムダ内の包含関数からローカル変数にアクセスできない場合、ラムダを使用する理由はまったくありません。だからこそ、地元の人たちを有効にするための仕組みを底に答えを投稿したのです。 –

4

あなたはラムダを使用することができますが、それは例えば、[]内の任意の変数をキャプチャしてはいけません:ラッピングクラスでのVisual C++ 2012

+1

リバイバルには申し訳ありませんが、どうしてキャプチャできないのですか? – rev

+1

何もキャプチャしないラムダだけが関数ポインタとして使用できます。あらゆる種類の状態(キャプチャされた変数)を格納するための関数ポインタの場所はありません。 – Azarien

1

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

作品、あなたはそれを行うことができますHWND上に "this"ポインタを貨物データとして格納する古い技法を使用しています。

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

サンプル使用:彼はWndProcメソッドの入力として取得するパラメータで、彼は余分なようなものを保存するためにそれらを使用する可能性があるため、彼の場合については

#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; 
} 
関連する問題