科技行者

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

知识库

知识库 安全导航

至顶网软件频道基础软件COM 组件设计与应用之简单调用组件

COM 组件设计与应用之简单调用组件

  • 扫一扫
    分享文章到微信

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

在第三回中,大家用“小本本”记录了一个原则:COM 组件是运行在分布式环境中的。

作者:杨老师 来源:vckbase 2007年10月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
示例程序

  示例一、由 CLSID 得到 ProgID。(程序以 word 为例子。如果运行不正确,嘿嘿,你没有安装 word 吧?)
 ::CoInitialize( NULL ); 

 HRESULT hr; 
 // {000209FF-0000-0000-C000-000000000046} = word.application.9 
 CLSID clsid = {0x209ff,0,0,{0xc0,0,0,0,0,0,0,0x46}}; 
 LPOLESTR lpwProgID = NULL; 
  
 hr = ::ProgIDFromCLSID( clsid, &lpwProgID ); 
 if ( SUCCEEDED(hr) ) 
 { 
  ::MessageBoxW( NULL, lpwProgID, L"ProgID", MB_OK ); 

  IMalloc * pMalloc = NULL; 
  hr = ::CoGetMalloc( 1, &pMalloc );  // 取得 IMalloc 
  if ( SUCCEEDED(hr) ) 
  { 
   pMalloc->Free( lpwProgID );  // 释放ProgID内存 
   pMalloc->Release();          // 释放IMalloc 
  } 
 } 

 ::CoUninitialize();
  示例二、如何使用“浏览文件夹”选择对话窗。
CString BrowseFolder(HWND hWnd, LPCTSTR lpTitle) 
{ 
    // 调用 SHBrowseForFolder 取得目录(文件夹)名称 
    // 参数 hWnd: 父窗口句柄 
    // 参数 lpTitle: 窗口标题 
     
    char szPath[MAX_PATH]={0}; 
    BROWSEINFO m_bi; 

    m_bi.ulFlags = BIF_RETURNONLYFSDIRS  | BIF_STATUSTEXT; 
    m_bi.hwndOwner = hWnd; 
    m_bi.pidlRoot = NULL; 
    m_bi.lpszTitle = lpTitle; 
    m_bi.lpfn = NULL; 
    m_bi.lParam = NULL; 
    m_bi.pszDisplayName = szPath; 

    LPITEMIDLIST pidl = ::SHBrowseForFolder( &m_bi ); 
    if ( pidl ) 
    { 
        if( !::SHGetPathFromIDList ( pidl, szPath ) )  szPath[0]=0; 

        IMalloc * pMalloc = NULL; 
        if ( SUCCEEDED ( ::SHGetMalloc( &pMalloc ) ) )  // 取得IMalloc分配器接口 
        { 
            pMalloc->Free( pidl );    // 释放内存 
            pMalloc->Release();       // 释放接口 
        } 
    } 
    return szPath; 
}
  示例三、在窗口中显示一幅 JPG 图象。
void CxxxView::OnDraw(CDC* pDC) 
{ 
 ::CoInitialize(NULL);  // COM 初始化 
 HRESULT hr; 
 CFile file; 
  
 file.Open( "c:\\aa.jpg", CFile::modeRead | CFile::shareDenyNone );  // 读入文件内容 
 DWORD dwSize = file.GetLength(); 
 HGLOBAL hMem = ::GlobalAlloc( GMEM_MOVEABLE, dwSize ); 
 LPVOID lpBuf = ::GlobalLock( hMem ); 
 file.ReadHuge( lpBuf, dwSize ); 
 file.Close(); 
 ::GlobalUnlock( hMem ); 

 IStream * pStream = NULL; 
 IPicture * pPicture = NULL; 
  
 // 由 HGLOBAL 得到 IStream,参数 TRUE 表示释放 IStream 的同时,释放内存 
 hr = ::CreateStreamOnHGlobal( hMem, TRUE, &pStream ); 
 ASSERT ( SUCCEEDED(hr) ); 
  
 hr = ::OleLoadPicture( pStream, dwSize, TRUE, IID_IPicture, ( LPVOID * )&pPicture ); 
 ASSERT(hr==S_OK); 
  
 long nWidth,nHeight;  // 宽高,MM_HIMETRIC 模式,单位是0.01毫米 
 pPicture->get_Width( &nWidth );    // 宽 
 pPicture->get_Height( &nHeight );  // 高 
  
 ////////原大显示////// 
 CSize sz( nWidth, nHeight ); 
 pDC->HIMETRICtoDP( &sz );  // 转换 MM_HIMETRIC 模式单位为 MM_TEXT 像素单位 
 pPicture->Render(pDC->m_hDC,0,0,sz.cx,sz.cy, 
  0,nHeight,nWidth,-nHeight,NULL); 
   
 ////////按窗口尺寸显示//////// 
// CRect rect; GetClientRect(&rect); 
// pPicture->Render(pDC->m_hDC,0,0,rect.Width(),rect.Height(), 
//  0,nHeight,nWidth,-nHeight,NULL); 

 if ( pPicture ) pPicture->Release();// 释放 IPicture 指针 
 if ( pStream ) pStream->Release();  // 释放 IStream 指针,同时释放了 hMem 
  
 ::CoUninitialize(); 
}
  示例四、在桌面建立快捷方式

  在阅读代码之前,先看一下关于“快捷方式”组件的结构示意图。

 
