一个体验好的Windows 任务栏缩略图开发心得

本文来自网易云社区

作者:孙有军


前言:

对于一个追求极致体验的软件来说,利用好系统的每一点优秀的特性,将会大大提高软件的品质。 Windows vista以来任务栏缩略图,及Win + TAB的程序切换预览图的定制也是对软件体验的一个巨大提升,这里我对云音乐中使用到的任务栏缩率图显示专辑封面,并且控制播放歌曲操作的开发做下简单的分享。


缩略图的显示图片和按钮定制:

Windows对缩略图的操作,主要会涉及到DWM (Desktop Window Manager 桌面窗口管理器)的相关知识,有兴趣的可以详细研究下。

1)打开缩略图显示图片的属性设置:

HRESULT WINAPI DwmSetWindowAttribute(
       HWND    hwnd,
       DWORD   dwAttribute,
  _In_ LPCVOID pvAttribute,
       DWORD   cbAttribute
);复制代码

指定窗口缩略图显示图片时必须打开该窗口的 DWMWA_HAS_ICONIC_BITMAP,DWMWA_FORCE_ICONIC_REPRESENTATION的属性设置,否则任务栏缩略图将无法生效。简单的示例代码:

BOOL switch= TRUE;
DwmSetWindowAttribute(hwnd, DWMWA_HAS_ICONIC_BITMAP,
&switch, sizeof(truth));
DwmSetWindowAttribute(hwnd, DWMWA_FORCE_ICONIC_REPRESENTATION,
&switch, sizeof(truth));
DWMWA_HAS_ICONIC_BITMAP表示窗口提供bitmap
DWMWA_FORCE_ICONIC_REPRESENTATION表示窗口强制使用bitmap展示缩略图。
复制代码

2)实际设置图片:

HRESULT WINAPI DwmSetIconicThumbnail(
  _In_ HWND    hwnd,
  _In_ HBITMAP hbmp,
  _In_ DWORD   dwSITFlags
);复制代码

可以指定任意的图片了。 但是要注意的是它是由图片大小限制的,一般是小于等于120*120 WM_DWMSENDICONICTHUMBNAIL 这个的窗口消息回调用会回调预览图片的大小的。

注意可能的问题:设置超过限制大小的图片就无法显示。但是WM_DWMSENDICONICTHUMBNAIL 这个回调并不会一开始就进行回调的,可能需要多次尝试,特别是win10的机器上,缩略图设置需要多次尝试

3)按钮定制:

缩略图上的按钮是通过获取COM组件 CLSID_TaskbarList得到ITaskbarList 实例 进行设置

taskbarlist->ThumbBarAddButtons(hwnd, btn_index, thumb_btn); taskbarlist ->ThumbBarUpdateButtons(hwnd, btn_index ,thumb_btn);

这样简单的缩略图预览就成型了:


然而文章到这里并未结束,当我们用win+tab切换程序时 你会看到切换动画里面的图片竟然就是一张图片, 让我们看看我们的程序有多么的突兀,如果在众多的窗口里面那么久显的更加怪异了:

之所以会造成这样的问题是指定使用图片进行开关的时候,系统会自动把设置的图片作为win+tab程序切换的预览图,并且通过修改其余的参数无法改正。

下面是解决的一种途径:


WIN+TAB 程序预览图定制:

原理是利用 ITaskbarList3可以注册 RegisterTab组成 tabgroup的方式,并且调整 SetTabOrder调整顺序。 win+tab会获取系统已显示的窗口预览图,任务栏显示的则是显示程序中设置。 具体的步骤是:

1. 创建一个窗口用于显示任务栏的缩略图和按钮自定义 hIconWindow,并且设置为隐藏

2. taskbar_list->RegisterTab( hIconWindow , hMainWindow); 注册为同一组(如果不隐藏的话,仍是显示两个任务栏图标)

3. taskbar_list->SetTabOrder( hIconWindow, hMainWindow ); 设置tab的顺序, 任务栏预览图是那组内第一个窗口的设置的预览图的, 如果顺序不调整的话,将会出现不可测的情况

4. 设置窗口任务栏缩略图是设置在 hIconWindow上

那么就完成了现在这种效果


个人感觉比之前的好多了。

可能的问题当窗口都隐藏是,再显示缩略图窗口的一些按钮会丢失,需要重新进行设置


后记:

实现以上方式,可能有多重途径,欢迎探讨或者指出错误



网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区


