2010-08-02 6 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. –

+0

спасибо, это трюк. Хотелось бы, чтобы был лучший способ справиться с угловыми перетаскиваниями. – yoyoyoyosef

+0

Просто примечание: этот код поддерживает соотношение сторон = 1 (квадрат) –

-3

Зачем предлагать изменение размера, если вы хотите предоставить пользователю фиксированный коэффициент сжатия?

Вы можете предложить экран с ползунком, чтобы изменить размер окна, соответствующее формату. Затем, когда он будет изменен, вы измените размер окна.

Я бы рекомендовал, чтобы ваши пользователи имели возможность изменять размер и позволяли им сохранять пропорции, которые выглядят лучше всего для них.

+1

несогласен. Это будет раздражать пользователя. – eitama

+0

Я за и против этого ответа. Против того, что многие люди (извините, но это правда) просто не сообразительны, достаточно, чтобы понять, что для изменения размера окна нужно использовать слайдер. Я за этот ответ, потому что мне не нравится изменять стандартное (и ожидаемое) поведение системы пользователей. Мое предложение: изменить размер окна, щелкнув левой кнопкой мыши и перетащив его. И если пользователь хочет изменить размер при сохранении пропорций, обработайте событие «вниз», поэтому, когда пользователь удерживает клавишу Shift и перетаскивает мышь, удерживая левую кнопку мыши, вы должны изменить размер – uSeRnAmEhAhAhAhAhA

+0

с соотношением сторон – uSeRnAmEhAhAhAhAhA

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; 
    } 
Смежные вопросы