< Word で、図形やワードアートの塗りつぶしの色が表示されない | アイコンの不透明部分のリージョンを作成する >

January 21, 2006

タイトルバーのないウインドウのドラッグ

タイトルバーのないウインドウを、ウインドウ内の任意の位置をドラッグして移動できるようにする方法です。

以下のように、WM_LBUTTONDOWN メッセージをすり替えて、タイトルバー上でマウスボタンが押下されたようにだましてしまうとうまくいきます。

LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_LBUTTONDOWN:
        ReleaseCapture ();
        SendMessage (hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
        return 0;
    default:
        break;
    }
    return DefWindowProc (hWnd, uMsg, wParam, lParam);
}

WM_NCLBUTTONDOWN は、非クライアント領域の左ボタンクリックメッセージです。ちなみに、同じ機能を実現するのに、この方法も時々紹介されています。

LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_NCHITTEST:
        LRESULT lResult = DefWindowProc (hWnd, WM_NCHITTEST, wParam, lParam);
        if ((HTCLIENT == lResult))
        {
            return HTCAPTION;
        }
        return lResult;
    default:
        break;
    }
    return DefWindowProc (hWnd, uMsg, wParam, lParam);
}

マウスイベントなんかの際に、マウス座標がクライアント領域にあるのか、ウインドウのボーダーにあるのか、キャプションにあるのか、などを判断するために WM_NCHITTEST メッセージが送出されます。メッセージ処理の流れとしては、このメッセージの結果がクライアント領域(HT_CLIENT)なら、WM_LBUTTONDOWN や、その他のクライアント領域イベントに振り分けられます。これは、その WM_NCHITTEST をとらえて、その戻り値がクライアント領域ならキャプションにすり替えてやるというものです。これだと、クライアント領域で発生するあらゆるイベントがキャプションのイベントとなってしまうため、WM_RBUTTONDOWN や WM_CONTEXTMENU といったイベントも発生しなくなってしまいます。

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/1263

コメント

こんにちわ
良い方法をご紹介くださり、ありがとうございます♪
このような方法があったのですね♪
今までWM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVEを駆使?して行っていたのですが、どうも素早くマウスを移動させるとメッセージがおかしくなり制御が外れウィンドウの移動がうまくいきませんでした…
上記の方法はそのような事もなく、またコーディング量も少なくて最高です!

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?