科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件实战COM编程系列之四

实战COM编程系列之四

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

客户端使用MFC实现,其中的框架类CMainFrame实现了IModuleSite、IErrorReport和ICompanyInfo 。

作者:lop5712 来源:论坛 2007年10月20日

关键字: 实战 COM 编程

  • 评论
  • 分享微博
  • 分享邮件
客户端使用MFC实现,其中的框架类CMainFrame实现了IModuleSite、IErrorReport和ICompanyInfo,而另一个窗口包装类CTaskManager实现ITaskManager,并由CMainFrame聚合它以表现出CMainFrame实现了ITaskManager。由于代码较长,本篇只罗列CMainFrame::OnCreate和CMainFrame的定义,其中实现了获取部门组件的实例(通过COM的组件类别功能进行记录,而非通过注册表),并进行管理。

  CMainFrame的定义:

#include "NewStatusBar.h"

class CMainFrame : public CFrameWnd
{
 // MFC定义宏
 DECLARE_DYNCREATE( CMainFrame )
 DECLARE_MESSAGE_MAP()
 DECLARE_INTERFACE_MAP()

 // 辅助结构
 private:
 struct TEMPSTRUCT
 {
  HWND m_hWnd;
  HMENU m_hMenu;
  IModule *m_pModule;
  CLSID m_CLSID;
  TEMPSTRUCT() : m_hWnd( NULL ), m_hMenu( NULL ), m_pModule( NULL )
  {
   // 什么都不做
  }
  ~TEMPSTRUCT()
  {
   SafeRelease( m_pModule );
  }
 };

 // 构造、析构
 public:
  CMainFrame();
  ~CMainFrame();

  // 操作
 public:
  void UpdateErrorState() // 更新状态条上的错误标志以表示指示最新错误的发生
  {
   ASSERT_VALID( this );

   if( m_wndStatusBar.GetSafeHwnd() )
    m_wndStatusBar.Invalidate();
  }

  // 辅助函数
 protected:
  // 根据菜单项ID确定是否是基本框架的菜单命令
  BOOL BeMenuOfBase( DWORD nID ) const;

  // 成员变量
 protected:
  CNewStatusBar m_wndStatusBar;
  CToolBar m_wndToolBar;
  DWORD m_Selected;
  long m_OldViewID;
  IUnknown *m_pTaskManager;

  CTypedPtrList< CPtrList, TEMPSTRUCT* > m_ModuleList;

  // 重载
 protected:
  void GetMessageString( UINT nID, CString &rMessage ) const;
  BOOL OnCommand( WPARAM wParam, LPARAM lParam );

