2012-02-17 7 views
1

「最小限の表示」モードでは、特定のポイントを超えてサイズを変更したくないため、最小の高さを設定したフォームがあります。WM_SIZEメッセージからフォームサイズを変更する

ユーザーがAeroでウィンドウを最大化しようとすると、ウィンドウが最大化されますが、ウィンドウの高さは240ピクセル(設定最大サイズ)にすぎません。 wParamSIZE_MAXIMIZEDのときにWM_SIZEメッセージを処理しようとすると、フォームの高さを設定しようとする試みがバイパスされます。

現在、最大化ボタンが押されたときを検出するためにSC_MAXIMIZEを処理しています。ユーザがタイトルバーをダブルクリックするとウィンドウが最大になるようにを処理しています。この両方の状況では、拡張ウィンドウモードを切り替えることができ、フルスクリーンになるように最小サイズを設定できます。

もちろん、ウィンドウが最大化されている場合は、ShowWindow(SW_MAXIMIZE)または画面の上部に空白が表示されても、どちらのメッセージも表示されません。

システムが実際に最大化を行う直前に発生するかもしれない別のメッセージがありますので、手作業でウィンドウサイズと表示モードを調整できますか?

現在のコード:最大ウィンドウサイズは、フルスクリーンを許可するように設定されているため、ウィンドウがWM_SIZEが送信される最大限の拡張表示モードですでにある場合

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == 0x0112) { // WM_SYSCOMMAND 
     if (m.WParam == new IntPtr(0xF030)) { // Maximize event - SC_MAXIMIZE from Winuser.h 
      // The window is being maximized 
      this.MaximumSize = new Size(9999, 9999); 
      ToggleDeviceDisplay(true); 
      linkToggleDeviceList.Visible = false; 
     } 
    } else if (m.Msg == 0x00A3) { // WM_NCLBUTTONDBLCLK - Double clicking on window title bar, min or max 
     if (this.WindowState == FormWindowState.Normal) { 
      if (grpDeviceList.Visible == false) { 
       this.MaximumSize = new Size(9999, 9999); 
       ToggleDeviceDisplay(true); 
      } 
      this.WindowState = FormWindowState.Maximized; 
      linkToggleDeviceList.Visible = false; 
     } else { 
      this.WindowState = FormWindowState.Normal; 
      linkToggleDeviceList.Visible = true; 
     } 
     return; 
    } else if (m.Msg == 0x0005) { // WM_SIZE 
     if (m.WParam == new IntPtr(0x02)) { // SIZE_MAXIMIZED 
      // CANT GET WINDOW TO GO TO FULL-SCREEN FROM HERE 
      this.MaximumSize = new Size(9999, 9999); 

      // THE LINE BELOW DOESN'T WORK, probably because it is already being sized 
      this.Height = Screen.FromHandle(this.Handle).WorkingArea.Size.Height; 
     } else if (m.WParam == new IntPtr(0x00)) { // SIZE_RESTORED 
      linkToggleDeviceList.Visible = true; 
     } 
    } 
    base.WndProc(ref m); 
} 

は、場合、しかし、問題はありません彼らは最小限のモードから最大化しようとすると、私はメッセージ中にフルスクリーンを取るために切り替えるには、アプリケーションを取得することはできません。

私は、メッセージから実行するタイマーや何かを起動させることができるので、すぐにフルスクリーンではないことにユーザーが気付かないほどにサイズを変更することができますが、それはひどいハックです。

EDIT:

2つのウィンドウ状態を説明するために、私は2つのスクリーンショットhereをアップロードしています。上の画像はウィンドウのサイズに制限のない拡張ディスプレイを示し、下の画像はウィンドウの高さを上げることができないように高さ制限が設定された最小表示を示します。スペース。

ありがとうございました。

+0

なぜ16進値の代わりにWM_SIZEのような実際のウィンドウメッセージ定数値を使用していませんか? – kprobst

+0

いいえ、最初は2つのメッセージしか使用していなかったので、私は自分のアプリでそれらを定数として定義する代わりに値を使用しました。 – drew010

+2

Windowsの観点から、「ウィンドウの高さは、ユーザーがそれを大きくしたい場合を除いてYピクセルを超えてはならず、大きくなる」という概念は愚かです。ウィンドウの高さがYピクセルに制限されているか、またはウィンドウの高さがYピクセルに制限されています。あなたはそれを両方向に持つことはできません。 – hvd

答えて

2

あなたはあまりにも複雑な方法で簡単なことをしようとしているようです。私はWM_GETMINMAXINFO messageを処理し、そのサイズや位置が変わるたびにあなたのウィンドウに送られます。このメッセージを処理することで、これらの属性ごとに最大値または最小値を指定して、それが望みよりも小さくまたは大きくならないように効果的に防止することができます。

WndProcを無効にしてウィンドウメッセージを処理する方法を既に知っているので、サンプルコードをたくさん投稿しません。唯一必要なことは、マネージコードでMINMAXINFO構造体を定義することです。このような何か:

