王朝网络
分享
 
 
 

活动桌面处理和一个例子

王朝vc·作者佚名  2006-01-17
宽屏版  字体: |||超大  

功能和用途

AddDesktopItem

添加一个桌面项。

AddDesktopItemWithUI

使用某个用户界面添加一个桌面项到活动桌面。

AddUrl

添加与指定的URL关联的桌面项。

ApplyChange

执行对活动桌面的修改。要使修改生效必须调用这个函数。用于激活或取消活动桌面。

GenerateDesktopItemHtml

产生包含给定桌面项的通用HTML页面。

GetDesktopItem

获得指定的桌面项。

GetDesktopItemByID

获得与给定ID匹配的桌面项。

GetDesktopItemBySource

用源URL获得某个桌面项。

GetDesktopItemCount

或的桌面项计数。

GetDesktopItemOptions

检查活动桌面是否打开或关闭。SHGetSettings 性能更佳。用于激活或取消活动桌面。

GetPattern

获取当前使用的式样。

GetWallpaper

获取当前使用的墙纸。仅用于活动桌面。标准模式时(桌面关闭),使用SystemParametersInfo。

GetWallpaperOptions

获得墙纸选项。仅用于活动桌面。标准模式时(桌面关闭),使用SystemParametersInfo。

ModifyDesktopItem

修改桌面项。

RemoveDesktopItem

从桌面删除指定的桌面项。

SetDesktopItemOptions

打开或关闭活动桌面。

SetPattern

设置活动桌面式样。

SetWallpaper

设置活动桌面墙纸。仅用于活动桌面。标准模式时(桌面关闭),使用SystemParametersInfo。

SetWallpaperOptions

设置墙纸选项。仅用于活动桌面。标准模式时(桌面关闭),使用SystemParametersInfo。

//

用IActiveDesktop可以添加和删除桌面项(HTML页面,图像,URLs或者ActiveX 控件),设置和获取墙纸(仅用于活动桌面,在标准模式时要用SystemParametersInfo函数)及其它有用功能。你可以用来打开或关闭活动桌面的函数是SetDesktopItemOptions。但首先要考虑——如何获得IActiveDesktop接口?用通常使用COM的方法创建一个实例:

//

IActiveDesktop* pAD;

HRESULT hr = ::CoCreateInstance(

CLSID_ActiveDesktop,

NULL, // 不支持聚合,也就是说没有外部Unknown

CLSCTX_INPROC_SERVER,

IID_IActiveDesktop,

(void**)&pAD);

//

不要忘了在启动代码中调用CoInitialize,如MFC应用的InitInstance函数。一旦你有了ActiveDesktop指针,便可以调用它的方法。

//

// 激活活动桌面

COMPONENTSOPT opt;

opt.dwSize = sizeof(opt);

opt.fActiveDesktop =

opt.fEnableComponents = TRUE;

HRESULT hr = pAD-SetDesktopItemOptions(&opt,0);

//

现在活动桌面应该被激活,但真是这样吗?当你第一次运行时,什么事情也没发生。怎么回事呢?经过检查,我发现之所以设置没有起作用是因为有个小细节在文档中没有说明——将设置应用到活动桌面:

//

pAD-ApplyChanges(AD_APPLY_REFRESH);

//

用完接口之后不要忘了释放(Release)它!(当然,你不应该使用原始的接口指针,应该用ATL智能指针——希望你正在使用它们)为了检查活动桌面是否打开或关闭,有一个对应的Get函数——GetDesktopItemOptions,它使用相同的COMPONENTSOPT结构。还有一个外壳函数做同样的事情:

//

// 活动桌面打开或关闭了吗?

SHELLFLAGSTATE shfs;

SHGetSettings(&shfs,SSF_DESKTOPHTML);

BOOL bADEnabled = shfs.fDesktopHTML;

//

不需要COM,CoCreateInstance,IActiveDesktop,或任何有关COM接口的东西。只要调用这个函数。你可以用SHGetSettings来检查一系列的外壳设置,下面列出了有关SHGetSettings使用的详细信息。这些设置或多或少与Windows

