有了COM对象后,必须对浏览栏的CLSID进行注册。另外如果要与IE或资源管理器协调运行,还必须进行的恰当的组件种类(CATID_DeskBand)注册。这个工作由DllRegisterServer处理。实现代码如下:
注册表中的结构如下图:
1. 注册
STDAPI DllRegisterServer() { BOOL isSuccess = SdkDeskBandHelper::RegisterServer( g_hDllInst, CLSID_SdkDeskBand, L"Sampele Band"); if ( TRUE == isSuccess ) { // 注册类型 isSuccess = SdkDeskBandHelper::RegisterComCategory(CLSID_LyraDeskBand); } // 以下代码就是让Toolbars子菜单项中立即出现我们注册的Band对象菜单项 if ( TRUE == isSuccess ) { ITrayDeskBand *pTrayDeskBand = NULL; HRESULT hr = CoCreateInstance(CLSID_TrayDeskBand, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pTrayDeskBand)); if ( SUCCEEDED(hr) ) { pTrayDeskBand->DeskBandRegistrationChanged(); } SAFE_RELEASE(pTrayDeskBand); } return (TRUE == isSuccess) ? S_OK : E_FAIL; }
这个函数内部由两SdkDeskBandHelper::RegisterServer和SdkDeskBandHelper::RegisterComCategory两个方法实现。
BOOL SdkDeskBandHelper::RegisterServer( HINSTANCE hDlInstance, CLSID clsidCom, IN const WCHAR* pszDefValueText) { WCHAR *pszTempDefValueText = (NULL == pszDefValueText) ? L"" : pszDefValueText; WCHAR szClsid[MAX_PATH] = { 0 }; StringFromGUID2(clsidCom, szClsid, MAX_PATH); WCHAR szSubKey[MAX_PATH] = { 0 }; HRESULT hr = StringCchPrintf(szSubKey, MAX_PATH, L"CLSID\\%s", szClsid); HKEY hKey = NULL; LONG lResult = (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INVALID_FUNCTION; if ( ERROR_SUCCESS == lResult ) { lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); if ( ERROR_SUCCESS == lResult ) { // Set default value. lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)pszDefValueText, (DWORD)wcslen(pszTempDefValueText) * sizeof(WCHAR)); hr = (ERROR_SUCCESS == lResult) ? S_OK : E_FAIL; } RegCloseKey(hKey); } if ( ERROR_SUCCESS == lResult ) { StringCchPrintf(szSubKey, MAX_PATH, L"CLSID\\%s\\InprocServer32", szClsid); lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); if ( ERROR_SUCCESS == lResult ) { WCHAR szModuleFile[MAX_PATH] = { 0 }; GetModuleFileName(hDlInstance, szModuleFile, MAX_PATH); lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szModuleFile, (DWORD)wcslen(szModuleFile) * sizeof(WCHAR)); WCHAR const szModel[] = L"Apartment"; lResult = RegSetValueEx(hKey, L"ThreadingModel", 0, REG_SZ, (LPBYTE)szModel, sizeof(szModel)); } } return (ERROR_SUCCESS == lResult) ? TRUE : FALSE; } ////////////////////////////////////////////////////////////////////////// BOOL SdkDeskBandHelper::RegisterComCategory(CLSID clsidCom) { ICatRegister *pCatReg = NULL; HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pCatReg)); if ( SUCCEEDED(hr) ) { // 注册Band对象的类型 CATID catid[] = { CATID_DeskBand }; hr = pCatReg->RegisterClassImplCategories(clsidCom, 1, catid); } SAFE_RELEASE(pCatReg); return (SUCCEEDED(hr)) ? TRUE : FALSE; }
2. 反注册
STDAPI DllUnregisterServer()
{ // Hide the desk band window. CommonHelper::ShowDeskBand(FALSE); // Find handle to the task bar. HWND hTaskbarWnd = FindWindow(L"Shell_TrayWnd", NULL); // If task bar receives this message, // it will call CoFreeUnusedLibraries function // immediately to free unused libraries. PostMessage(hTaskbarWnd, WM_TIMER, 24, 0); return (TRUE == SdkDeskBandHelper::UnregisterServer(CLSID_SdkDeskBand)) ? S_OK : SELFREG_E_CLASS; }
其中SdkDeskBandHelper::UnregisterServer的实现如下:
BOOL SdkDeskBandHelper::UnregisterServer(CLSID clsidCom) { WCHAR szClsid[MAX_PATH] = { 0 }; StringFromGUID2(clsidCom, szClsid, MAX_PATH); WCHAR szSubKey[MAX_PATH] = { 0 }; StringCchPrintf(szSubKey, MAX_PATH, L"CLSID\\%s", szClsid); LONG lResult = RegDeleteTree(HKEY_CLASSES_ROOT, szSubKey); return (ERROR_SUCCESS == lResult) ? TRUE : FALSE; }