重画控件与系统托盘图标编写(VC_MFC)
目录
(本章节中例子都是用 VS2005 编译调试的)
控件重绘
注意:
- 要自绘的控件必须在 Owner Draw 属性上设置为 true,
- 或者用 Create 函数创建控件时候,具备自绘属性(例如 CButton 在用 Create 创建时候需具备 BS_OWNERDRAW, CStatic 在用 Create 创建时候需具备 SS_OWNERDRAW 等等)
在重绘某个控件时
重要结构体:
DRAWITEMSTRUCT(MSDN 链接)
作用: 为需要自绘的控件或者菜单项提供了必要的信息
结构体定义:
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 选中项以黑色背景,白色字体显示,非选中项以黑色字体,白色背景显示,具体代码如下:
//添加一个 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 链接)
作用: 记录着在托盘中相关项的相关信息
结构体定义:
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)
/* 托盘图标的初始化工作 ************************************************************************/ //初始化 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:鼠标事件值)
/* 对话框头文件 **********************************/ ... #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);
相关文章