MFC   VC++   Visual Studio   Visual Studio   プログラミング

スプリッタウインドウの最小制限 その2

 前回紹介した方法だと一度小さくなったあと指定のサイズになるため、場合によってはビュー内がちらついたりスクロールバーが一瞬表示されるなどの症状が出るため、今回は別の方法を紹介します。

 今回は、仮想関数「TrackRowSize/TrackColumnSize」を使います。
 これらの関数はペインサイズ変更後に呼ばれ、引数にウインドウ内の仕切り線の位置とサイズ変更されたペインの行/列番号が渡されます。
 例えば、3行になっているビューの真ん中のペインサイズを変更した場合(2番目の仕切り線を移動)、スプリッタウインドウ内の仕切り線の位置「y」とペイン番号「1」が渡されます。

 実際にコードで表すと、CSplitterWnd(Ex)から派生させたクラスのヘッダに、
    virtual void TrackRowSize(int y, int row);
と記述し、cppファイル内に以下のように記述します。
void CMySplitterWndEx::TrackRowSize(int y, int row)
{
    ASSERT_VALID(this);
    ASSERT(m_nRows > 1);

    CPoint pt(0, y);
    ClientToScreen(&pt);
    GetPane(row, 0)->ScreenToClient(&pt);
    m_pRowInfo[row].nIdealSize = pt.y;      // new size
    if (pt.y < m_pRowInfo[row].nMinSize)
    {
        // resized too small
       // m_pRowInfo[row].nIdealSize = 0; // make it go away
        m_pRowInfo[row].nIdealSize = m_pRowInfo[row].nMinSize; // ここを変更
        if (GetStyle() & SPLS_DYNAMIC_SPLIT)
            DeleteRow(row);
    }
    else if (m_pRowInfo[row].nCurSize + m_pRowInfo[row+1].nCurSize
            < pt.y + m_pRowInfo[row+1].nMinSize)
    {
        // not enough room for other pane
        if (GetStyle() & SPLS_DYNAMIC_SPLIT)
            DeleteRow(row + 1);
    }
}
 このとき、引数「y」はペインの高さではなく、スプリッタウインドウ内での仕切り位置で、クライアント領域との隙間などを引き、ペインのクライアント座標に変更した「pt.y」がペインの高さになります。

 今回掲載したコードは、あらかじめ「SetRowInfo/SetColumnInfo」関数で最小値を設定しておき、それ以下になったときに最小値にする、というものです。
 このコードは、何行何列でもすべての行のサイズを最小値にするもので、特定の行だけ制限したい場合は、制限したい行だけ「SetRowInfo」で最小値を設定して下さい。

 あと、行ではなく列で制限したい場合は以下のように記述します。
void CMySplitterWnd::TrackColumnSize(int x, int col)
{
    ASSERT_VALID(this);
    ASSERT(m_nCols > 1);

    CPoint pt(x, 0);
    ClientToScreen(&pt);
    GetPane(0, col)->ScreenToClient(&pt);
    m_pColInfo[col].nIdealSize = pt.x;      // new size
    if (pt.x < m_pColInfo[col].nMinSize)
    {
        // resized too small
       // m_pColInfo[col].nIdealSize = 0; // make it go away
        m_pColInfo[col].nIdealSize = m_pColInfo[col].nMinSize; // ここを変更
        if (GetStyle() & SPLS_DYNAMIC_SPLIT)
            DeleteColumn(col);
    }
    else if (m_pColInfo[col].nCurSize + m_pColInfo[col+1].nCurSize
            < pt.x + m_pColInfo[col+1].nMinSize)
    {
        // not enough room for other pane
        if (GetStyle() & SPLS_DYNAMIC_SPLIT)
            DeleteColumn(col + 1);
    }
}
 追記ですが、この方法だと大きくする方向(下/右)へ仕切り線を移動させた場合、一つ下/一つ右の行/列の最小サイズが確保出来ません。
 そこで、上記の場合でもきちんと動作する方法を次で紹介します。
ランキングへ     posted by 遠雷 | Comment(0) | フレーム
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。