2012-11-19 71 views
1

所以我使用Visual C++,並創建了一個可拖動的無邊框窗口。無論如何,頂部有一個工具欄,我希望能夠通過該工具欄拖動窗口。我仍然希望工具欄能夠正常工作,但是我沒有任何想法如何能夠通過它拖動窗口。這是我的當前窗口(見頂部的工具欄):可通過其菜單欄拖動的C++窗口

window

這是我當前的代碼,使其可拖動:

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

回答

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上其他應用程序正在開始做的事情 - 將菜單欄功能移動到標題欄中繪製的單個按鈕。 (請參閱最新版本的Windows 8中的Firefox/Opera或Windows資源管理器,以便將某些東西移動到標題欄。
+0

謝謝!!!!!!!! –

0

在我的一個應用程序中,我也想讓窗口稱爲「客戶區可拖動」 。不幸的是,提到的解決方案(與HTCAPTION更換HTCLIENT) 確實有一個嚴重的缺陷:

雙擊客戶區現在顯示相同的行爲 雙擊標題(即最小化/最大化窗口)!

爲了解決這個問題,我在我的消息處理程序(摘錄)中做了以下操作:

 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)和變量定義,但 應使程序清晰反正!? (如果不給我一條線,我會添加更多 或所有代碼)。

PS:我剛剛發現了另一個全面的描述這也解釋了區別這兩種解決方案的 :http://tinyurl.com/bqtyt3q