五、示例程序 示例一、由 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()。(注6)  图三、快捷方式中的各种属性 #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 的开发工作啦,您老人家准备好了吗? 作业,留作业啦...... 1、你已经学会如何建立快捷方式了,那么你知道怎么读取它的属性吗?(如果写不出这个程序,那么你就不用继续学习了。因为......动点脑筋呀!我还没有见过象你这么笨的学生呢!) 2、示例程序三中使用了 IPicture 接口显示一个 JPG 图象。那么你现在去完成一个功能,把 JPG 文件转换为 BMP 文件。
注1:智能指针的概念和用法,后续介绍。 注2:IDL 文件,下回就要介绍啦。 注3:东北话,想干什么都可以,反正我不管啦。 注4:聚合,也许在第30回中介绍吧:-) 注5:持续性,IPersistXXXXXX是一个非常强大的接口家族,后续介绍。 注6:想知道 IShellLink、IPersistFile接口的所有函数吗?别愣着,快去看MSDN呀...... |