  // 窗口消息
 protected:
  afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
  afx_msg void OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized );
  afx_msg void OnSetFocus( CWnd *pOldWnd );
  afx_msg void OnInitMenuPopup( CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu );
  afx_msg void OnInitMenu( CMenu *pMenu );
  afx_msg BOOL OnEraseBkgnd( CDC *pDC );
  afx_msg void OnClose();

  // 菜单消息
 protected:
  void OnModule( UINT nID );
  void OnUpdateModule( CCmdUI *pCmdUI );

  // 自定消息
 protected:
  afx_msg LRESULT OnAllTaskTerminated( WPARAM, LPARAM );

  // 接口映射
 public:
  // IModuleSite
  BEGIN_INTERFACE_PART( ModuleSite, IModuleSite )
  INIT_INTERFACE_PART( CMainFrame, ModuleSite )
  STDMETHOD(ChangeModule)( REFCLSID clsid,
   WCHAR *pModuleName,
   ULONG command,
   ULONG param );
  STDMETHOD(GetFrameWindow)( HWND *pHwnd );
  END_INTERFACE_PART_STATIC( ModuleSite )

  // IErrorReport
  BEGIN_INTERFACE_PART( ErrorReport, IErrorReport )
  INIT_INTERFACE_PART( CMainFrame, ErrorReport )
  STDMETHOD(ReportSoftError)( WCHAR *fileName,
   ULONG row,
   WCHAR *errorString );
  STDMETHOD(ReportHardError)( WCHAR *fileName,
   ULONG row,
   WCHAR *errorString );
   END_INTERFACE_PART_STATIC( ErrorReport )

   // ICompanyInfo
  BEGIN_INTERFACE_PART( CompanyInfo, ICompanyInfo )
  INIT_INTERFACE_PART( CMainFrame, CompanyInfo )
  STDMETHOD(GetDataServerInfo)( WCHAR **pLoaction,
   WCHAR **pServer,
   WCHAR **pPassword );
  END_INTERFACE_PART_STATIC( CompanyInfo )
 };

 CMainFrame::OnCreate代码

 int CMainFrame::OnCreate( LPCREATESTRUCT lpCreateStruct )
 { 
  if( CFrameWnd::OnCreate( lpCreateStruct ) == -1 )
   return -1;

  // 创建基本工具条及状态条
  EnableDocking( CBRS_ALIGN_ANY );

  if( !m_wndToolBar.CreateEx( this, TBSTYLE_FLAT,
    WS_CHILD | WS_VISIBLE | CBRS_TOP |
    CBRS_GRIPPER | CBRS_TOOLTIPS |
    CBRS_FLYBY | CBRS_SIZE_DYNAMIC,
    CRect( 0, 0, 0, 0 ) ) )
   WriteSoftErrorLog( __LINE__, __WFILE__,IDS_MAINFRM_CREATETOOLBAR );
  else
  {
   m_wndToolBar.EnableDocking( CBRS_ALIGN_ANY );
   DockControlBar( &m_wndToolBar );
  }

  if( !m_wndStatusBar.Create( this ) ||!m_wndStatusBar.SetIndicators( indicators,
sizeof( indicators ) / sizeof( UINT ) ) )
  {
   WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_CREATESTATUSBAR );
   return -1;
  }
  else
  {
   CCmdTarget *pTarget = m_wndStatusBar.Initial();
   if( !pTarget )
   {
    WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_CREATESTATUSBAR );
    return -1;
   }
   ASSERT_VALID( pTarget );

   // 设置任务管理器的指针以使得CMainFrame聚合CTaskManager
   pTarget->m_pOuterUnknown = GetControllingUnknown();
   m_pTaskManager = reinterpret_cast< IUnknown* >( &pTarget->m_xInnerUnknown );
   ASSERT( m_pTaskManager );
  }

  // 创建组件类别管理器并获得模块CLSID枚举器
  IEnumCLSID *pEnum = NULL;
  ICatInformation *pCat = NULL;
  CATID tempCATID[1] = { CATID_Example };

  if( FAILED( CoCreateInstance( CLSID_StdComponentCategoriesMgr,
   NULL,
   CLSCTX_INPROC_SERVER,
   IID_ICatInformation,
   reinterpret_cast< void** >( &pCat ) ) ) ||
FAILED( pCat->EnumClassesOfCategories( 1, tempCATID, 0, NULL, &pEnum ) ) )
  {
   MessageBox( L"致命错误!系统即将退出。", g_SysCaption );
   WriteHardErrorLog( __LINE__,__WFILE__,IDS_KILLINGERROR );
   SafeRelease( pCat );
   SafeRelease( pEnum );
   return -1;
  }
  pCat->Release();

  // 枚举每个模块信息
  g_theApp.BeginWaitCursor();

  CLSID clsid;
  CStringW temp;
  TEMPSTRUCT *pStruct = NULL;
  IModuleUI *pUI = NULL;
  IMenuUpdate *pMenuUp = NULL;
  long index = -1;
  IModuleSite *pSite = static_cast< IModuleSite* >(
  GetInterface( &IID_IModuleSite ) );

  pSite->AddRef();
  while( pEnum->Next( 1, &clsid, NULL ) == S_OK )
  {
   ++index;
   pStruct = new TEMPSTRUCT;
   if( !pStruct )
   {
    WriteSoftErrorLog( __LINE__,__WFILE__,IDS_OUTOFMEMORY );
    continue;
   }

  // 创建模块对象
  if( FAILED( CoCreateInstance( clsid,NULL,CLSCTX_INPROC_SERVER,IID_IModule,
reinterpret_cast< void** >(
&pStruct->m_pModule ) ) ) )
  {
   WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_CREATEMODULE );
   delete pStruct;
   continue;
  }
  pStruct->m_CLSID = clsid;

  // 初始化模块
  if( FAILED( pStruct->m_pModule->InitialModule( pSite,IDC_MODULE_VIEW +index–1 ) ) )
  {
   WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_CREATEMODULE );
   delete pStruct;
   continue;
  }

  // 获取模块窗口
  if( FAILED( pStruct->m_pModule->QueryInterface(IID_IModuleUI,reinterpret_cast< void** >( &pUI ) ) ) )
  {
   WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_GETMODULEWND );
   delete pStruct;
   continue;
  }
  if( FAILED( pUI->GetMainWindow( &pStruct->m_hWnd ) ) || !pStruct->m_hWnd )
  {
   WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_GETMODULEWND );
   pUI->Release();
   delete pStruct;
   continue;
  }
  pUI->Release();
  {
   // 修改窗口风格,确保模块窗口具有WS_EX_CLIENTEDGE风格
   if( !::SetWindowLong( pStruct->m_hWnd,GWL_EXSTYLE,::GetWindowLong( pStruct->m_hWnd,
GWL_EXSTYLE ) | WS_EX_CLIENTEDGE ) )
    WriteSoftErrorLog( __LINE__,__WFILE__,IDS_SETWINDOWSTYLE );
  }

  // 隐藏模块窗口
  ::ShowWindow( pStruct->m_hWnd, SW_HIDE );

  // 获取模块的菜单句柄,并插入到MainFrame
  if( SUCCEEDED( pStruct->m_pModule->QueryInterface(IID_IMenuUpdate,
reinterpret_cast< void** >( &pMenuUp ) ) ) )
  {
   // 模块提供了菜单,获取菜单句柄
   if( FAILED( pMenuUp->GetMenu( &pStruct->m_hMenu ) ) )
    WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_CREATEMODULEMENU );
    pMenuUp->Release();
  }

  m_ModuleList.AddTail( pStruct );
 }
 pSite->Release();
 pEnum->Release();

 // 一个模块都不激活
 m_Selected = static_cast< ULONG >( -1 );

 ULONG count = m_ModuleList.GetCount();
 if( count )
 {
  // 获取模块的图标,并将其插入到模块工具条和菜单中
  m_wndToolBar.SetSizes( CSize( 23, 22 ), CSize( 16, 15 ) );
  if( !m_wndToolBar.SetButtons( NULL, count ) )
   WriteSoftErrorLog( __LINE__,__WFILE__,IDS_CREATETOOLBARBUTTON );
  else
  {
   // 将图标画到位图中
   CBitmap bitmap;
   CDC *pScreen = CDC::FromHandle( ::GetDC( NULL ) );
   CDC sdc;
   if( !bitmap.CreateCompatibleBitmap( pScreen,ICONWIDTH * count,ICONHEIGHT ) ||
!sdc.CreateCompatibleDC( pScreen ) )
   {
    WriteSoftErrorLog( __LINE__,__WFILE__,L"创建缓冲位图失败!" );
    return 0;
   }
   sdc.SelectObject( &bitmap );
   sdc.FillSolidRect( 0, 0, ICONWIDTH * count, ICONHEIGHT, RGB( 0xC0, 0xC0, 0xC0 ) );
   HICON hIcon = NULL;
   ULONG i = 0;
   POSITION pos = m_ModuleList.GetHeadPosition();
   CMenu *pMenu = GetMenu()->GetSubMenu(0)->GetSubMenu(0);
   ASSERT_VALID( pMenu );

   // 清空原来的占位符
   while( pMenu->DeleteMenu( 0, MF_BYPOSITION ) );

    while( pos )
    {
     pStruct = m_ModuleList.GetNext( pos );
     ASSERT( pStruct );

     // 将图标画到位图上
     if( SUCCEEDED( pStruct->m_pModule->GetIcon( &hIcon ) ) )
      ::DrawIconEx( sdc.GetSafeHdc(),i * ICONWIDTH,0,hIcon,ICONWIDTH,ICONHEIGHT,0,NULL,
DI_NORMAL );
     else
      WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_GETMODULEICON );

      // 添加菜单
      {
       // 获取模块的名字
       WCHAR *io = NULL;
       if( FAILED( pStruct->m_pModule->GetName( &io ) ) )
         WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_GETMODULENAME );
       else
       {
        if( !pMenu->AppendMenu( MF_STRING, ID_MODULE + i, io ) )
         WriteSoftErrorLog( __LINE__,__WFILE__,IDS_MAINFRM_CREATEMODULEMENU );
         ::CoTaskMemFree( io );
       }
      }

      // 设置工具条上的按钮
      m_wndToolBar.SetButtonInfo( i, ID_MODULE + i, TBBS_BUTTON, i );

      i++;
     }

     // 将位图设置到工具条中
     if( !m_wndToolBar.SetBitmap(static_cast< HBITMAP >( bitmap.Detach() ) ) )
       WriteSoftErrorLog( __LINE__,__WFILE__,IDS_SETTOOLBARBITMAP );
    }
  }
  g_theApp.EndWaitCursor();
  return 0;
 }

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章