2013-02-02 12 views
6

親ウィンドウにコンソールウィンドウを表示する小さなクラスを作成しようとしています。
異なるインスタントにはメッセージ配列や親ウィンドウなどのさまざまなプライベート変数があるので、Windowsイベントのコールバックとして非静的メソッドを使用する必要があります(この場合、チャットやデバッグ情報は表示されません)。
私は実際のクラスインスタンスを静的コールバック関数に渡してから適切なメソッドを呼び出す方法を考えましたが、winAPIではすべてがTranslateMessageDispatchMessageを使用して実行され、私の引数自分の。
私はここにいくつかのコードを見つけました:Class method as winAPI callbackしかし、私はそれを理解していない、と私はそれが私が必要とするものではないと思う。そうであれば、提供されたコードについてさらに説明してください。
エラー私が手:オブジェクトメソッドをWinApiとして使用するWndProcコールバック

エラー:型の引数を 'LRESULT(WindowConsole::)(HWND__ 、UINT、WPARAM、LPARAM)'「LRESULT(*)(HWND__、UINT、 と一致していませんWPARAM、LPARAM) '

括弧内のその星の意味は分かりませんが、これは一致しません。
とコード:

class WindowConsole { 
    char messages[255][255]; 
    HWND mainWindow; 
    public: 
    int width; 
    int height; 
    inline HWND create(HWND parent); 
    inline bool update(); 
    inline LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); 
}; 

HWND WindowConsole::create(HWND parent) { 
    HINSTANCE inst = GetModuleHandle (0); 
    WNDCLASSEX wincl; 

    /* The Window structure */ 
    wincl.hInstance = inst; 
    wincl.lpszClassName = "ConsoleClass"; 
    wincl.lpfnWndProc = this->WndProc;  /* This function is called by windows */ 
    /* more WNDCLASSEX crap...*/ 

    mainWindow = CreateWindow (
      /*PARAMS*/ 
    ); 
    ShowWindow(mainWindow,1); 
    return mainWindow; 

} 
bool WindowConsole::update() { 
    return true; 
} 
LRESULT CALLBACK WindowConsole::WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { 
    switch (message)     /* handle the messages */ 
    { 
      /*EVENT crap*/ 
    } 

    return 0; 
} 
+0

999999999 dupes – Puppy

+0

まあ、それらのどれも私を助けてくれません。私は長い間、この問題に関する多くのトピックを検索してきましたが、わかりませんでした。 –

+0

user16100 ...の回答とmsdn-articleへのリンクを見てください... – Incubbus

答えて

9

いつもこのために何かです。派生クラスでは、BaseWindow内の(純粋な仮想)ものをオーバーライドする "WindowProc"を提供します。ここでのトリックはかなりシンプルです:パラメータを直接渡すことはできないので、クラスのアドレスをウィンドウのGWLP_USERDATAに格納してから、ウィンドウproc(取得しようとします)を取り出して派生クラスの 'virtualウィンドウプロシージャ

これはスケッチであり、完成した作品ではないことに注意してください。そのままコンパイルする必要がありますが、ここにないかなりの数の部分を記入しないと結果は実際には機能しません(例えば、WNDCLASS構造の他のフィールドは最も明白です)。

+0

ありがとう、あなたの例では、私は何かを作りました、少なくとも、エラーなしでコンパイルします。今、obvionsの質問があります:ウィンドウイベントをキャプチャして送出するためにループをどこに置くのですか? プログラムを非同期にする必要がありますか(別のスレッドを追加しますか?) –

+0

@TomášZato:メッセージループはWinMainに(本質的に)常にあります。通常はWinMainのインスタンスを作成し、メッセージループに入ります。いいえ、通常は別のスレッドで実行する必要はありません。 –

+0

私のクラスでは、多くのインスタンスを作成できるので、多くのウィンドウを作成できます。だから私はウィンドウハンドラ(HWND)をそれぞれのイベントをWinMain()でディスパッチするために、いくつかのグローバル変数に保持する必要がありますか? –

4

あなただけにリンクされている他の質問は、部分的に適用されます。

WindowProcメソッドは静的である必要があります。 GWLP_USERDATAを2番目のパラメータとして、SetWindowLongPtrを呼び出して、の3番目のパラメータとして呼び出します。これは、HWNDをクラスインスタンスに関連付けます。その後、静的なWindowProcメソッドでGetWindowLongPtr(GWLP_USERDATA)を呼び出して、UIイベントを受け取ったWindowConsoleインスタンスを取得します。すべてここでは詳細に説明しています

:あなたはBaseWindowからクラスを派生、これにより

#include <windows.h> 

class BaseWindow { 

    static LRESULT CALLBACK internal_WndProc(HWND hWnd, int msg, WORD wParam, LONG lParam) { 
     BaseWindow *c = (BaseWindow *)GetWindowLong(hWnd,GWLP_USERDATA); 

     if (c == NULL) 
      return DefWindowProc(hWnd, msg, wParam, lParam); 

     return c->WindowProc(hWnd, msg, wParam, lParam); 
    } 

public: 
    virtual int WindowProc(HWND hWnd, int msg, WPARAM wParam, LPARAM lParam) = 0; 

    BaseWindow(HINSTANCE instance) { 
     WNDCLASS window_class = {0}; 
     HWND window; 
     HMENU my_menu; 

     window_class.lpfnWndProc = (WNDPROC)internal_WndProc; 
     /* fill in window_class here */ 
     RegisterClass(&window_class); 

     window = CreateWindow(
      "My Application", "Stupidity", 
      WS_OVERLAPPEDWINDOW, 
      CW_USEDEFAULT, CW_USEDEFAULT, 
      CW_USEDEFAULT, CW_USEDEFAULT, 
      NULL, my_menu, instance, NULL); 

     // save the address of the class as the Window's USERDATA. 
     SetWindowLong(window, GWLP_USERDATA, (long)this); 
    } 
}; 

http://msdn.microsoft.com/en-us/library/windows/desktop/ff381400(v=vs.85).aspx

1

私は単純な解決方法を使用します。 winprocはテンプレート関数です。 メッセージ受信者はsetwindowptrの内側です。

受信者がメッセージ名を持つ関数、たとえばonpaintを持つ場合、wm_paintはメッセージスイッチに含まれます。

http://www.thradams.com/codeblog/wndproc.htm

関連する問題