デル株式会社

CFrameWnd 雑記

Last Updated: Dec.19,2006
使用しているコンパイラは、Microsoft Visual C++ 6.0 です。これ以外のバージョンでは記述と食い違うことがあるかも知れません。

アプリケーションのメインウィンドウの位置とサイズを保存し、次回の起動時に復元する処理は是非とも実装したい機能です。この機能を CFrameWnd の派生クラス CMainFrame において、実装してみたいと思います。

1. ウィンドウの状態の保存

まず、ウィンドウの位置を保存する関数です。

// ウィンドウの位置を保存する
void CMainFrame::SaveWindowPlacement()
{
    WINDOWPLACEMENT wp;
    GetWindowPlacement(&wp);
    AfxGetApp()->WriteProfileBinary(
        _T("Settings"), _T("Window"), (LPBYTE)&wp, sizeof(WINDOWPLACEMENT));
}

上記の関数は、現在のウィンドウの状態を GetWindowPlacement で取得して、レジストリ(あるいは ini ファイル)に保存するものです。WriteProfileBinary を使っているのは少々手抜きなので、気に入らなければ、WINDOWPLACEMENT のメンバから、rcNormalPosition と showCmd の値を保存するように修正してください。showCmd を保存する理由は、最大表示だった場合を考慮するためです。最大表示の場合の rcNormalPosition の値は、最大化する前の通常表示のときの値になっています。

あとはこの関数を、OnDestroy で呼び出します。

void CMainFrame::OnDestroy()
{
    SaveWindowPlacement();

    CFrameWnd::OnDestroy();
} 

2. ウィンドウの状態の復元

今度はウィンドウの位置を復元する関数を作成します。注意してほしいのは、WINDOWPLACEMENT の showCmd メンバの値が、SW_SHOWMAXIMIZED(最大表示)のときのみ、AfxGetApp()->m_nCmdShow に代入している部分です。これにより、アプリケーションは最大表示されることになります。また、アプリケーションで通常表示にすると、前回通常表示だったときの位置とサイズが復元されます。

// ウィンドウ位置を復元する
void CMainFrame::InitWindowPlacement(CREATESTRUCT& cs)
{
    WINDOWPLACEMENT wp;
    LPBYTE pData;
    UINT nSize;
    if (AfxGetApp()->GetProfileBinary(
        _T("Settings"), _T("Window"), &pData, &nSize))
    {
        ASSERT(nSize == sizeof(WINDOWPLACEMENT));
        ::CopyMemory(&wp, pData, sizeof(WINDOWPLACEMENT));
        delete [] pData;
        cs.x = wp.rcNormalPosition.left;
        cs.y = wp.rcNormalPosition.top;
        cs.cx = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
        cs.cy = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
        if (wp.showCmd == SW_SHOWMAXIMIZED)
            AfxGetApp()->m_nCmdShow = SW_SHOWMAXIMIZED;
    }
}

このメンバ関数は、PreCreateWindow で呼び出します。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 
{
    if (!CFrameWnd::PreCreateWindow(cs))
        return FALSE;
    InitWindowPlacement(cs);
    return TRUE;
}

3. フォントデータの保存と復元

アプリケーションで使用するフォントデータの保存・復元用の関数です。こちらもよく使います。

void CMainFrame::InitFontData(CFont* pFont)
{
    LOGFONT lf;
    LPBYTE pData;
    UINT nSize;
    if (AfxGetApp()->GetProfileBinary(
        _T("Settings"), _T("Font"), &pData, &nSize))
    {
        ASSERT(nSize == sizeof(LOGFONT));
        ::CopyMemory(&lf, pData, sizeof(LOGFONT));
        delete [] pData;
        if (pFont->CreateFontIndirect(&lf))
            return;
    }
    pFont->CreatePointFont(10*14, _T("FixedSys"));
}

void CMainFrame::SaveFontData(CFont* pFont)
{
    LOGFONT lf;
    pFont->GetLogFont(&lf);
    AfxGetApp()->WriteProfileBinary(
        _T("Settings"), _T("Font"),
        (LPBYTE)&lf, sizeof(LOGFONT));
}

WriteProfileBinary は、構造体をそのままで扱えるので、とても便利です。ただし、_UNICODE ビルドと _MBCS ビルドで構造体のサイズが違う場合がありますので、そのあたりは注意して使用する必要があります。


Back Copyright (c) 2003, 2006 AOK. All Rights Reserved.