2011-08-24 37 views
1

我想要一個帶有BorderStyle = bsNone(無邊框,無標題)的TForm,但它可以調整大小和移動。我已經想出瞭如何做可調整的部分,但我堅持讓它可移動。C++ Builder:使用BorderStyle bsNone創建一個TForm,但仍然可移動和可調整大小

/** 
* Overrides standard CreateParams method to create a TForm with BorderStyle 
* bsNone but is nevertheless movable and resizable 
**/ 
void __fastcall CreateParams(TCreateParams &Params) 
{ 
    BorderStyle = bsNone; 
    TForm::CreateParams(Params); 
    //set flag WS_EX_STATICEDGE 
    //for more details on this flag, see http://msdn.microsoft.com/en-us/library/ms632680(v=vs.85).aspx 
    Params.ExStyle = Params.ExStyle^0x00020000L; 
    //set flag WS_SIZEBOX 
    //for more details on this flag, see http://msdn.microsoft.com/en-us/library/ff700543(v=VS.85).aspx 
    Params.Style = Params.Style^0x00040000L; 
} 

這可能只是找到正確的標誌的問題。有任何想法嗎?

回答

5

的最好方法允許移動形式是模仿形式如何移動,當您單擊並拖動標題欄。由於您的窗口沒有標題欄,因此當Windows需要知道表單的哪部分時,鼠標光標停留在您說謊並告訴Windows它確實在標題欄上。之後,因爲默認行爲正常進行,所以移動工作正常。

要做到這一點,您要回復WM_NCHITTEST message,這很容易通過overriding the form's WndProc method完成。此消息在幾種情況下發送(不只是鼠標點擊或移動),所以不要假設用戶在收到此消息時所做的任何事情。通過將消息結果設置爲HTCAPTION來處理它,該值指示位置在標題欄上。

重要的事情需要注意的是:

  • 這種方法將被調用爲每封郵件的形式獲得;這裏不要做任何緩慢或複雜的事情。
  • 總是讓默認繼承的實現WndProc處理消息。這對於大多數消息來說是必不可少的,因爲你只想改變這個消息的行爲,如果你不調用繼承的消息,消息根本就不會發生,但是對於這個消息來說也是很重要的,因爲你不知道哪些代碼需要發送此消息。也就是說,你想增加你的程序對此的反應,而不是取代它。這是您攔截/添加的所有消息處理的一般良好指南。 WndProc文檔也提到了這一點。
  • 通過檢查鼠標座標,可以將表單的區域設置爲可拖動位。在下面的代碼中,只有表單的前100個像素是可拖動的。

示例代碼:

void __fastcall TForm1::WndProc(Messages::TMessage& Message) { 
    TForm::WndProc(Message); // Inherited implementation 
    if (Message.Msg == WM_NCHITTEST) { 
     TWMNCHitTest& oMsg = reinterpret_cast<TWMNCHitTest&>(Message); 
     TPoint oPoint(oMsg.XPos, oMsg.YPos); // Screen coordinates 
     oPoint = ScreenToClient(oPoint); // Now in form-local coordinates 
     // It's in the title bar (caption) if it's in a rectangle at the top of the form 
     if ((oPoint.x > 0 && oPoint.x < ClientWidth) && 
      (oPoint.y > 0 && oPoint.y < 100)) 
     { 
      oMsg.Result = HTCAPTION; 
     } 
    } 
} 
+1

非常感謝!這是我非常樂意接受! – mort

4

嘗試把這個代碼到窗體onmousedown事件的事件處理程序:

ReleaseCapture(); 
this->Perform(WM_SYSCOMMAND, 0xF012, 0); 
+2

更好地提供一個'WM_NCHITTEST'處理程序返回HTCAPTION在形式應該是可移動的,而不是一個未公開的伎倆。 –

+0

@Sertac Akyuz:您好,請給出一些關於您的想法的更多信息?我真的不明白你的想法。 – mort

+0

@mort - 查看[本頁]上的WM_NCHITTEST處理程序示例(http://bcbjournal.com/bcbcaq/?loc=forms&caq=44)。例如,'Dispatch'後,你可以做'if(Pt.y <21)Msg.Result = HTCAPTION;'其中Pt是一個TPoint轉換爲客戶端座標與ScreenToClient'從一個點分配從Msg.LParam低字是x,高字是y)。另見[本頁](http://www.delphigroups.info/3/10/173301.html),其中使用了「MapWindowPoints」而不是ScreenToClient。 –

相關問題