1

そのため、Visual C ++を使用しており、ドラッグ可能なボーダレスウィンドウを作成しました。とにかく、上部にツールバーがあり、そのツールバーでウィンドウをドラッグできるようにしたいと思います。ツールバーを機能させたいのですが、それによってウィンドウをドラッグする方法がわかりません。これは私の現在のウィンドウです(上部のツールバーを参照):

窓

そして、これはドラッグ可能にするための私の現在のコードです:

case WM_NCHITTEST: {
    LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
    if(hit == HTCLIENT) hit = HTCAPTION;
    return hit;
}
break;
4

2 に答える 2

1

WM_NCHITTESTをフックすることで正しい方向に進んでいます。ここで、クライアントヒットとキャプションヒットの構成を変更する必要があります。私が今あなたのコードを理解しているなら、ウィンドウのクライアント領域内(境界線以外のすべて)をクリックすると、ウィンドウを他の場所にドラッグできます。これにより、アプリケーションとの対話が非常に困難になります。代わりに、ヒットがメニューバー領域内にあると判断した後でのみ、HTCAPTIONを返す必要があります。具体的には、ファイル/編集/ヘルプボタンを保持していないメニューバーの領域。

case WM_NCHITTEST: {
  LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
  if (hit == HTCLIENT) { // The hit was somewhere in the client area. Don't know where yet.
    // Perform your test for whether the hit was in the region you would like to intercept as a move and set hit only when it is.
    // You will have to pay particular attention to whether the user is actually clicking on File/Edit/Help and take care not to intercept this case.
    // hit = HTCAPTION;
  }
  return hit;
  break;
}

ここで覚えておくべきいくつかのこと:

  • これは、アプリケーションを最小化、クローズ、または移動したいユーザーにとって非常に混乱する可能性があります。メニューバーは、ドラッグしてウィンドウを移動できることをユーザーに伝えません。
  • 垂直方向のピクセルに関心がある場合は、Windows上の他のアプリケーションが実行し始めていること、つまりメニューバーの機能をタイトルバーに描画されている単一のボタンに移動することを検討してください。(タイトルバーに移動するためのアイデアについては、Windows8のFirefox/OperaまたはWindowsエクスプローラーの最近のバージョンを参照してください。
于 2012-11-19T18:30:50.433 に答える
0

私のアプリケーションの1つでは、ウィンドウを「クライアント領域をドラッグ可能」と呼んでいるものにしたいとも思っていました。残念ながら、前述のソリューション(HTCLIENTをHTCAPTIONに置き換える)には重大な欠陥があります。

クライアント領域をダブルクリックすると、キャプションをダブルクリックした場合と同じ動作が表示されるようになりました(つまり、ウィンドウを最小化/最大化)。

これを解決するために、メッセージハンドラーで次のことを行いました(抜粋)。

        case WM_MOUSEMOVE:
            // Move window if we are dragging it
            if (mIsDragging) // variable: bool mIsDragging;
            {
                POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

                mIsDragging = (ClientToScreen(hWnd, &mousePos) &&
                               SetWindowPos(hWnd,
                               NULL,
                               mDragOrigin.left + mousePos.x - mDragPos.x,
                               mDragOrigin.top + mousePos.y - mDragPos.y,
                               0,
                               0,
                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE));
            }
            break;

        case WM_LBUTTONDOWN:
            // Check if we are dragging and safe current cursor position in case
            if (wParam == MK_LBUTTON)
            {
                POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
                if (ClientToScreen(hWnd, &mousePos) &&
                    DragDetect(hWnd, mousePos))
                {
                    // Check if the cursor is pointing to your new caption here!!!!
                    mIsDragging = true;
                    mDragPos = mousePos;

                    GetWindowRect(hWnd, &mDragOrigin);
                    SetCapture(hWnd);
                }
            }
            break;

        // Remove this case when ESC key handling not necessary
        case WM_KEYDOWN:
            // Restore original window position if ESC is pressed and dragging active
            if (!mIsDragging || wParam != VK_ESCAPE)
            {
                break;
            }

            // ESC key AND dragging... we restore original position of window
            // and fall through to WM_LBUTTONUP as if mouse button was released
            // (i.o.w. NO break;)
            SetWindowPos(hWnd, NULL, mDragOrigin.left, mDragOrigin.top, 0, 0,
                         SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

        case WM_LBUTTONUP:
            ReleaseCapture();
            break;

        case WM_CAPTURECHANGED:
            mIsDragging = false;
    break;

(擬似)コードは戻り値(デフォルト:0)と変数定義を省略しますが、とにかく手順を明確にする必要があります!?(そうでない場合は、私に1行削除してください。コードを追加するか、すべて追加します)。

ps:これら2つのソリューションの違いを説明する別の包括的な説明を見つけました:http://tinyurl.com/bqtyt3q

于 2012-12-10T21:51:29.640 に答える