9x的资源管理器(参见图四)中“查看”=〉“文件夹选项”=〉“查看”标签中的选项对应。(Windows

2000有所不同,它是在“工具”=〉“文件夹选项”=〉“查看”标签中)可惜没用对应的SHSetSettings函数。

//

// 用SHGetSettings获得信息

// SHGetSettings 获得当前外壳设置

//

VOID SHGetSettings(

LPSHELLFLAGSTATE lpsfs, // 下列结构的地址

DWORD dwMask // 获取哪个信息(参见下面内容)

);

// SHGetSettings 填充下面的位域结构. 这些标志与Explorer的“查看”=〉“文件夹选项”=〉“查看”标签中的选项对应

//

typedef struct {

BOOL fShowAllObjects : 1; // 显示所有文件 (隐藏的或系统的)

BOOL fShowExtensions : 1; // 显示文件扩展名 (如 .txt)

BOOL fNoConfirmRecycle : 1; // 删除时不确认

BOOL fShowSysFiles : 1; // 显示文件的系统属性

BOOL fShowCompColor : 1;

BOOL fDoubleClickInWebView : 1; // 顾名思义

BOOL fDesktopHTML : 1; // 已打开活动桌面

BOOL fWin95Classic : 1; // 已打开Windows 95 "传统"视图

BOOL fDontPrettyPath : 1;

BOOL fShowAttribCol : 1;

BOOL fMapNetDrvBtn : 1; // 显示网络驱动器按钮

BOOL fShowInfoTip : 1; // 显示弹出式描述

BOOL fHideIcons : 1; //在活动桌面模式中隐藏图标

UINT fRestFlags : 3;

} SHELLFLAGSTATE;

// 这些标志被用于获取上面的这些域;如调用时使用:

dwMask =

// (SSF_DESKTOPHTML | SSF_WIN95CLASSIC) 来获取 fDesktopHTML 和

// fWin95Classic。

//

#define SSF_SHOWALLOBJECTS 0x00000001

#define SSF_SHOWEXTENSIONS 0x00000002

#define SSF_SHOWCOMPCOLOR 0x00000008

#define SSF_SHOWSYSFILES 0x00000020

#define SSF_DOUBLECLICKINWEBVIEW 0x00000080

#define SSF_SHOWATTRIBCOL 0x00000100

#define SSF_DESKTOPHTML 0x00000200

#define SSF_WIN95CLASSIC 0x00000400

#define SSF_DONTPRETTYPATH 0x00000800

#define SSF_SHOWINFOTIP 0x00002000

#define SSF_MAPNETDRVBUTTON 0x00001000

#define SSF_NOCONFIRMRECYCLE 0x00008000

#define SSF_HIDEICONS 0x00004000

图四 “查看”/“工具”

菜单 =〉“文件夹选项”=〉“查看”

现在我们知道由两种方法来检查是否活动桌面是否激活——SHGetSettings 和

IActiveDesktop::GetDesktopItemOptions,哪个方法好呢?这很重要吗?为了回答这个问题,让我们来探讨问题中的第二部分:如何断定用户激活或取消活动桌面,不论是从桌面菜单或者是从属性对话框(如图五)?

图五 选择活动桌面

当用户打开或关闭活动桌面时,Windows广播WM_SETTINGCHANGE消息给所有最上层窗口,消息值分别为:wParam = 0 和 lParam = "ShellState"。所以为了捕获这个事件,必须处理WM_SETTINGCHANGE消息。

//

// 最上层框架窗口!

void CMainFrame::OnSettingChange(UINT

uFlags, LPCTSTR pszSection)

{

if (lpszSection &&

_tcscmp(pszSection,_T("ShellState"))==0) {

// do what you want

}

CFrameWnd::OnSettingChange(uFlags,

pszSection);

}

//

WM_SETTINGCHANGE是个Windows的常用消息,当程序修改了SystemParametersInfo设置,则Windows就会广播此消息。但WM_SETTINGCHANGE也比较多地用在其它情形。

