zoukankan      html  css  js  c++  java
  • 重画控件与系统托盘图标编写(VC_MFC)

    目录

    控件重绘
    系统托盘图标

    (本章节中例子都是用 VS2005 编译调试的)


    控件重绘

    注意:

    • 要自绘的控件必须在 Owner Draw 属性上设置为 true,
    • 或者用 Create 函数创建控件时候,具备自绘属性(例如 CButton 在用 Create 创建时候需具备 BS_OWNERDRAW, CStatic 在用 Create 创建时候需具备 SS_OWNERDRAW 等等)

    在重绘某个控件时

    重要结构体:

    DRAWITEMSTRUCT(MSDN 链接)

    作用:  为需要自绘的控件或者菜单项提供了必要的信息

    结构体定义:

    View Code
    typedef struct tagDRAWITEMSTRUCT { 
      UINT CtlType;  // Unsigned integer that specifies the control type. 
      UINT CtlID; // Unsigned integer that specifies the identifier of the combo box, list box, or button. This member is not used for a menu.
      UINT itemID; // Unsigned integer that specifies the menu item identifier for a menu item or the index of the item in a list box or combo box.
      UINT itemAction; // Unsigned integer that specifies the drawing action required.
      UINT itemState; // Unsigned integer that specifies the visual state of the item after the current drawing action takes place.
      HWND hwndItem; // Handle to the control for combo boxes, list boxes, buttons, and static controls. For menus, this member is a handle to the menu containing the item.
      HDC hDC; // Handle to a device context.
      RECT rcItem; // RECT structure that specifies a rectangle that defines the boundaries of the control to be drawn. 
      ULONG_PTR itemData;  
    } DRAWITEMSTRUCT; 

    注意:  在 CListBox,CListCtrl,CTreeCtrl,CComboBox 控件中可以使用 SetItemData 来设置结构体中的 itemData 值. ( CListBox::SetItemData , CListCtrl::SetItemData , CTreeCtrl::SetItemData , CComboBox::SetItemData )

    相关文献链接:

    代码样例:

    这里以 List Box 控件为例子来说,首先在新建的工程中添加一个 List Box 控件,并设置 Has Strings 属性为 true,Owner Draw 属性上设置为 fixed,List Box控件资源为 IDC_LIST1,对话框资源视图如下:

    然后为这个 List Box 添加一个关联的控制变量 m_listBox 这里的变量类型先选默认的 CListBox 然后点击确定.然后派生一个 CMyListBox 基类为 CListBox ,然后为 CMyListBox 去添加一个控件重绘函数(即 DrawItem,这里可以用 VS 帮你自动生成这个函数),然后在控件中添加以下操作,可以使 List Box 选中项以黑色背景,白色字体显示,非选中项以黑色字体,白色背景显示,具体代码如下:

    View Code
    //添加一个 CDC 对象然后关联 List Box 项的资源 DC
    CDC dc;
    dc.Attach(lpDrawItemStruct->hDC);
    //判断是否是选中项,通过判断这个项是否具有焦点
    CBrush bs;
    if(lpDrawItemStruct->itemState & ODS_SELECTED)
    {
        //绘制选中项的背景色为黑色
        bs.CreateSolidBrush(RGB(0,0,0));
        dc.FillRect(&lpDrawItemStruct->rcItem,&bs);
        //文本背景色为黑色,字体为白色
        dc.SetBkColor(RGB(0,0,0));
        dc.SetTextColor(RGB(255,255,255));
    }
    else
    {
        //绘制未选中项的背景色为白色,
        bs.CreateSolidBrush(RGB(255,255,255));
        dc.FillRect(&lpDrawItemStruct->rcItem,&bs);
        //文本背景色为白色,字体为黑色
        dc.SetBkColor(RGB(255,255,255));
        dc.SetTextColor(RGB(0,0,0));
    }
    CString str;
    GetText(lpDrawItemStruct->itemID,str);
    //绘制文本
    dc.DrawText(str,&lpDrawItemStruct->rcItem,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
    //分离资源 DC
    dc.Detach();

    运行结果:

    相关文献:

     


    系统托盘图标

    重要结构体:

    NOTIFYICONDATA(MSDN 链接)

    作用:  记录着在托盘中相关项的相关信息

    结构体定义:

    View Code
    typedef struct _NOTIFYICONDATA { 
      DWORD cbSize; // Size of this structure, in bytes.
      HWND hWnd; // Handle to the window that receives notification messages associated with an icon in the taskbar status area.
      UINT uID; // Application-defined identifier of the taskbar icon. Values from 0 to 12 are reserved and should not be used.
      UINT uFlags; // Array of flags that indicate which of the other members contain valid data. 
      UINT uCallbackMessage; // Application-defined message identifier
      HICON hIcon; // Handle to the icon to add, modify, or delete.
      WCHAR szTip[64]; // Null-terminated string that contains ToolTip text to display for the icon.
    } NOTIFYICONDATA, *PNOTIFYICONDATA;

    操作流程:

    代码示例:

    这里以对话框为例(单/多文档也类似),在对话框工程中添加一个成员 NOTIFYICONDATA 类型的 m_NotifyIconData 变量,然后在对话框初始化的函数(即 OnInitDialog 函数)中添加具体实现代码,代码如下:( MSDN链接: Shell_NotifyIcon)

    View Code
    /* 托盘图标的初始化工作 ************************************************************************/
    //初始化 m_NotifyIconData 内存空间
    memset(&m_NotifyIconData, 0, sizeof(NOTIFYICONDATA));
    //使托盘中图标对应于本窗体,这样它便可以把托盘图标的事件发送给窗体程序
    m_NotifyIconData.hWnd = GetSafeHwnd();
    ASSERT(m_NotifyIconData.hWnd != NULL);
    //定托盘图标产生事件时候发出的事件
    m_NotifyIconData.uCallbackMessage = WM_NOTI;
    //填充结构体的大小
    m_NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
    //加载托盘图标(这里以默认的资源图标)
    m_NotifyIconData.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    //设置鼠标移动到托盘图标时候的提示文字
    memcpy (m_NotifyIconData.szTip,L"test",sizeof(L"test"));
    //设置托盘图标的属性
    m_NotifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    //设置托盘图标的图标资源 ID
    m_NotifyIconData.uID = IDR_MAINFRAME;
    
    
    /* 显示托盘图标 *********************************************************************************/
    Shell_NotifyIcon(NIM_ADD, &m_NotifyIconData);

    然后为托盘图标写事件响应函数,即先在对话框的消息映射中添加消息的消息映射,然后定义相关消息映射函数(参数说明: wParam:任务栏图标的ID, lParam:鼠标事件值)

    View Code
    /* 对话框头文件 **********************************/
     ...
    #pragma once
    //消息定义
    #define WM_NOTI (WM_USER+1)
    
    // CtestDlg 对话框
    class CtestDlg : public CDialog
    {
        ...
        //NOTITYICONDAT结构
        NOTIFYICONDATA m_NotifyIconData;
        ...
        //托盘图标响应事件消息的函数
        afx_msg LRESULT OnMyNoTi(WPARAM wParam, LPARAM lParam);
    };
    
    
    
    
    /* 对话框实现文件 ********************************/
    ...
    
    BEGIN_MESSAGE_MAP(CtestDlg, CDialog)
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        //}}AFX_MSG_MAP
        //消息映射
        ON_MESSAGE(WM_NOTI,OnMyNoTi)
    END_MESSAGE_MAP()
    
    ...
    
    LRESULT CtestDlg::OnMyNoTi(WPARAM wParam,LPARAM lParam)
    { 
        // TODO: 处理用户自定义消息
        //当用户单击托盘图标时候弹出一个消息框
        if(lParam == WM_LBUTTONUP)
            MessageBox(L"test");
        return 0; 
    }

    然后在对话框窗口销毁的时候删除托盘中的图标,即为对话框添加 WM_DESTORY 事件响应函数,然后加入以下代码:

    Shell_NotifyIcon(NIM_DELETE, &m_NotifyIconData);

    相关文章

  • 相关阅读:
    利用艺术家的整数ID映射将标签转换为向量
    TOMCATserver不写port号、不写项目名訪问项目、虚拟文件夹配置
    一、奇妙插件Tampermonkey的简单安装教程
    三层登录—c#
    MapReduce中combine、partition、shuffle的作用是什么
    代码混淆防止APP被反编译指南
    数据分析思路的套路攻略
    聊一聊数据分析师这个职业
    Android优化之内存优化倒计时篇
    如何实现360度的手游安全防护?网易云易盾专家分享最新实践
  • 原文地址:https://www.cnblogs.com/kzang/p/2790736.html
Copyright © 2011-2022 走看看