[StructLayout(LayoutKind.Sequential)] 
struct POINT 
{ 
    public int X; 
    public int Y; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct MINMAXINFO 
{ 
    public POINT ptReserved; 
    public POINT ptMaxSize; 
    public POINT ptMaxPosition; 
    public POINT ptMinTrackSize; 
    public POINT ptMaxTrackSize; 
} 

使用Marshal.PtrToStructure上で定義されMINMAXINFO構造体のインスタンスにMessage.LParamプロパティに含まれるポインタを変換します。

MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(msg.LParam, typeof(MINMAXINFO)); 
が更新

:あなたが投稿したスクリーンショットから

が、それは二つの異なるディスプレイのように見えるが同一であるので、あなたのWndProc方法の内、あなたのような何かをしたいです唯一の違いは、下部のDataGridViewが表示されているかどうかです。フォームのサイズに関係なく、上部のGroupBoxが表示されます。

したがって、解決策は、関係なく、フォームのサイズが変更されたかのをを提起しなければならないForm.Resizeイベントを(処理するために、単純であるように私には思える手動キャプションバーのボタンをクリックすると、その境界をドラッグ経由、または持つかどうかエアロスナップ)。

このイベントハンドラメソッドの内部で、フォームの現在のサイズを確認します。十分に大きければ、DataGridViewコントロールのVisibleプロパティをtrueに設定します。十分なサイズでない場合は、DataGridView.Visible = falseを設定して「最小限のモード」に切り替えます。

これは技術的には非常に複雑な解決策ではありませんが、あなたが望むすべての目標を達成する必要があるようです。私が理解している動機は、フォームが小さすぎてすべてを見ることができず、フォームが大きくなるとそのインターフェイスを拡張できるようにするには、単純なインターフェイスを提供することです。 Resizeイベントを処理し、そのイベントが発生した後にフォームの実際のサイズを確認すると間違ってはいけません。

代わりの解決策は、AutoScrollプロパティを有効にして、常に両方のコントロールを表示することです。ユーザーがしなければならないことは、必要なものを見るために上下にスクロールすることです。 WinFormsは残りの部分を処理します。

+0

ずっと前に 'WM_GETMINMAXINFO'を実験し始めました。私はそれが行く方法かもしれないと思っています。今私が持っている唯一の問題は、ウィンドウを移動したり、サイズを変更しようとすると、Windowsがそのメッセージを送信することです。アプリが最小限のモードであれば、最大サイズは小さいサイズだと言いたいのですが、エアロスナップをしようとすると、最大サイズがディスプレイのサイズであると思うようにトリックする必要があります。今は、メッセージが移動/サイズ変更のために到着したときを知る方法を理解することが難しいだけです。 – drew010

+0

@drew:私はその動機を理解しているかどうかはわかりません。とにかくAero Snapはそれを画面より大きくするつもりはない。 –

+0

スクリーンショット[here](http://imgur.com/a/Zap2C)を参照してください。問題は、ウィンドウに高さ制限が設定されている最小モードでは、エアロ・スナップがウィンドウを最大化しますが、高さは依然として〜300ピクセルです。私は何とか画面サイズにウィンドウのサイズを増やしたいと同時に、拡張表示を有効にしたいと思います。 'SC_MAXIMIZE'と' WM_NCLBUTTONDBLCLK'を使うと素晴らしいですが、(小さな高さを使って)ウィンドウが最大化された後、エアロ・スナップはWM_SIZEメッセージをポストするだけです。 WM_SIZEでは、高さを変更できないようですが、サイズ変更は無視されます。 – drew010

2

私は正しく理解していますか?ウィンドウのサイズを最小限にして、最大化できるようにしたいですか?そうであれば、あなたのコードはあまりにも複雑で実際には必要ではありません。ウィンドウのプロパティMinimumSizeを使用するだけです。

+0

私は最小サイズを設定しますが、ウィンドウが最小表示モードになっていると、特定の高さを超えてサイズを変更できないため、最大サイズ制限を設定しています。問題は、最小モードで、Aero Snapを使ってウィンドウを最大化すると、最大化する前に最大サイズを増やす方法が見つけられないようです。 – drew010

+0

次に私の次の答えを見てください。 –

1

あなたのフォームは最小サイズ、最大サイズを持ち、タイトルバーのダブルクリック、最大化ボタン、およびエアロスナップを使用して最大化することができますか?トリッキー:-)ここに解決策があります。その後、

プロパティであなたのminimumSizeを設定し、2つのイベント書き込み:

private void Form1_Resize(object sender, EventArgs e) 
{ 
    if (WindowState == FormWindowState.Normal) 
    { 
     MaximumSize = new Size(maxWidth, maxHeight); 
    } 
} 

と:

private void Form1_ResizeEnd(object sender, EventArgs e) 
{ 
    MaximumSize = new Size(0, 0); 
} 

トリックを行います。少なくとも私のマシンで動作します:-)

関連する問題