フローティングできないペインの復元

[戻る]
NOR 2011/05/12(木) 20:57:42
Visual C++ 2008 MFCです。
質問間隔が短くなってしまいますが、ご容赦ください。

ユーザによるフローティングは許可せずに、メニューのコマンドによって
直接ドッキング位置の変更のみできるペインを実現しようとしています。
以下は問題を発生させるための試験的なものです。

SDIのプロジェクトを作成
(高度なフレームペインは「ドッキング可能なプロパティペイン」のみに変更)

CMainFrame::CreateDockingWindows()を以下の部分を変更

    if (!m_wndProperties.Create(... | CBRS_FLOAT_MULTI))
    ↓
    if (!m_wndProperties.Create(... | CBRS_FLOAT_MULTI, AFX_CBRS_REGULAR_TABS,
AFX_CBRS_RESIZE))

メニューに「下」と「右」をとりあえず追加し、コマンドハンドラを以下のようにする

    /* 下 */
    void CMainFrame::On32772()
    {
        m_wndProperties.DockToFrameWindow(CBRS_ALIGN_BOTTOM);
    }

    /* 右 */
    void CMainFrame::On32773()
    {
        m_wndProperties.DockToFrameWindow(CBRS_ALIGN_RIGHT);
    }

これらによって、ユーザによるフローティングはできなくなり、
メニューのコマンドでドッキング位置を変更できるようになりました。

しかし、ペインを下に移動し、アプリケーションを終了させ、
再度起動すると、右に最大サイズでドッキングした状態になってしまいます。

ちなみに、m_wndProperties.Create()で、
AFX_CBRS_RESIZEと一緒にAFX_CBRS_FLOATも付けてやると、
下でも右でも正しく復元されます。

原因を追い切れずに困っているのですが、やはりMFC内部に
「フローティングできないペインはドッキング位置が変わってるわけ無い」
というような前提の復元処理でもあるのでしょうか?

たしかに、CDockingManager::Serialize()のソースを見てみると、
CanFloat()という判定があちこちに見られるのですが。

それとも、ドッキング位置の変更のために呼ぶ関数が間違っているのでしょうか?
よろしくお願いいたします。

えーと 2011/05/13(金) 11:52:01
固定、タブなど幾つかのパネルはLoadState()内部で
処理が分けてあります。
これが原因でそのようになるかと思います。

操作中だけ固定にしたい場合には、SaveState()している最中だけ
AFX_CBRS_FLOATを有効にします。

これまでの改良自体はそのままでいいので、以下の処理を追加して下さい。

1.CMainFrameクラスにメンバ関数 FixMyDockingPane()※名前はご自由に

void CMainFrame::FixMyDockingPane( BOOL bFix )
{
    if( bFix ){
        m_wndProperties.SetControlBarStyle( m_wndProperties.GetControlBarStyle
() & ~AFX_CBRS_FLOAT );
    } else {
        m_wndProperties.SetControlBarStyle( m_wndProperties.GetControlBarStyle
() | AFX_CBRS_FLOAT );
    }
}

2.Appクラスには既にSaveCustomState()が
 あるので、virtual void PreSaveState()を追加します。

3.PreSaveState()内に以下の処理を追加
    dynamic_cast<CMainFrame *>( AfxGetMainWnd() )->FixMyDockablePane( FALSE );

4.SaveCustomState()内に以下の処理を追加
    dynamic_cast<CMainFrame *>( AfxGetMainWnd() )->FixMyDockablePane( TRUE );

えーと 2011/05/13(金) 11:53:52
追加です。
5.AppクラスのLoadCustomState()にも以下の処理を追加
dynamic_cast<CMainFrame *>( AfxGetMainWnd() )->FixMyDockablePane( TRUE );

えーと 2011/05/13(金) 11:55:50
何度もすみません。TT)
LoadState()直後はSaveState()の処理でフロート可で保存されているので、
不可に戻すために追加が必要です。

NOR 2011/05/13(金) 13:16:46
[[解決]]
えーとさん、いつもありがとうございます。
ということは、やはりMFC内部が

> 「フローティングできないペインはドッキング位置が変わってるわけ無い」
> というような前提の復元処理でもあるのでしょうか?

のようになっているため、
保存時や復元時のときだけ、MFCを騙してしまうことになるのですね。

CWinAppEx::PreLoadState()
CWinAppEx::LoadCustomState()
CWinAppEx::PreSaveState()
CWinAppEx::SaveCustomState()

上記の4つの仮想関数をオーバライドし、提案していただいた方法を実装します。
ありがとうございました。

古いスレッドには追加発言できません。