2010-08-02 80 views
4

如何讓表格具有固定的寬高比,並在調整大小時保留它?在c#中調整大小後保留表格的寬高比

我知道這可以通過覆蓋OnSizeChanged並手動修改[新]高度/寬度來完成,但是這會導致閃爍,因爲它在調用事件之前被調整大小(大小與寬高比不匹配),然後再次調整大小(以正確的寬高比)。有沒有更好的辦法?

回答

11

一些代碼讓你開始。關鍵是響應WM_SIZING消息,它允許您更改窗口矩形。這個例子很粗糙,你真的想要注意用戶拖動哪個角或邊緣,可以從m.WParam獲得。用戶界面永遠不會很棒,當用戶拖曳一個角落時,你無法做任何合理的事情。使表單的佈局足夠靈活,所以你不關心方面配給是真正的解決方案。當內容不適合時,顯示滾動條可以讓用戶自動執行正確的操作。

using System.Runtime.InteropServices; 
// etc.. 

public partial class Form1 : Form { 
    public Form1() { 
     InitializeComponent(); 
    } 
    protected override void WndProc(ref Message m) { 
     if (m.Msg == 0x216 || m.Msg == 0x214) { // WM_MOVING || WM_SIZING 
      // Keep the window square 
      RECT rc = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); 
      int w = rc.Right - rc.Left; 
      int h = rc.Bottom - rc.Top; 
      int z = w > h ? w : h; 
      rc.Bottom = rc.Top + z; 
      rc.Right = rc.Left + z; 
      Marshal.StructureToPtr(rc, m.LParam, false); 
      m.Result = (IntPtr)1; 
      return; 
     } 
     base.WndProc(ref m); 
    } 
    [StructLayout(LayoutKind.Sequential)] 
    public struct RECT { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 
    } 
} 
+0

糟糕,我不是想要包含WM_MOVING。 – 2010-08-03 14:37:49

+0

謝謝,這是訣竅。我希望有一個更好的方式來處理角落拖拉雖然。 – yoyoyoyosef 2010-08-24 13:15:37

+0

只是說明:此代碼保持高寬比= 1(方形) – 2013-12-12 20:22:12

-3

爲什麼要調整大小,如果你想給用戶一個固定的長寬比?

您可以提供一個帶滑塊的屏幕來更改窗口的大小,以確保寬高比。然後,一旦它被改變,你調整窗口的大小。

我建議讓用戶有能力調整大小,讓他們儘量保持最適合他們的縱橫比。

+1

不同意。這對用戶來說會很煩人。 – eitama 2012-06-02 15:50:36

+0

我既贊成也反對這個答案。反對,因爲很多人(對不起,但它是真的)只是不明智 - 足以拿起一個滑塊來調整窗口的大小。我爲這個答案,因爲我不喜歡改變用戶系統的默認(和預期)行爲。我的建議是:通過左鍵單擊並拖動來正常調整窗口大小。如果用戶想要在保持高寬比的同時調整大小,則處理按鍵事件,以便當用戶按住Shift鍵並按住鼠標左鍵的同時拖動鼠標時,則 – uSeRnAmEhAhAhAhAhA 2014-03-22 14:53:24

+0

應調整高寬比 – uSeRnAmEhAhAhAhAhA 2014-03-22 14:54:08

0

要擴大接受的答案:

protected override void WndProc(ref Message m) 
    { 
     /* 
     internal const int WMSZ_LEFT = 1; 
     internal const int WMSZ_RIGHT = 2; 
     internal const int WMSZ_TOP = 3; 
     internal const int WMSZ_TOPLEFT = 4; 
     internal const int WMSZ_TOPRIGHT = 5; 
     internal const int WMSZ_BOTTOM = 6; 
     internal const int WMSZ_BOTTOMLEFT = 7; 
     internal const int WMSZ_BOTTOMRIGHT = 8; 
     */ 

     if (m.Msg == 0x214) 
     { // WM_MOVING || WM_SIZING 
      // Keep the window square 
      RECT rc = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); 
      int w = rc.Right - rc.Left; // get width 
      int h = rc.Bottom - rc.Top; // get height 
      int z = w > h ? w : h; // z is greatest of the two (w/h) 
      switch ((int)m.WParam) 
      { 
       case 1: //left 
        rc.Bottom = rc.Top + w;//define width 
        rc.Top = rc.Top + (h - (rc.Bottom - rc.Top))/2;//define width 
        break; 
       case 2: //right 
        rc.Bottom = rc.Top + w;//define width 
        rc.Top = rc.Top + (h - (rc.Bottom - rc.Top))/2;//define width 
        break; 
       case 3: //top 
        rc.Right = rc.Left + h;//define width 
        rc.Left = rc.Left + (w - (rc.Right - rc.Left))/2;//define width 
        break; 
       case 4: 
        rc.Top = rc.Bottom - z;//define height 
        rc.Left = rc.Right - z;//define width 
        break; 
       case 5: 
        rc.Top = rc.Bottom - z;//define height 
        rc.Right = rc.Left + z;//define width 
        break; 
       case 6: 
        rc.Right = rc.Left + h;//define width 
        rc.Left = rc.Left + (w-(rc.Right - rc.Left))/2;//define width 
        break; 
       case 7: 
        rc.Bottom = rc.Top + z;//define height 
        rc.Left = rc.Right - z;//define width 
        break; 
       case 8: 
        rc.Bottom = rc.Top + z;//define height 
        rc.Right = rc.Left + z;//define width 
        break; 
       default: 
        break; 
      } 
      Marshal.StructureToPtr(rc, m.LParam, false); 
      m.Result = (IntPtr)1; 
      return; 
     } 
     base.WndProc(ref m); 
    } 
    [StructLayout(LayoutKind.Sequential)] 
    public struct RECT 
    { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 
    } 
相關問題