2009-10-08 69 views
14

我想讓用戶調整右下角的無邊框窗口的大小,就像我可以調整組合框控件的自動填充窗口一樣。調整右下角的無邊界窗口

我無法找到屬性來配置表單。

也許有人可以幫我解決這個問題。

的圖像可以在這裏找到:

enter image description here

+0

發表了一些代碼。您可以通過更改控件的寬度和高度來調整大小。 – 2009-10-08 05:50:52

+0

由於Andrew Keith的評論,修改了問題並添加了截圖的鏈接:用戶應該能夠調整表單的大小。 – 2009-10-08 05:59:21

+0

使用面板查看我的解決方案:http://stackoverflow.com/a/8848440/640781 – edid 2012-01-13 09:42:07

回答

13

實現此目的的正確方法是將消息處理程序處理程序(例如,通過重寫Form.WndProc)添加到窗體並處理消息WM_NCHITTEST。 (您可以在PInvoke.net上找到該消息的C#定義)特別是,當您收到消息時,計算命中測試是否針對指定調整大小的區域中的點,如果是,則返回HTBOTTOMRIGHT。默認的窗口過程會爲你完成剩下的工作,因爲它假設用戶點擊了窗口邊界的右下角,即使你的窗口沒有邊框。

這個問題需要一點點的Win32 interop,但它會使你的調整大小看起來像其他任何窗口調整大小。

最簡單的方法是按@benPearce的說法,在面板的角落放置一個面板,並使用寬度/高度調整窗體大小。它會起作用,但調整大小不會一帆風順,特別是在Vista和Win7 Basic中,在標準移動和重新調整大小時完全重繪被禁用,而每一步都將嘗試重繪。

更新:在這兩種方法中,您將不得不弄清楚如何繪製抓手。例如,您可以放置​​標準抓手的位圖。儘管如此,由於您的表單沒有標題和邊框,因此您不一定會使用標準的Windows視覺效果,您可能會選擇更快捷的方式。

更新2:如果您有一個覆蓋整個窗口的控件,它將吃掉表單鼠標消息。你必須以某種方式剪輯你想用來調整大小的地方。您有幾種選擇來處理這個:

  1. 調整控制,使尺寸調整握一些空間。
  2. 調整控制區域(通過Region屬性)以排除調整大小的控制點。
  3. 覆蓋調整大小控制面板,聽取它的MouseEnter消息,並將Capture屬性設置爲true,這將導致所有更多的鼠標消息到達它。 注意:調整大小完成後,鼠標離開該區域後,您將不得不釋放捕獲。

我會推薦去選擇最簡單的選項1。選項3是最複雜的,需要關於鼠標輸入在Windows中的工作方式的詳細信息,所以我不會推薦它。選項2是選項1的一個很好的選擇,但您必須嘗試查看ListView控件如何對其區域進行調整。

+1

非常感謝,這對於靜態表單非常有用。但是我的表單包含一個填充表單的列表視圖。沒有WM_NCHITTEST消息被激發。 – 2009-10-08 06:41:38

+1

任何人都在尋找如何繪製抓手,'ControlPaint.DrawSizeGrip'是一個開始。 – AnotherUser 2014-07-02 11:23:38

2

將面板或在角落裏其他一些控制,使用面板的MouseDown和mousemove事件時,調整形式大小適當。

在MouseDown中,我會記錄座標,然後在MouseMove中,您可以計算與原始位置的差異來調整表格大小。

+0

我認爲第二句中「MouseDown」的最後一個實例應該是「MouseMove」。 – bentsai 2010-02-17 14:32:50

+0

正確!更新。 – benPearce 2010-02-17 22:01:50

+0

這花了一些工作,但我更喜歡乾淨的事件驅動的解決方案比其他建議更好。謝謝 – BrianLegg 2015-12-24 19:49:30

31

下面是與Franci的解釋相對應的代碼,我正在寫它,但他同時回答了他的解釋,如果這段代碼適合您的需求,那麼這是很好的解決辦法。

protected override void WndProc(ref Message m) { 
    const int wmNcHitTest = 0x84; 
    const int htBottomLeft = 16; 
    const int htBottomRight = 17; 
    if (m.Msg == wmNcHitTest) { 
     int x = (int) (m.LParam.ToInt64() & 0xFFFF); 
     int y = (int) ((m.LParam.ToInt64() & 0xFFFF0000) >> 16); 
     Point pt = PointToClient(new Point(x, y)); 
     Size clientSize = ClientSize; 
     if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) { 
      m.Result = (IntPtr) (IsMirrored ? htBottomLeft : htBottomRight); 
      return; 
     } 
    } 
    base.WndProc(ref m); 
} 

