加载中
加载中
表情图片
评为精选
鼓励
加载中...
分享
加载中...
文件下载
加载中...
修改排序
加载中...
VC/MFC实用任务栏编程
acmilan2015/05/28软件综合 IP:四川
一、闪动任务栏,提醒用户该窗口需要操作
这个很简单,直接在需要提醒用户的地方加入这一句就好了:
Kotlin
this->FlashWindowEx(FLASHW_TRAY | FLASHW_TIMERNOFG, 0, 0); // 仅任务栏,闪烁直到窗口激活,默认频率
CWnd::FlashWindowEx第一个参数是闪动方式:
FLASHW_CAPTION 闪动标题栏
FLASHW_TRAY 闪动任务栏
FLASHW_ALL 闪烁标题栏和任务栏
FLASHW_STOP 停止闪烁
FLASHW_TIMER 一直闪烁,直到FLASHW_STOP
FLASHW_TIMERNOFG 一直闪烁,直到窗口被切换到前台
第二个参数是闪烁次数,第三个参数是闪烁间隔毫秒数,这里都写0。
效果: 捕获6.png

二、在任务栏显示进度(Win7)
Windows 7 中带来了超级任务栏,其中一个功能便是显示进度,它在Visual C++中可以利用ITaskbarList3实现。它是一个COM组件,需要手工创建。通常在"TaskbarButtonCreated"这个注册消息(任务栏按钮创建完毕)中实例化。
在Visual C++ 2010中的CFrameWnd中已经集成了这个功能,直接调用SetProgressValue和SetProgressState就可以了,但是对话框CDialog或CDialogEx仍然不能这么做。如果你使用的是Visual Studio 2008或以前的版本,那么需要安装Windows 7 SDK,或者手工移植ITaskbarList3。
首先在对话框的类声明里加入以下几句:
Other
CComQIPtr<itaskbarlist3> m_tbl; // 任务栏:ITaskBarList3实例指针 LRESULT OnTaskbarButtonCreated(WPARAM wParam, LPARAM lParam); // 任务栏:"TaskbarButtonCreated"消息</itaskbarlist3>
然后修改对话框的CPP文件:
Other
const UINT WM_TASKBAR_BUTTON_CREATED = RegisterWindowMessage("TaskbarButtonCreated"); // 任务栏:注册消息 BEGIN_MESSAGE_MAP(CTaskBarTestDlg, CDialog)     // ... 其它消息映射 ...     ON_REGISTERED_MESSAGE(WM_TASKBAR_BUTTON_CREATED, OnTaskbarButtonCreated) // 任务栏:映射消息 END_MESSAGE_MAP()
为消息映射添加代码:
Other
LRESULT CTaskBarTestDlg::OnTaskbarButtonCreated(WPARAM wParam, LPARAM lParam) // 任务栏图标创建时:ITaskBarList3实例化COM对象 {     // RegisterWindowsMessage("TaskbarButtonCreated") 注册的消息,ON_REGISTERED_MESSAGE(msg, fn) 登记                                // 在任务栏按钮创建完毕时,"TaskbarButtonCreated"会被触发,     // 这个时候就可以实例化ITaskbarList3对象了                                m_tbl.Release(); // 如果有的话,释放以前的                                m_tbl.CoCreateInstance(CLSID_TaskbarList); // 任务栏:构造ITaskbarList3类型COM对象                                return TRUE; }
最后添加WM_DESTROY消息映射,释放ITaskbarList3实例(因为MFC在对话框析构之前调用了CoUninitialize(),不及时释放会崩溃):
C++
void CTaskBarTestDlg::OnDestroy() // 窗口销毁时:ITaskBarList3析构COM对象 {     CDialog::OnDestroy();                                m_tbl.Release(); // 任务栏:析构COM对象(必须在调用CoUnintialize()之前,不能等待CComQIPtr析构函数,否则会崩溃) }
这样,我们就可以使用m_tbl的成员函数SetProgressValue和SetProgressState来在任务栏显示进度了:
Other
void CTaskBarTestDlg::OnBnClickedSetProgress() {     UpdateData(true);                                if (m_tbl != NULL) {         m_tbl->SetProgressValue(m_hWnd, m_slider, 100); // 设置任务栏进度     } }                            void CTaskBarTestDlg::OnBnClickedButton1() {     if (m_tbl != NULL) {         m_tbl->SetProgressState(m_hWnd, TBPF_NORMAL); // 设置任务栏进度状态:正常 - 绿色     } }                            void CTaskBarTestDlg::OnBnClickedButton2() {     if (m_tbl != NULL) {         m_tbl->SetProgressState(m_hWnd, TBPF_ERROR); // 设置任务栏进度状态:错误 - 红色     } }                            void CTaskBarTestDlg::OnBnClickedButton3() {     if (m_tbl != NULL) {         m_tbl->SetProgressState(m_hWnd, TBPF_PAUSED); // 设置任务栏进度状态:暂停 - 黄色     } }                            void CTaskBarTestDlg::OnBnClickedButton4() {     if (m_tbl != NULL) {         m_tbl->SetProgressState(m_hWnd, TBPF_INDETERMINATE); // 设置任务栏进度状态:不确定 - 绿色滚动     } }                            void CTaskBarTestDlg::OnBnClickedButton5() {     if (m_tbl != NULL) {         m_tbl->SetProgressState(m_hWnd, TBPF_NOPROGRESS); // 设置任务栏进度状态:清除进度     } }
效果:
1. 正常 - 绿色
捕获1.png
2. 错误 - 红色
捕获2.png
3. 暂停 - 黄色
捕获3.png
4. 不确定 - 绿色滚动
捕获4.png
5. 清除进度
捕获5.png

三、在通知区域显示图标
这是一个烂大街的老技术了,但是还是很实用的。操作通知区域图标一般使用Shell_NotifyIcon()函数,该函数需要两个参数,第一个参数是操作命令,第二个参数是一个NOTIFYICONDATA结构。
第一个参数的常用取值:
NIM_ADD 添加图标
NIM_DELETE 删除图标
NIM_MODIFY 修改图标参数
结构体NOTIFYICONDATA的成员:
cbSize 结构体大小(用sizeof获得)
hWnd 窗口句柄
uID 通知区域图标ID
uFlags 表明具体哪些其他成员为合法数据,有NIF_ICON、NIF_MESSAGE、NIF_TIP、NIF_STATE、NIF_INFO、NIF_GUID等,在这里我们只用到NIF_ICON、NIF_MESSAGE、NIF_TIP三个标志。
NIF_ICON代表成员:hIcon表示要显示的图标句柄
NIF_MESSAGE代表成员:uCallbackMessage表示鼠标点击图标触发的消息(可自定义消息,通常定义为WM_USER+x)
NIF_TIP代表成员:szTip表示鼠标悬停在图标上显式的提示文字
由于explorer崩溃以后系统不会储存图标,因此需要程序捕捉explorer崩溃重启,手动重建图标,方法是捕获"TaskbarCreated"注册消息。
创建图标的代码:
C++
// 自定义图标消息 #define WM_ICON_MESSAGE (WM_USER + 100)              void CTaskBarTestDlg::OnBnClickedShowTray() {     NOTIFYICONDATA tnd;                            tnd.cbSize = sizeof(NOTIFYICONDATA); // 自身大小                            // 窗口句柄     tnd.hWnd = this->m_hWnd;                            // 通知图标ID     tnd.uID = IDR_MAINFRAME;                                // 标志位:消息 + 图标 + 工具提示     tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;                            // 消息     tnd.uCallbackMessage = WM_ICON_MESSAGE;                            // 图标     tnd.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));                            // 提示     strcpy(tnd.szTip,"测试程序");                            Shell_NotifyIcon(NIM_ADD, &tnd); // 添加图标                            m_is_icon_show = true; }
删除图标的代码:
Other
void CTaskBarTestDlg::OnBnClickedHideTray() {     NOTIFYICONDATA tnid;                                tnid.cbSize = sizeof(NOTIFYICONDATA);     tnid.hWnd = this->m_hWnd;     tnid.uID = IDR_MAINFRAME;     tnid.uFlags = NULL;                            Shell_NotifyIcon(NIM_DELETE, &tnid); // 删除图标                            m_is_icon_show = false; }
explorer崩溃重建图标:
Other
const UINT WM_TASKBAR_CREATED = RegisterWindowMessage("TaskbarCreated"); // 通知图标:注册消息 BEGIN_MESSAGE_MAP(CTaskBarTestDlg, CDialog)     // ... 其它消息映射 ...     ON_REGISTERED_MESSAGE(WM_TASKBAR_CREATED, OnTaskbarCreated) // 通知图标:映射消息 END_MESSAGE_MAP()              // ... 其它代码 ...              LRESULT CTaskBarTestDlg::OnTaskbarCreated(WPARAM wParam, LPARAM lParam) // 当explorer崩溃时重建图标 {     // RegisterWindowsMessage("TaskbarCreated") 注册的消息,ON_REGISTERED_MESSAGE(msg, fn) 登记     if (m_is_icon_show)         OnBnClickedShowTray();     return TRUE; }
图标点击消息:
Other
BEGIN_MESSAGE_MAP(CTaskBarTestDlg, CDialog)     // ... 其它消息映射 ...     ON_MESSAGE(WM_ICON_MESSAGE, OnIconMessage) // 通知图标:映射消息 END_MESSAGE_MAP()    // ... 其它代码 ...    LRESULT CTaskBarTestDlg::OnIconMessage(WPARAM wParam, LPARAM lParam) // 自定义的通知图标消息WM_ICON_MESSAGE {     // #define WM_ICON_MESSAGE (WM_USER + 100) 定义的消息,ON_MESSAGE(msg, fn) 登记     UINT uID = (UINT) wParam;     UINT uMouseMsg = (UINT) lParam;                              if (uID = IDR_MAINFRAME) {                              switch (uMouseMsg) {                                  case WM_LBUTTONDBLCLK: // 双击时:显示窗口并隐藏图标                                      this->SetForegroundWindow();                 this->ShowWindow(SW_SHOW);                 OnBnClickedHideTray();                                      return TRUE;                                  case WM_RBUTTONDOWN: // 右击时:显示弹出菜单                                      CMenu menu, *pMenu;                 menu.LoadMenu(IDR_MENU1); // 加载菜单                 pMenu = menu.GetSubMenu(0); // 获取子菜单                                      POINT ptPos;                 GetCursorPos(&ptPos); // 获取鼠标指针                                      pMenu->SetDefaultItem(ID_POP_SHOW_MAIN); // 设置默认项                                      this->SetForegroundWindow(); //这一行代码很重要,否则右键菜单工作不正常。详见msdn说明: http://support.microsoft.com/kb/135788                                                      pMenu->TrackPopupMenu(                     TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,                     ptPos.x, ptPos.y,                     this); // 弹出菜单                                      return TRUE;         }     }     return FALSE; }
效果:
无标题1.png

无标题2.png

==========================================================
示例源码和程序:
attachment icon TaskBarTest.rar 303.52KB RAR 81次下载
运行界面:
无标题.png

[修改于 10年0个月前 - 2015/05/28 18:25:14]

来自:计算机科学 / 软件综合
1
新版本公告
~~空空如也

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,6年4个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的