Windows 7程序开发系列之二(JumpList篇1 - User Task)
来源:互联网 发布:java json转化为数组 编辑:程序博客网 时间:2024/06/07 11:45
相对于上一篇中任务栏特性的开发,JumpList的开发显得稍微麻烦一些。JumpList将分为两次讲解,这次先讲解如何添加用户任务(User Task)。同样以foobar2000为例,当右键点击任务栏按钮时,显示程序的JumpList。
最下方3个项目为系统任务,一般不需要我们去操作。上方的两个任务:播放、参数选项,即为自定义的用户任务。用户任务本质上是一个快捷方式,对应于程序中由IShellLink接口表示。
一、ICustomDestinationList接口
同样先创建一个窗口,然后添加一个CreateJumpList方法,在这个方法中创建JumpList。创建JumpList需要几个步骤:1、创建ICustomDestinationList接口,这个接口对应的就是JumpList。2、调用BeginList方法。3、创建IObjectCollection接口。4、向IObjectCollection中添加快捷方式。5、由IObjectCollection接口取得IObjectArray接口。6、将IObjectArray加入ICustomDestinationList。7、调用CommitList方法。在CreateJumpList方法中加入下面代码:
二、IShellLink接口
上面的代码还不能编译,AddShellLink方法还没有编写。这个方法用于在IObjectCollection中加入一个IShellLink对象。IShellLink接口有几个方法用于设置属性:1、SetPath:设置目标的路径。2、SetWorkingDirectory设置工作目录。3、SetIconLocation设置图标。4、SetArguments设置命令行参数。5、设置标题(这一步稍微复杂一点、在独立的方法中设置)。设置完属性后,调用IObjectCollection的AddObject方法,将快捷方式加入。
SetTitle方法用于设置标题,由于IShellLink接口本身不带有设置标题的方法。因此需要用到另一个接口IPropertyStore来设置标题。首先由IShellLink接口得到IPropertyStore接口,然后由字符串初始化一个PROPVARIANT对象,接下来将该PROPVARIANT对象设置为标题,最后提交。
上面的例子将目标路径设置为记事本的路径,并且加上命令行参数"Test.txt",当点击后,将调用记事本并传入参数"Test.txt"。
三、由当前程序实例响应用户任务
现在问题的是,在大多数情况下,用户任务应该不仅仅对应的是一个指向某个程序的快捷方式,而是应该对应的是当前程序的某个功能。比如在foobar2000中的参数选项,对应着程序中的功能。而且当选择这个用户任务的时候,应该是由当前程序的当前实例来响应这个操作,而不是由新的实例来完成这个操作。接下来要做的就是如何将用户任务反映到当前程序实例中。
这里涉及到两个问题。第一个问题是,程序必须是单实例应用程序,因为当点击用户任务时,我们不能由新的程序实例来响应。解决办法是当程序启动时,检查该程序是否已有先前实例在运行,如果有,则退出,防止第二个实例运行。第二个问题是,我们的用户任务实际是通过快捷方式传递给程序的参数来反映的。而这个参数只有第二个实例能够收到。那么在第二个实例退出之前,要想办法把参数传递到第一个实例。
我们先把之前创建的用户任务改为指向自己。修改AddShellLink方法如下,其中注释的地方即为修改过的地方:
现在的情况是,当我们点击User Task 1时,一个新的实例启动了。接下来就来解决上面提到的问题。
第一个问题的解决方法是使用Mutex(互斥量)。当第一个实例启动时,创建一个互斥量。当第二个实例启动时,同样创建这个互斥量。由于该互斥量已经创建,所以必然导致失败,第二个实例退出。当第一个实例结束的时候,撤销该互斥量。在WinMain函数的开头加上下面代码:
WinMain函数的结尾加上下面代码:
这次当我们点击User Task 1时已经看不见新的实例启动了(实际上新的实例仍然启动了,只不过检测到先前实例后,迅速退出了)。
第二个问题是如何将参数传递到第一个实例。对于Windows程序来说,最容易想到的就是通过消息发送了。但又如何得到先前实例的主窗口句柄呢?这里要用到内存映射文件(Memory Mapped File)。第一个实例运行后,将自己的主窗口句柄放入到一个内存映射文件中,第二个实例从该内存映射文件中读出先前实例的主窗口句柄。在窗口创建之后加入下面代码,将当前主窗口句柄放入内存映射文件:
该内存映射文件的名字不要和之前Mutex的名字相同,否则会创建失败。在程序退出之前要关闭文件:
在WinMain函数开头,检测到有先前实例运行之后。从这个内存映射文件读入先前实例的主窗口句柄:
得到先前实例的窗口句柄后,利用WM_COPYDATA消息,将命令行参数发送到先前实例。
然后加入对WM_COPYDATA消息的处理:
在HandleCmdLine中,我们只简单显示一条消息即可:
验证一下现在的效果:
因为JumpList即使在程序没有运行时也是存在的,所以我们在窗口创建之后也要调用一次HandleCmdLine方法,以使第一个程序实例可以响应静止状态下的用户点击。如下面的效果:
此时程序未运行,只是锁定到任务栏,点击JumpList上的用户任务,第一个程序实例启动,并响应用户任务
为了简化问题,上面的代码中省去了很多错误处理。在实际的使用中,我将单实例运行与实例间的数据传递封装在了一个辅助的类中,源代码中将会提供这个类。
上面代码需要包含的头文件:
需要连接的库:shlwapi.lib
本节源代码下载
- Windows 7程序开发系列之二(JumpList篇1 - User Task)
- Windows 7程序开发系列之二(JumpList篇1 - User Task)
- Windows 7程序开发系列之二(JumpList篇1 - User Task)
- Windows 7程序开发系列之二(JumpList篇2 - Destination)
- Windows 7程序开发系列之二(JumpList篇2 - Destination)
- Windows 7程序开发系列之二(JumpList篇2 - Destination)
- Windows 7程序开发系列 任务栏篇
- Windows 7程序开发系列之一(任务栏篇)
- Windows 7程序开发系列之一(任务栏篇)
- Windows 7程序开发系列之一(任务栏篇)
- Windows 7程序开发系列之一(任务栏篇)
- Windows 7程序开发系列之一(任务栏篇)
- JBoss 系列四十七:jBPM5示例之 User Task
- windows 7 内核程序开发二之数据结构
- .NET 4 并行(多核)编程系列之二 从Task开始
- 【Windows Mobile开发系列 之 开始二】使用VS2008进行Windows Mobile开发环境的搭建
- Windows Mobile开发系列 之 开始二】使用VS2008进行Windows Mobile开发环境的搭建
- IOS开发模块总结(二)后台运行程序(2)Task completion-UIBackgroundTaskIdentifier
- C#实现windowsfrom界面美化
- 计算机开发技术的发展
- 删除文件到回收站
- 动态内容缓存
- 成为一名优秀的程序员/第一份工作
- Windows 7程序开发系列之二(JumpList篇1 - User Task)
- 十款最热门最流行的开发框架横向比对
- 用VMWARE7安装MAC OS虚拟机
- 交换和路由上的二层三层特征
- Winsock2中WSAAsynSelect()模型各种事件的触发条件
- 剪切板API函数介绍
- Parser Error Message: Could not load file or assembly 'Telerik.Web.UI' or one of its dependencies.解决方法
- Productivity Hacks
- javascript实现自动求和