图二、快捷方式组件的接口结构示意图



  从结构图中可以看出,“快捷方式”组件(CLSID_ShellLink),有3个(其实不止)接口,每个接口完成一组相关功能的函数。IShellLink 接口(IID_IShellLink)提供快捷方式的参数读写功能(见图三),IPersistFile 接口(IID_IPersistFile)提供快捷方式持续性文件的读写功能。对象的持续性(注5),是一个非常常用,并且功能强大的接口家族。但今天,我们只要了解其中两函数,就可以了:IPersistFile::Save()和IPersistFile:Load()。



 
图三、快捷方式中的各种属性
#include < atlconv.h > 
void CreateShortcut(LPCTSTR lpszExe, LPCTSTR lpszLnk) 
{ 
 // 建立块捷方式 
 // 参数 lpszExe: EXE 文件全路径名 
 // 参数 lpszLnk: 快捷方式文件全路径名 
  
 ::CoInitialize( NULL ); 

 IShellLink * psl = NULL; 
 IPersistFile * ppf = NULL; 

 HRESULT hr = ::CoCreateInstance(  // 启动组件 
  CLSID_ShellLink,      // 快捷方式 CLSID 
  NULL,                 // 聚合用(注4) 
  CLSCTX_INPROC_SERVER, // 进程内(Shell32.dll)服务 
  IID_IShellLink,       // IShellLink 的 IID 
  (LPVOID *)&psl );     // 得到接口指针 

 if ( SUCCEEDED(hr) ) 
 { 
  psl->SetPath( lpszExe );  // 全路径程序名 
//  psl->SetArguments();      // 命令行参数 
//  psl->SetDescription();    // 备注 
//  psl->SetHotkey();         // 快捷键 
//  psl->SetIconLocation();   // 图标 
//  psl->SetShowCmd();        // 窗口尺寸 
   
  // 根据 EXE 的文件名,得到目录名 
  TCHAR szWorkPath[ MAX_PATH ]; 
  ::lstrcpy( szWorkPath, lpszExe ); 
  LPTSTR lp = szWorkPath; 
  while( *lp )    lp++; 
  while( ’’\\’’ != *lp )    lp--; 
  *lp=0; 

  // 设置 EXE 程序的默认工作目录 
  psl->SetWorkingDirectory( szWorkPath ); 

  hr = psl->QueryInterface(  // 查找持续性文件接口指针 
   IID_IPersistFile,      // 持续性接口 IID 
   (LPVOID *)&ppf );      // 得到接口指针 

  if ( SUCCEEDED(hr) ) 
  { 
   USES_CONVERSION;       // 转换为 UNICODE 字符串 
   ppf->Save( T2COLE( lpszLnk ), TRUE );  // 保存 
  } 
 } 
 if ( ppf ) ppf->Release(); 
 if ( psl ) psl->Release(); 

 ::CoUninitialize(); 
} 

void OnXXX() 
{ 
 CreateShortcut( 
  _T("c:\\winnt\\notepad.exe"),  // 记事本程序。注意,你的系统是否也是这个目录? 
  _T("c:\\Documents and Settings\\Administrator\\桌面\\我的记事本.lnk") 
 ); 
 // 桌面上建立快捷方式(lnk)文件的全路径名。注意,你的系统是否也是这个目录? 
 // 如果用程序实现寻找桌面的路径,则可以查注册表 
 // HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders 
} 

  小结


  本回介绍的内容比较实用。大家不要只抄袭代码,而一定要理解它。结合 MSDN 的说明去思索代码、理解其含义。好了,想方设法把代码忘掉!三天后(如过你还没有忘记,那就再过三天),你在不参考示例代码,但可以随便翻阅 MSDN 的情况下,自己能独立地再次完成这四个例程,那么恭喜你,你已经入门了:0) 从下回开始,我们要用 ATL 做 COM 的开发工作啦,您老人家准备好了吗?

查看本文来源

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

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

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