VC/MFC实用任务栏编程
acmilan2015/05/28软件综合 IP:四川
一、闪动任务栏,提醒用户该窗口需要操作
这个很简单,直接在需要提醒用户的地方加入这一句就好了:
<code class="lang-cpp">this->FlashWindowEx(FLASHW_TRAY | FLASHW_TIMERNOFG, 0, 0); // 仅任务栏,闪烁直到窗口激活,默认频率</code>
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。
首先在对话框的类声明里加入以下几句:
<code class="lang-cpp">CComQIPtr<itaskbarlist3> m_tbl; // 任务栏:ITaskBarList3实例指针
LRESULT OnTaskbarButtonCreated(WPARAM wParam, LPARAM lParam); // 任务栏:"TaskbarButtonCreated"消息</itaskbarlist3></code>
然后修改对话框的CPP文件:
<code class="lang-cpp">const UINT WM_TASKBAR_BUTTON_CREATED = RegisterWindowMessage("TaskbarButtonCreated"); // 任务栏:注册消息
BEGIN_MESSAGE_MAP(CTaskBarTestDlg, CDialog)
    // ... 其它消息映射 ...
    ON_REGISTERED_MESSAGE(WM_TASKBAR_BUTTON_CREATED, OnTaskbarButtonCreated) // 任务栏:映射消息
END_MESSAGE_MAP()</code>
为消息映射添加代码:
<code class="lang-cpp">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;
}</code>
最后添加WM_DESTROY消息映射,释放ITaskbarList3实例(因为MFC在对话框析构之前调用了CoUninitialize(),不及时释放会崩溃):
<code class="lang-cpp">void CTaskBarTestDlg::OnDestroy() // 窗口销毁时:ITaskBarList3析构COM对象
{
    CDialog::OnDestroy();
                          
    m_tbl.Release(); // 任务栏:析构COM对象(必须在调用CoUnintialize()之前,不能等待CComQIPtr析构函数,否则会崩溃)
}</code>
这样,我们就可以使用m_tbl的成员函数SetProgressValue和SetProgressState来在任务栏显示进度了:
<code class="lang-cpp">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); // 设置任务栏进度状态:清除进度
    }
}</code>
效果:
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"注册消息。
创建图标的代码:
<code class="lang-cpp">// 自定义图标消息
#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;
}</code>
删除图标的代码:
<code class="lang-cpp">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;
}</code>
explorer崩溃重建图标:
<code class="lang-cpp">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;
}</code>
图标点击消息:
<code class="lang-cpp">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;
}</code>
效果:
无标题1.png

无标题2.png

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

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

来自:计算机科学 / 软件综合
1
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也

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

所属专业
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年3个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}