相关文章:
【推荐】 流式断言器AssertJ介绍
【推荐】 从互联网+角度看云计算的现状与未来
【推荐】 Android 模拟器下载、编译及调试


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
效果图:音乐播放控制按钮 教程开始: 实现方法在微软的帮助文档中,我发不了链接(百度关键词 任务栏扩展 MSDN) 文档中提供了3三个API:ThumbBarAddButtons(创建按钮)、 ThumbBarSetImageList、 ThumbBarUpdateButtons(更新按钮) 这三个API在动态链接库 Explorerframe.dll 中,我尝试过直接调用它们,结果却不存在。 不过MSDN中提供了C++的调用方法,在C++中这三个API被封装在 ITaskBarList3 类中,ITaskBarList3类定义在“ Shobjidl.h ”头文件 所以我想想到个方法,利用微软提供的C++代码编写一个DLL库来实现这三个方法,让易语言程序调用。 接下来我编写了 TaskBarEx.dll 这个链接库(C++源码在最下面),里面提供了 AddThumbarButtons 这个方法,方法易语言定义如下: 复制代码 .版本 2 .DLL命令 AddThumbarButtons, 整数型, "TaskBarEx", "_AddThumbarButtons@12", 公开 .参数 句柄, 整数型 .参数 sum, 整数型 .参数 pTHUMBBUTTON, THUMBBUTTON, 数组 这个链接库的代码都是MSDN中现成的,从微软的帮助文档复制过来,稍加修改就行了。 你们以为这样就结束了! 当我在易语言中声明此API调用后,才发现并没有什么卵用,我也不知道为什么。后面才知道微软提供的这三个API是用COM对象的方式调用的。于是 我在论坛中找了一大堆关于如何调用COM对象的教程,完全看不懂! 当然!什么事情都是有解决的办法的,最终我还是找到办法了,以下方法是我乱搞搞出来的。 我在易语言中创建了一个“对象”类型的变量(用来调用COM对象的)取名: ITAskBarList3并创建了 ITAskBarList3类的COM对象 复制代码 ITAskBarList3.创建 (“{56FDF344-FD6D-11d0-958A-006097C9A090}”, ) 代码中那一串文本是COM对象的唯一标识符,我在VS2017中 ITAskBarList3类的声明中找得到。定义在“ Shobjidl.h ”头文件中。 然后声明了一个THUMBBUTTON 结构(见MSDN),定义按钮的信息: 复制代码 .版本 2 ' 按钮1 Button.hIcon = LoadIconA (mHwnd, 112)' 112为“上一首按钮”的图标在TaskBarEx.dll链接库的资源编号 Button.dwMask = 位或 (2, 4, 8)' 表示你准备使用THUMBBUTTON结构中的哪些成员 Button.iId = 0' 按钮的编号,用于在窗口的消息循环中的WM_COMMAND消息下判断是哪个按钮 Button.dwFlags = 0' 表示按钮状态,可用还是禁用,0表示可用 wtext = Ansi转Unicode (“上一首”)' 按钮提示文本需要Unicode类型 toBytes (Button.szTip, wtext, 取字节集长度 (wtext)) 加入成员 (sButton, Button)' 声明好一个按钮结构就加sButton数组 最后调用TaskBarEx.dll中我提供的AddThumbarButtons函数 复制代码 AddThumbarButtons (窗口句柄, 1, sButton) 以上就是创建一个缩略图按钮的基本代码。下面还有一些问题: 以下是MSDN的原话: 注意 当应用程序显示窗口时,系统会创建其任务栏按钮。当按钮就位时,任务栏会向窗口发送TaskbarButtonCreated消息。它的值通过调用RegisterWindowMessage(L(“TaskbarButtonCreated”))计算。该消息必须在应用程序调用任何ITaskbarList3方法之前接收。 意思就是创建按钮的所有代码都在TaskbarButtonCreated消息之后,并且这个消息值需要我们调用API自己注册。我做过测试,发现要想在窗口创建完成后创建按钮,就必须这样做;如果将创建按钮代码放在 __按钮__被按下事件 下就不一定,不知道为什么。 教程结束 当然还有一些细节问题需要处理,在我的源码中都有注释,可以看看。如果代码看不懂可以问我,不过关于COM对象的问题我也不懂。 TaskBarEx.dll的源代码:整个VC++工程目录100多MB,无语了,如果需要我后面再发;下面两个主要函数代码,其实MSDN都有。 我用的是VS2017 EXTERN_C __declspec(dllexport) int _stdcall eG
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值