編輯:寫夾子,你可以初始化一個new VisualStyleRenderer(VisualStyleElement.Status.Gripper.Normal)並使用其PaintBackground()方法。

+1

有關繪製抓手的更多說明,請參閱http://stackoverflow.com/a/4918111/161052 – JYelton 2012-11-28 20:54:55

19

非常感謝發佈這個偉大的樣本和解釋。我在下面添加了一些其他代碼可能會感興趣的附加內容。這裏的一些代碼來自其他stackoverflow帖子,但爲了能夠在一個代碼塊中看到它,可能會對其他人有所幫助。 我希望能夠調整窗體的大小,而不僅僅是右下角。我也想能夠拖動表格。最後,我想要一個陰影。

//*********************************************************** 
//This gives us the ability to resize the borderless from any borders instead of just the lower right corner 
protected override void WndProc(ref Message m) 
{ 
    const int wmNcHitTest = 0x84; 
    const int htLeft = 10; 
    const int htRight = 11; 
    const int htTop = 12; 
    const int htTopLeft = 13; 
    const int htTopRight = 14; 
    const int htBottom = 15;    
    const int htBottomLeft = 16; 
    const int htBottomRight = 17;   

    if (m.Msg == wmNcHitTest) 
    { 
     int x = (int)(m.LParam.ToInt64() & 0xFFFF); 
     int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16); 
     Point pt = PointToClient(new Point(x, y)); 
     Size clientSize = ClientSize; 
     ///allow resize on the lower right corner 
     if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) 
     {   
      m.Result = (IntPtr)(IsMirrored ? htBottomLeft : htBottomRight); 
      return; 
     }  
     ///allow resize on the lower left corner 
     if (pt.X <= 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) 
     { 
      m.Result = (IntPtr)(IsMirrored ? htBottomRight : htBottomLeft); 
      return; 
     } 
     ///allow resize on the upper right corner 
     if (pt.X <= 16 && pt.Y <= 16 && clientSize.Height >= 16) 
     { 
      m.Result = (IntPtr)(IsMirrored ? htTopRight : htTopLeft); 
      return; 
     } 
     ///allow resize on the upper left corner 
     if (pt.X >= clientSize.Width - 16 && pt.Y <= 16 && clientSize.Height >= 16) 
     { 
      m.Result = (IntPtr)(IsMirrored ? htTopLeft : htTopRight); 
      return; 
     } 
     ///allow resize on the top border 
     if (pt.Y <= 16 && clientSize.Height >= 16) 
     { 
      m.Result = (IntPtr)(htTop); 
      return; 
     } 
     ///allow resize on the bottom border 
     if (pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) 
     { 
      m.Result = (IntPtr)(htBottom); 
      return; 
     } 
     ///allow resize on the left border 
     if (pt.X <= 16 && clientSize.Height >= 16) 
     { 
      m.Result = (IntPtr)(htLeft); 
      return; 
     } 
     ///allow resize on the right border 
     if (pt.X >= clientSize.Width - 16 && clientSize.Height >= 16) 
     { 
      m.Result = (IntPtr)(htRight); 
      return; 
     } 
    } 
    base.WndProc(ref m); 
} 
//*********************************************************** 
//*********************************************************** 
//This gives us the ability to drag the borderless form to a new location 
public const int WM_NCLBUTTONDOWN = 0xA1; 
public const int HT_CAPTION = 0x2; 

[DllImportAttribute("user32.dll")] 
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 
[DllImportAttribute("user32.dll")] 
public static extern bool ReleaseCapture(); 

private void YOURCONTROL_MouseDown(object sender, MouseEventArgs e) 
{ 
    //ctrl-leftclick anywhere on the control to drag the form to a new location 
    if (e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Control) 
    {  
     ReleaseCapture(); 
     SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); 
    } 
} 
//*********************************************************** 
//*********************************************************** 
//This gives us the drop shadow behind the borderless form 
private const int CS_DROPSHADOW = 0x20000; 
protected override CreateParams CreateParams 
{ 
    get 
    { 
     CreateParams cp = base.CreateParams; 
     cp.ClassStyle |= CS_DROPSHADOW; 
     return cp; 
    } 
} 
//***********************************************************