一般情况下,wParam/uFlags时0,lParam/pszSection是WIN.INI段名或被修改部分的注册表键(只是最终的键,而不是整个串)。事实上,WM_SETTINGCHANGE常被叫做WM_WININICHANGE,这两个符号在#define中的值也一样!当IActiveDesktop广播设置修改时,它将“ShellState”作为段名来传递,因为活动桌面设置被存储在一个注册表键中:

\HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellState

另外,如果你要广播自己修改的全程设置,也可以使用WM_SETTINGCHANGE。广播是应该使用SendMessageTimeout(HWND_BROADCAST, ...)函数。

图六 TestAD

为了整合所讲的内容,我编写了一个小程序:TestAD(如图六)。当TestAD获得

WM_SETTINGCHANGE时,便显示一条消息。利用我创建的一个类(CActiveDesktop)来获得并设置活动桌面的状态。为了使用这个类,你只要编写如下代码:

//

CActiveDesktop ad;

if (!ad.IsEnabled())

ad.Enable(TRUE);

//

CActiveDesktop隐藏了所有与COM有关的琐事。它使用ATL智能指针来保证接口处理的正确性和整体处理的自动化。如果你现在不使用CComQIPtr,那么赶快学会使用它,对于它的正确使用能使你获得健壮的,无错的COM代码,它非常有用。CActiveDesktop并没用封装所有的IActiveDesktop特性,只是封装了我编写TestAD所需要的功能。如果我什么时候想要编写一个Windows外壳时(我当然不会),再添加缺少的方法。但决定权在于你自己。CActiveDesktop非常简单,所以有关细节就请你参考源代码吧。

在实现CActiveDesktop和TestAD时,我遇到了一些意想不到的事情。首先是我在前面已经提到的在修改设置后要将它“应用”到(ApplyChanges)活动桌面的问题。其次是我发现了IActiveDesktop的同步bug问题。当我开始实现TestAD时,IActiveDesktop好像老是报告的错误状态。也就是说活动桌面真正打开的时候,它报告的是关闭,反之亦然。我以为是我的代码有问题,但当我细究后发现IActiveDesktop::GetDesktopItemOptions事实上在报告错误的状态信息!请看下面的分析:

//

TestAD 调用 CActiveDesktop::Enable(TRUE).

//

CActiveDesktop 调用 IActiveDesktop::SetDesktopItemOptions, 然后将修改应

用到活动桌面(ApplyChanges)。

//

ApplyChanges 向最上层窗口广播WM_SETTINGCHANGE 消息。

//

CMainFrame获得WM_SETTINGCHANGE,并调用IActiveDesktop::GetDesktopItemOptions

来获得开/关状态——但IActiveDesktop报告的状态仍然是关闭!

//

显然IActiveDesktop在广播完成之前没有更新其内部的状态。即GetDesktopItemOptions报告的是旧的开/关状态。碰到这种情况怎么办呢?我试图自己通过消息处理来修正这个问题,也就是在主窗口处理完WM_SETTINGCHANGE消息后添加“活动桌面开/关消息”。结果在TestAD程序中开/关活动桌面倒是没什么问题了,但当我用桌面上下文菜单的时候,又发生同样的问题。不用怀疑,肯定是当TestAD处理添加的消息时,Windows仍然在向下一个最上层窗口广播WM_SETTINGCHANGE消息。

怎么办?难道在显示状态信息前等待半秒钟?真臭。这时如果用SHGetSettings就没问题啦。实践证明,SHGetSettings报告的是正确的活动桌面开/关状态,即便GetDesktopItemOptions报告的是相反的状态——真让人高兴!很显然,ApplyChanges更新注册表是在广播WM_SETTINGCHANGE消息之前及在更新其内部状态之前——这是一件让人哭笑不得的事情。

现在我们应该可以明确回答前面提出的问题了:用哪个方法来获得活动桌面得开/关状态

好呢?好像SHGetSettings最接近正确答案。

最后祝弟兄们编程愉快!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有