« 10.27 Microsoft Visual Basic 2005実践講座 | ココ | 10.28 NZD若干調整 »

2006年10月27日

WM_NCCALCSIZEで苦戦  このエントリーを含むはてなブックマーク 

先日紹介したMDITabコントロールではWM_NCPAINTでタブを描画しているようで、"NC"ってことは、non-clientということなのでして。クライアント領域にタブを描画しているわけではない。まぁ、1つ1つ違う内容を保持しているウィンドウに共通したタブを描画することは、コード管理の点から見ても非効率的なので、非クライアント領域に描画することは合点がいく。

非クライアント領域に描画することを利用したTipsについては、ざっと下記のものがある(敢えて英語で)。


非クライアント領域の大きさを大きくしたり、クライアント領域の大きさを小さくするトリックなら結構いろいろなところで紹介されているんだけども、逆(クライアント領域の大きさ「だけ」を大きくする)があまりない。参考になりそうな*1はウィンドウの枠線をカスタム描画する方法。こちらは厳密にはWM_NCPAINTになるんだが。
テキストボックスにカスタムボタンを追加する*2は、WM_NCCALCSIZEで入力部分を狭くして、非クライアント領域にボタンを描画する。これはテクニック的に参考になった。
そして*3は、本家MSDN内のブログでのWM_NCCALCSIZEの説明。どのパラメータが何を指しているのかが書かれているんやけど、これによるとWM_NCCALCSIZEで渡されるNCCALCSIZE_PARAMS構造体はウィンドウプロシージャ内で別の用途で使い回されているらしい。単純にMSDNでの説明どおりではなさげ。オブジェクト指向の観点から考えると、こういった使い方はもうご法度に近いものがあるのだろうが、メモリが少なかったWin95とかの時代から使われ続けてることを考えると、仕方ないのかもしれない。

非クライアント領域をなくしたい場合は、WndProc()でWM_NCCALCSIZEを受け取ったときに何もせずにReturnだけすればよい、ということなのではあるが、なぜこうすると非クライアント領域がなくなるか、僕にはまったく理解できない。
このメッセージを処理するときに、変更する対象となる矩形と、戻り値で処理のされ方が変わるということのようだけども、ウィンドウの矩形だ、クライアント領域の矩形だ、その上、変更前だ、変更後だ、メッセージ処理後にはそれがこう変化する、ということの規則性が分からないんよね。

結局最終手段として結論に達したのが、MyBase.WndProc(m)で一旦処理してしまい、NCCALCSIZE_PARAMS.rgrc(0)(※新しいクライアント領域の矩形が入っている)を好きに変更する、戻り値は0、MyBase.WndProc()の2回目は呼び出さずにReturn、という手法。これなら何も考えなくていい。実際、こういった手法を使ってるところもあるみたい。

WM_NCCALCSIZE, WM_NCPAINTを駆使すれば、たぶん下のような画も可能だと思う。
ToDoList 5.0 Beta (b5)

Docking Windows WinDockChild Codeに一歩近づいた。

By ただ at 23:02 カテゴリー ; プログラミング単語帳 , リンク , プログラミング , mein Erbe , 仕事関係

« 10.27 Microsoft Visual Basic 2005実践講座 | 10月の記事 | 10.28 NZD若干調整 »




トラックバック

このエントリーのトラックバックURL:
http://pinmarch.sakura.ne.jp/mt/mt-tb.cgi/688