6

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

私が得るエラー:

エラー:タイプ'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;
}
4

3 に答える 3

10

通常はこの順序で何かです:

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

これにより、BaseWindowからクラスを派生させます。派生クラスでは、BaseWindowの(純粋な仮想)クラスをオーバーライドする「WindowProc」を提供します。ここでの秘訣は非常に単純です。パラメータを直接渡すことはできないため、クラスのアドレスをウィンドウのGWLP_USERDATAに格納し、ウィンドウprocで(試行して)それを取得し、それを使用して派生クラスの仮想を呼び出します。ウィンドウプロシージャ。

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

于 2013-02-02T13:23:37.460 に答える
4

あなたがリンクした他の質問は部分的にしか当てはまりません。

WindowProcメソッドは静的である必要があります。次に、CreateWindowExの呼び出しの直後に、GWLP_USERDATAを2番目のパラメーターとして、これを3番目のパラメーターとしてSetWindowLongPtrを呼び出します。これにより、HWNDがクラスインスタンスに関連付けられます。次に、静的WindowProcメソッドでGetWindowLongPtr(ここでもGWLP_USERDATAを使用)を呼び出して、UIイベントを受信したWindowConsoleインスタンスを取得します。

それはすべてここで詳細に説明されています:

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

于 2013-02-02T13:16:30.367 に答える
1

私は簡単な解決策を使用します。winprocはテンプレート関数です。メッセージ受信者はsetwindowptr内にあります。

受信者がメッセージ名を持つ関数(たとえば、onpaint)を持っている場合、wm_paintはメッセージ交換に含まれます。

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

于 2013-02-02T15:22:12.813 に答える