对于一个DeskBand来说,它应该是一个DLL,也是一个COM对象,它是由explorer来调用的。对于DLL来说,它有几个函数,相当重要,本文对这几个函数作一个简单说明。
1,DllMain
2,DllGetClassObject
3,DllCanUnloadNow
4,DllRegisterServer
5,DllUnregisterServer
其中函数2—5是需要导出的,作为该DLL与客户端通信的接口。
下面对这5个函数作个说明。
1,DllMain
注意,这个函数通常中做进程或线程的初始化和清除操作,当你的DllMain函数执行时,同一个地址空间中的其他DLL可能尚未执行它们的DllMain函数,这意味着它们尚未初始,因此你应该避免调用从其他DLL中输出的函数。此外,你应该避免从DllMain内部调用LoadLibrary和FreeLibrary函数,因为这些函数会形成一个依赖性循环。
2,DllGetClassObject
这个函数相当重要,它必须是一个输出函数。它用于创建类工厂,在类工厂里面创建自定义的COM对象。不要直接调用这个函数。请看它的实现:
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{
DeskBand 实现4(四个函数)_LeeHong
// CLSID_SdkDeskBand这个就是自定义COM的CLSID
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
if ( TRUE == IsEqualCLSID(rclsid, CLSID_SdkDeskBand) )
{
hr = E_OUTOFMEMORY; // 这就是我们自己实现类工厂,它可创建出我们自大定义的COM对象
SdkClassFactory *pClassFactory = new SdkClassFactory();
if ( NULL != pClassFactory )
{
hr = pClassFactory->QueryInterface(riid, ppv);
}
SAFE_RELEASE(pClassFactory);
}return hr;
}
3,DllCanUnloadNow
这个函数告诉OS是否可以卸载该DLL,它一般实现比较简单,也可以作一些清除操作,如果关闭一些全局句柄,写一个LOG等。
STDAPI DllCanUnloadNow()
{ // g_lDllRefCount是当前DLL的引用计数,如果这个变量值为0的话,说明可以卸载该DLL,否则不可以。
return (g_lDllRefCount > 0) ? S_FALSE : S_OK;
}
4,DllRegisterServer
当该DLL注册时,就会调用这个函数,典型的就是用regsvr32命令注册DLL时,它就会调用该函数,一般在这个函数里央就可以来注册了,比如写一些注册表,注册当前DLL的类型等。
5,DllUnregisterServer
当用regsvr32 /u来卸载该DLL时会调用这个方法,在这个方法里面,要做的就是在注册表中删除写入的值。当这个函数调用后,一般DLL还不能立马被删除,OS会有一个轮循机制,大概要等一段时间,这个DLL就可以删除掉了。为了能够马上删除它,可以在这个函数里加入如下代码:
// Find handle to the task bar.
// hTaskbarWnd是Desk Band对象的容器
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);