スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

DockPanel Suiteの座標の考え方

リサイズ時にDocumentや複数のウィンドウのサイズを固定するときの設定方法について

整理して考えてみたところ、DockPanel Suiteでは次のような座標設定になっているようです。
2014-12-20 191759

上から(行,列)の形式でインデックスの開始を0からとして、(0,1)のマスには必ずTopが格納されます。(0,0)、(0,2)のマスはドッキングの順番によってTopがくることもあれば、それ以外のウィンドウが格納されることもあります。これはどのウィンドウを最初にドッキングしたかによって決まり、例えば、一番最初にTopをDockPanelにドッキングすれば、Topは(0,0)~(0,3)にドッキングされ、次にLeftをドッキングすればLeftは(1,0),(2,0)にドッキングされます。逆にLeftを先にドッキングしてから、Topをドッキングすると、Leftは(0,0)~(3.0)に、Topは(0,1),(0,2)にドッキングされます。

この順序関係を判定するのをはかなりめんどくさいので、必ずTop, Left, Bottom, Rightがドッキングされる(0,1),(1,0),(2,1),(1,2)のマスについて考えます。これらのマスの大きさ(ピクセル数)を、

\begin{verbatim}top\end{verbatim}=(T_x, T_y)
\begin{verbatim}left\end{verbatim}=(L_x, L_y)
\begin{verbatim}right\end{verbatim}=(R_x, R_y)
\begin{verbatim}bottom\end{verbatim}=(B_x, B_y)

とします。このうちT_y, B_y, L_x, R_xについてはDockPanelのプロパティDock○○Portion(○○:Top, Left, …)によって設定できるので、これらについて式を解けばいいことになります。ウィンドウ全体のサイズを(X, Y)とすると、

L_x + R_x = X - T_x = X - B_x
T_y + B_y = Y - L_y = Y - R_y

ここでTopのxとBottomのx、LeftのyとRightのyは等しいことになります。これはつまりDocumentのxとyにほかならないので、

T_x = B_x = D_x, L_y = R_y = D_y

とすることで、ドックパネル全体のレイアウトを決定することができます。それぞれのPortionの値については相対比で表す場合は(*)、

p_L = L_x / X, p_R = R_x / X, p_T = T_y / Y, p_B = B_y/Y

このように計算されます。
(*) Portion自体はdouble型で定義されていて、1以下の場合は相対比で指定され、1より大きい場合はピクセル数の絶対指定されます。つまり、このPortion自体がLeftとRight、TopとBottomでどれだけの領域を配分するかという値と、絶対指定するかどうかのフラグをそれぞれ内包しているのです。DocumentのXとYさえ指定すれば全てのウィンドウを固定・伸縮させることができます。

さて、リサイズ時に他のウィンドウのPortionをいじらなければならない場合とはどういう状態でしょうか?例えばLeftとRightのPortionについて考えてみると、

・両方固定(>1)の場合 → DockPanel Suite本来の仕様で固定されるので必要ない
・両方非固定(≦1)の場合 →  〃          〃 勝手にピクセル配分されるので必要ない
・Leftが固定で、Rightが非固定の場合 → サイズ変更にあわせてこちらが指定してあげる必要がある
・Rightが非固定で、Leftが固定の場合 →     同上


太字で示したパターンのみリサイズ処理を入れればいいということになります。これを実装すると次のようになります。

int documentx = 200;
int documenty = 200;

void Form1_SizeChanged(object sender, EventArgs e)
{
int x = dockPanel1.ClientRectangle.Width;
int y = dockPanel1.ClientRectangle.Height;
if(dockPanel1.DockLeftPortion <= 1 && dockPanel1.DockRightPortion > 1)
{
dockPanel1.DockLeftPortion = Math.Max((x - documentx - dockPanel1.DockRightPortion) / x, 0);
}
if(dockPanel1.DockRightPortion <= 1 && dockPanel1.DockLeftPortion > 1)
{
dockPanel1.DockRightPortion = Math.Max((x - documentx - dockPanel1.DockLeftPortion) / x, 0);
}
if(dockPanel1.DockTopPortion <= 1 && dockPanel1.DockBottomPortion > 1)
{
dockPanel1.DockTopPortion = Math.Max((y - documenty - dockPanel1.DockBottomPortion)/y, 0);
}
if(dockPanel1.DockBottomPortion <= 1 && dockPanel1.DockTopPortion > 1)
{
dockPanel1.DockBottomPortion = Math.Max((y - documenty - dockPanel1.DockTopPortion)/y, 0);
}
}


※追記
Portionの最小値を0とするとOutOfRangeExceptionが飛ぶようなので、0にしたいときは0.001とかほぼ0に近い値(もしくは2pxとか0に近い固定値)を設定することを推奨。


※座標の設定を
Top : (0,0), (0,1)
Left : (1.0). (2,0)
Bottom : (2,1),(2,2)
Right : (0,2),(1,2)
と組み合わせて設定すると、サイズ計算が左右独立になって計算しやすくなるのですが、Documentのサイズが(D_x, D_y) = (B_x + T_x - X, L_y + R_y - Y)となり、フォームサイズが大きくなるほどDocumentが小さくなるという現象が起こるので(パラメーターや条件設定がいけないのかもしれないです)上手く行かなかったです。
スポンサーサイト
プロフィール

こしあん

Author:こしあん
(:3[____]
【TwitterID : koshian2】
【ほしい物リスト】http://goo.gl/bDtvG2

Twitter
カウンター
天気予報

-天気予報コム- -FC2-
カテゴリ
月別アーカイブ
最新記事
最新トラックバック
検索フォーム
リンク
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。