縦横比を固定したままウィンドウ(Form)を拡大縮小したい
タイトル通り、縦横比を保ったまま、.NETのFormのサイズを変更したかった。で、FormのResizeイベントのドキュメントを見てみると、Formを正方形に保つサンプルが載ってた。それを参考に、FormのClientSizeを4:3に保つコードを書いてみた。
const double fixedRate = (double)4 / 3; private void Form1_Resize(object sender, EventArgs e) { ClientSize = new Size((int)(fixedRate * ClientSize.Height + 0.5),ClientSize.Height); }
これだけで4:3に固定されたよ!やったね!と言いたい所だけど、これだけだとまずい。まず、サイズが変わるたびにちらつく。ついでに、角とか辺とかでサイズ変更すると挙動が若干怪しい。まぁ、挙動はちゃんと書けばどうにかなるような気はするが、SuspendLayoutとか入れたりしたけどちらつきはどうにもならなかった。
他にいろいろイベントを探したけど、うまく行きそうなイベントは見つからなかった。で、.NETじゃないWindouws APIだとどうやってるんだろう、って調べてみると、どうもWM_SIZINGメッセージを受け取ったときにごにょごにょしてあげるといいらしい(c¡Ìä¦ðêèɵÄTCYÏX)。というわけで、FormのWndProcをoverrideしてごにょごにょしてみよう。
//using System.Runtime.InteropServices; const double fixedRate = (double)4 / 3; const int WM_SIZING = 0x214; const int WMSZ_LEFT = 1; const int WMSZ_RIGHT =2; const int WMSZ_TOP = 3; const int WMSZ_TOPLEFT =4; const int WMSZ_TOPRIGHT =5; const int WMSZ_BOTTOM =6; const int WMSZ_BOTTOMLEFT =7; const int WMSZ_BOTTOMRIGHT = 8; [StructLayout(LayoutKind.Sequential)] struct RECT { public int left; public int top; public int right; public int bottom; } protected override void WndProc(ref Message m) { switch(m.Msg){ case WM_SIZING: RECT r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); int w = r.right - r.left - (Size.Width - ClientSize.Width); int h = r.bottom - r.top - (Size.Height - ClientSize.Height); int dw = (int)(h * fixedRate + 0.5) - w; int dh = (int)(w / fixedRate + 0.5) - h; switch(m.WParam.ToInt32()) { case WMSZ_TOP: case WMSZ_BOTTOM: r.right += dw; break; case WMSZ_LEFT: case WMSZ_RIGHT: r.bottom += dh; break; case WMSZ_TOPLEFT: if(dw > 0) r.left -= dw; else r.top -= dh; break; case WMSZ_TOPRIGHT: if(dw > 0) r.right += dw; else r.top -= dh; break; case WMSZ_BOTTOMLEFT: if(dw > 0) r.left -= dw; else r.bottom += dh; break; case WMSZ_BOTTOMRIGHT: if(dw > 0) r.right += dw; else r.bottom += dh; break; } Marshal.StructureToPtr(r, m.LParam, false); goto default; default: base.WndProc(ref m); break; } }
こうすると、ちらつきもなく、挙動もちゃんとしたままサイズの変更が出来るようになった。やったね!