ActiveX Control で MDI を実現する

ActiveX Control テクノロジで MDI 形式 の Window を 実現する には次のようにして行う。
(2009/06/28 ※ 複数のブラウザプロセスで動作させた場合に不具合があり、一部投稿内容を修正しました)

① ActiveX Control の上に CMDIFrameWnd を載せる

class CMFCActiveXMDICtrl : public COleControl
{
    DECLARE_DYNCREATE(CMFCActiveXMDICtrl)

protected:
    CMainFrame*    m_pFrameWnd;    // フレーム

protected:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
};

② ActiveX Control の OnCreate イベントハンドラ で CMDIFrameWnd サブクラス を WS_CHILD スタイル で 構築する。

int CMFCActiveXMDICtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (COleControl::OnCreate(lpCreateStruct) == -1)
        return -1;

    HINSTANCE hInst = AfxGetResourceHandle();
    m_hMDIMenu  = ::LoadMenu(hInst, MAKEINTRESOURCE(IDR_MFCMDITYPE));
    m_hMDIAccel = ::LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_MFCMDITYPE));   

    CString strClass = AfxRegisterWndClass(
                            CS_VREDRAW |CS_HREDRAW,
                            ::LoadCursor(NULL, IDC_ARROW),
                            (HBRUSH)::GetStockObject(WHITE_BRUSH),
                            ::LoadIcon(NULL, IDI_APPLICATION));
    CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CMainFrame);
    m_pFrameWnd = (CMainFrame*)pRuntimeClass->CreateObject();

    CCreateContext context;
    context.m_pCurrentDoc = NULL;
    context.m_pNewViewClass = NULL;
    context.m_pCurrentFrame = m_pFrameWnd;

    CRect rc;
    GetClientRect(&rc);

    if (!m_pFrameWnd->Create(strClass, NULL, WS_CHILD, rc,
        this, NULL/*MAKEINTRESOURCE(IDR_MAINFRAME)*/, 0, &context)) // ※
    {
        TRACE0("Error ! Create FrameWnd.");
        return -1;
    }

    m_pFrameWnd->ShowWindow(SW_SHOW);
    m_pFrameWnd->MoveWindow(rc);
    m_pFrameWnd->RecalcLayout(TRUE);

    return 0;
}

※子(WS_CHILDスタイル)ウィンドウはメニューを持つことができません
a child window cannot have a menu.
http://msdn.microsoft.com/en-us/library/ms632599(VS.85).aspx#child

③ CMDIFrameWnd を継承した CMainFrame クラス の 実装

class CMainFrame : public CMDIFrameWnd
{
   
DECLARE_DYNCREATE(CMainFrame)
public:
    CMainFrame();
public:
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
    virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo);

// 実装
public:
    virtual ~CMainFrame();

protected:  // コントロール バー用メンバ
    CToolBar          m_wndToolBar;
    CReBar            m_wndReBar;
    CDialogBar        m_wndDlgBar;

// 生成された、メッセージ割り当て関数
protected:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    DECLARE_MESSAGE_MAP()

protected:
    virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
};

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
    // return CMDIFrameWnd::OnCreateClient(lpcs, pContext);
    return CreateClient(lpcs, NULL);
}

④ Child Window 作成 イベントハンドラ の 実装

void CMFCActiveXMDICtrl::OnFileNew()
{
    CWinApp *pApp = AfxGetApp();
    pApp->m_pMainWnd = m_pFrameWnd;

    CMDIChildWnd* pChildWnd = m_pFrameWnd->CreateNewChild(
        RUNTIME_CLASS(CChildFrame), IDR_MFCMDITYPE, m_hMDIMenu, m_hMDIAccel);

    pChildWnd->SetTitle(COleDateTime::GetCurrentTime().Format());
    pChildWnd->SetWindowText(pChildWnd->GetTitle());

    pApp->m_pMainWnd = NULL;
}

⑤ CChildFrame クラスの Create メソッド の オーバーライド

BOOL CChildFrame::Create(LPCTSTR lpszClassName,
    LPCTSTR lpszWindowName, DWORD dwStyle,
    const RECT& rect, CMDIFrameWnd* pParentWnd,
    CCreateContext* pContext)
{
    if (pParentWnd == NULL)
    {
        CWinApp *pApp = AfxGetApp();
        ENSURE_VALID(pApp);
        CWnd* pMainWnd = pApp->m_pMainWnd;

        ENSURE_VALID(pMainWnd);
        ASSERT_KINDOF(CMDIFrameWnd, pMainWnd);
        pParentWnd = (CMDIFrameWnd*)pMainWnd;
    }
    ASSERT(::IsWindow(pParentWnd->m_hWndMDIClient));

// ここから一部省略

// …..
// …..
// …..

// ここまで一部省略

    ASSERT(hWnd == m_hWnd);
    return TRUE;
}

⑥ Sample HTMLファイル

<html>
<head>
<title>MFCActiveXMDI ActiveX Contol</title>
   <span id="preservea777c851bf5c47eca61176846d0beb51" class="wlWriterPreserve"><script language="jscript" type="text/javascript">
// <!CDATA[
        function buttonNewChild_onclick()
        {
            var ax = document["MFCActiveXMDI"];
            ax.OpenNewWnd();
        }
        function buttonWindowCascade_onclick()
        {
            var ax = document["MFCActiveXMDI"];
            ax.WindowCascade();
        }
        function buttonWindowTileHorz_onclick()
        {
            var ax = document["MFCActiveXMDI"];
            ax.WindowTileHorz();
        }
        function buttonWindowArrange_onclick()
        {
            var ax = document["MFCActiveXMDI"];
            ax.WindowArrange();
        }
// ]]>
   </script></span>
</head>
<body topmargin="0" leftmargin="0" marginwidth="0" marginheight="0">
    <b>MFC ActiveX Control MDI Sample</b><br />
    <table bgcolor="MenuBar"><tr><td>
<input id="buttonNewChild" type="button" value="New Window" onclick="return buttonNewChild_onclick()" />
<input id="buttonWindowCascade" type="button" value="Window Cascade" onclick="return buttonWindowCascade_onclick()" />
<input id="buttonWindowTileHorz" type="button" value="Window Tile Horz" onclick="return buttonWindowTileHorz_onclick()" />
<input id="buttonWindowArrange" type="button" value="Window Arrange" onclick="return buttonWindowArrange_onclick()" />
    </td></tr></table>
<object id="MFCActiveXMDI" classid="CLSID:4F0069A8-DF97-4B7D-88D4-C17F72EAC0F8" width="800" height="600">
</object>

</body>
</html>


ActiveX Control で MDI を実現する」への2件のフィードバック

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください