2012-02-24 3 views
0

私は自分のパーソナライズされたwinapiラッパーを開発しています。私の希望構文は、次のとおりです。ボタンとウィンドウクラスをリンクする

// #define wndproc(name) void name (Window & hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
// #define buttonproc(name) void name (Button & hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 

wndproc (rightClick) { //evaluates to function to handle window message 
    ::msg ("You right clicked the window. Closing window..."); 
    hwnd.close(); //close() is implemented in my Window class 
} 

buttonproc (buttonClick) { //same thing basically 
    ::msg ("You clicked this button. I'm going to hide the other one..."); 

    //if text on this button is "One button", find the one belonging to parent 
    //with the text "Other button" and hide it, or vice-versa 
    hwnd.text == "One button" 
    ? hwnd.parent().button ("Other button").hide(); 
    : hwnd.parent().button ("One button").hide(); 
} 

int main() { 
    Window win; //create default window 
    win.addmsg (WM_LBUTTONDOWN, rightClick); //look for l-click message and call that 

    Button b1 (win, "One button", 100, 100, 50, 20, buttonClick); //parent, coords, size, clicked 
    Button b2 (win, "Other button", 200, 100, 50, 20, buttonClick); 

    return messageLoop(); //should be self-explanatory 
} 

事があり、wndprocで、hwndWindow &あるとbuttonprocで、hwndButton &です。

msgproc (Window, rightClick){...} 
msgproc (Button, buttonClick){...} 

問題は、私はこれらの手順を呼び出し、それらを右hwndを与えるために持っているという事実である:私は言って逃げることができるかもしれません。私のメインウィンドウの手順は私のWindowクラスで実装されています。それは4つの通常の引数を取得します。右ボタンの手順にWM_COMMANDというメッセージを渡す必要がある場合は、対応するButtonオブジェクトを付けたいと思います。

現状では、WindowButtonの両方のスーパークラスへのポインタを渡します。もちろん、次のような複雑なコードを作成します。

((Window *)hwnd)->operator()() //get HWND of the Window 

実際にはうまくいかないようです。残念ながら、現時点で私が考えることができる唯一の方法は、すべてButtonのリストを作成し、正しいものを取り出しておくことです。私はこれをすべての可能な受信者にまで拡大することさえできました。

このようにする利点は、私のButtonクラスには、メッセージが見つかるたびに呼び出される静的ウィンドウプロシージャがあることです。私は他のコントロールを追加していませんが、既存のものでIDをチェックし、一致する場合にボタンを作成するときに指定したプロシージャを呼び出すことによって動作するように設計されています。これが完了すると、WM_COMMANDハンドラを追加する他のもの(チェックボックスなど)も呼び出されます。

私はすべてのHWNDの子とその対応するオブジェクトのWindowにリストを保持することを考えていました。このようにして、Buttonのようなすべてのクラスで余分な処理を行い、余分な処理が多くなります。をproc [i] (control [loword(wParam)], msg, wParam, lParam)の代わりにWM_COMMANDに置き換え、lParamを使用してコントロールかどうかを確認します。

私は大きなものを見逃しているようです。私はこれを実装してから大きな問題にぶつかる可能性があります。これをすべて行うには良い方法がありますか?

私がそれをやっている間に、正しいオブジェクトタイプ(Button、Checkbox ...)を返すcontrol()関数を作る方法がありますさまざまなオブジェクト(これは私が行うべき方法を見ていると確信しています)?

+0

あなたは明らかにC++を使用しています。なぜマクロを最初に使用するのですか? –

+0

@Cody Grey、その背後にある理由は、一般的に使用されるパラメータのリストを削除することでした。毎回入力するのはかなりのビットです。 – chris

+0

そうです、私はそれを手に入れます。なぜ仮想関数を使用しないのですか?あなたはすでに 'Window'クラスと' Button'クラスを定義しています。 –

答えて

1

質問は、ボタンクラス(または何か)ではなく親に配信されるWM_COMMANDメッセージを処理する方法でした。

最も単純な修正は、WM_COMMANDハンドラをウィンドウベースクラスに追加して、メッセージを生成したコントロールにメッセージを転送することです。メッセージはコントロールのクラスで処理されます。

WM_COMMANDハンドラのコードは次のようなものになります。

if (lParam != 0) 
{ 
    // lParam non zero so this is a control notification. 
    if ((HWND)lParam == hWnd) 
    { 
     // The message has arrived at its destination 
     return OnNotify(HIWORD(wParam), LOWORD(wParam)); 
    } 
    else 
    { 
     // Reflect the message back to the control. 
     return SendMessage((HWND)lParam, WM_COMMAND, wParam, lParam); 
    } 
} 

を私はもともと質問を誤解しました。すべてのウィンドウには、同じウィンドウプロシージャを使用しています

MFCの道

:以下は、オブジェクトにメッセージをルーティングするいくつかの方法について説明します。 HWNDからウィンドウオブジェクトへのグローバルマップがあります。 (マップは実際にはスレッドごとですが、ほとんどのアプリケーションではこれは不要です)。メッセージが到着すると、オブジェクトをルックアップしてメッセージをディスパッチします。 ButtonWindowから派生した場合、クラスごとの処理は非常に簡単です。

ウィンドウが作成されている間に生成されたメッセージをキャプチャする場合は、グローバルウィンドウの手順でウィンドウをマップに追加する必要があります。

ATLの道

すべてのウィンドウは、独自のウィンドウプロシージャがある(最初はウィンドウプロシージャを設定することを容易にするあまり、おそらく独自のクラスを、私は忘れて)。ウィンドウプロシージャは、生成されたスタブで、オブジェクト*へのポインタをロードし、ベースクラスのウィンドウプロシージャ(非静的メンバ関数)にジャンプします。 (これを単純にするために、スタブは、 "実際の"仮想wndprocを呼び出す基本クラスの非仮想のwndprocにジャンプする必要があります).HWNDがオブジェクトにマップする方法を変更することは別として、これは他の点では基本的にMFCモデル

* x86では、スタブはwndprocにジャンプする前にオブジェクトポインタをECXに配置します。これはx64でも動作します(ただし、このように動作するかどうかはわかりませんが)。オブジェクトポインタはHWNDを上書きします(非仮想のwndprocの基本クラスはHWNDパラメータを持ちません)。

+0

私がMFCで持っている1つの問題は、マネージコードを使ってラッパーを記述していることです。私はそれが少し学習の経験を打ち負かすと思うし、私はネイティブコードをとにかくもっとよく知っています。今設定されている方法はあなたのATLの方法です。 WindowとButtonの両方から派生した私のスーパークラスは、ウィンドウプロシージャを持ち、継承された各クラスがそれ自身を実装するように強制します。それはメッセージを渡すときに呼び出されます。ただし、コントロールメッセージが届くと、それは親のWM_COMMANDです。目的地は私のニーズにとって間違った手順です。 – chris

+0

私は、ButtonがWindowから派生できると思っていますが、それらは全く異なる機能を持っています。その関係は親子である。私のWindowクラスは一番上になることができますが、全画面表示、閉じる、ボタンはそれらを使用することはできません。 – chris

+0

MFCより前の.Net。私はしばらくそれを使用していませんが、マネージコードを使用していると確信していますか?それは、主な利点(.Netランタイムを必要としない)の1つを殺します。はい、WM_COMMANDは親に移動しますが、(コントロールの場合)HWNDが含まれているため、適切なオブジェクトに転送するだけです。なぜ、Windowから派生したButtonとTopLevelWindow(フルスクリーン、クローズなど)を持っていないのでしょうか? – arx

関連する問題