五.控件基础编程
1.控件的概念:所有的子窗口都是控件
特点:与主窗口一致,但是其行为限制在主窗口内
2.利用预定义类创建控件实例
创建一个控件
HWND GUIAPI CreateWindowEx2 (const char* spClassName,const char* spCaption, DWORD dwStyle, DWORD dwExStyle,int id, int x, int y, int w, int h, HWND hParentWnd,const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs,DWORD dwAddData);
static inline HWND GUIAPI CreateWindowEx (const char* spClassName,const char* spCaption, DWORD dwStyle, DWORD dwExStyle,int id, int x, int y, int w, int h, HWND hParentWnd,DWORD dwAddData)
{
return CreateWindowEx2 (spClassName, spCaption, dwStyle, dwExStyle,id, x, y, w, h, hParentWnd, NULL, NULL, dwAddData);
}
参数 add_data用来向控件传递其特有数据的指针,该指针所指向的数据结构随控件类的不同而不同
#define CreateWindow(class_name, caption, style, id, x, y, w, h, parent, add_data) CreateWindowEx(class_name, caption, style, 0, id, x, y, w, h, parent, add_data)
销毁一个控件
BOOL GUIAPI DestroyWindow (HWND hWnd);
3.控件编程涉及的内容
3.1 相关的函数 ShowWindow、 MoveWindow、 EnableWindow、 SetWindowFont
3.2 控件内部发生某种事件时,会通过通知消息通知其父窗口
注:如果在创建过程中有相应的回调函数,则给回调函数处理,否则由父窗口处理
3.3 MSG_COMMAND消息
wParam 参数由子窗口标识符(低16位)和通知码组成(高16位)
lParam 参数含有发出通知消息的控件句柄。
例:若在编辑框发生改变,则向父窗口发出MSG_COMMAND消息,标识符为该编辑框在父窗口的id,通知码为EN_CHANGE
SetNotificationCallback
static void my_notif_proc (HWND hwnd, int id, int nc, DWORD add_data);//控件过程回调函数
SetNotificationCallback (GetDlgItem (hDlg, IDC_SIZE_MM), my_notif_proc);
SetWindowAdditionalData (hDlg, lParam);
double* length = (double*) GetWindowAdditionalData (hDlg);
3.4控件专用的操作函数
GetNotificationCallback 获取控件的通知消息回调函数
SetNotificationCallback 设置控件的通知消息回调函数
NotifyParentEx 发送控件通知消息
六.控件的高级编程
1.自定义控件
RegisterWindowClass
UnregisterWindowClass
2.控件的子类化
• 一种是对已经建立的控件实例进行子类化,子类化的结果只会影响这一个控件实例。
• 一种是对某个控件类进行子类化,将影响其后创建的所有该控件类的控件实例。
• 最后一种是在某个控件类的基础上新注册一个子类化的控件类,不会影响原有控件类。 在 Windows 中,这种技术
又称为超类化。
方法:在主窗口内,用自定义的窗口过程替换编辑框的窗口过程,并保存老的窗口过程(可以是编辑框默认的窗口过程,也可以是用户封装过的窗口过程)
old_edit_proc = SetWindowCallbackProc (hWnd1, RestrictedEditBox);
SetWindowCallbackProc (hWnd2, RestrictedEditBox);
问题:那么控件的过程处理是什么,而我需要自定义一个控件到底该怎么做
十九.静态框
1.什么是静态框
1.1 用于在窗口特定位置显示文字、数字或者图片
1.2 静态框不能对用户的输入进行动态的响应
1.3 控件名称: CTRL_STATIC 或者 "static"
2.标准型
SS_SIMPLE、 SS_LEFT、 SS_CENTER、 SS_RIGHT,以及 SS_LEFTNOWORDWRAP
SS_SIMPLE:单行文本,不会自动换行显示,左对齐
SS_LEFT、 SS_CENTER 或 SS_RIGHT:多行文本 左对齐、中对齐和右对齐显示
SS_LEFTNOWORDWRAP: 静态框会扩展文本中的 TAB 符,但不做自动换行处理。
创建一个标准型静态框
CreateWindow (CTRL_STATIC,"This is a simple static control.",WS_CHILD | SS_NOTIFY | SS_SIMPLE | WS_VISIBLE | WS_BORDER,IDC_STATIC1,10, 10, 180, 20, hWnd, 0);
3.位图型 ---- SS_BITMAP SS_ICON
dwAddData 参数设定要显示的位图对象指针或者图标对象句柄。
默认情况下,位图和图标要经过适当的缩放充满整个静态框
SS_REALSIZEIMAGE 风格将取消缩放操作,并显示在静态框的左上方
SS_REALSIZEIMAGE | SS_CENTERIMAGE 会在控件中部显示位图或图标。
创建一个位图型控件
CreateWindow (CTRL_STATIC,"",WS_CHILD | SS_BITMAP | WS_VISIBLE,IDC_STATIC,280, 80, 50, 50, hWnd, (DWORD)GetSystemBitmap (SYSBMP_CHECKMARK));
创建一个图标型控件
CreateWindow (CTRL_STATIC,"",WS_CHILD | SS_ICON | WS_VISIBLE,IDC_STATIC,280, 20, 50, 50, hWnd, (DWORD)GetLargeSystemIcon (IDI_INFORMATION));
4.分组框 ------ SS_GROUPBOX
创建一个分组框对话框
CreateWindow (CTRL_STATIC,"A Group Box",WS_CHILD | SS_GROUPBOX | WS_VISIBLE,IDC_STATIC,350, 10, 200, 100, hWnd, 0);
5.其它类型风格对话框
• SS_WHITERECT:以白色填充静态框矩形。
• SS_GRAYRECT:以灰色填充静态框矩形。
• SS_BLACKRECT:以黑色填充静态框矩形。
• SS_GRAYFRAME:灰色边框。
• SS_WHITEFRAME:白色边框。
• SS_BLACKFRAME:黑色边框。
6.静态框消息
获得或者修改静态框的位图:
STM_GETIMAGE 获得静态框消息
STM_SETIMAGE 通过 wParam 参数重新设置位图指针或者图标句柄,并且返回原来的指针
意思是发消息的时候,想要修改静态框的图标,在wParam参数那里,传入图标的句柄
7.静态框消息通知码
当风格含有:SS_NOTIFY
STN_DBLCLK:表示用户在静态框内双击了鼠标左键
STN_CLICKED:表示用户在静态框内单击了鼠标左键
二十.按钮
1.普通按钮 ---- BS_PUSHBUTTON 和 BS_DEFPUSHBUTTON
1.1对话框: BS_DEFPUSHBUTTON 默认接收 ENTER 键输入的按钮
1.2普通主窗口:BS_DEFPUSHBUTTON 边框要粗
1.3按钮文本会以单行的形式在垂直和水平方向居中显示,不会自动换行。
自动换行: BS_MULTILINE 垂直向上对齐
1.4BS_BITMAP 或者 BS_ICON 默认情况下位图或图标会缩放显示以充满整个按钮窗口范围
创建一个带位图的按钮
hwnd = CreateWindow (CTRL_BUTTON,"Close",WS_CHILD | BS_PUSHBUTTON | BS_BITMAP |BS_REALSIZEIMAGE | BS_NOTIFY | WS_VISIBLE,IDC_BUTTON + 4,10, 300, 60, 30, hWnd, (DWORD) GetSystemBitmap (IDI_APPLICATION));
2.复选框
BS_CHECKBOX 和 BS_AUTOCHECKBOX
BS_CHECKBOX : 应用程序需要自己向该控件发送消息来设定选中标记
BS_AUTOCHECKBOX : 控件会自动在选中和非选中状态之间切换
BS_3STATE 和 BS_AUTO3STATE 第三种状态是灰色的
BS_LEFTTEXT 使复选框靠右对齐
BS_LEFT、 BS_CENTER、 BS_RIGHT、 BS_TOP、 BS_VCENTER、 BS_BOTTOM
BS_PUSHLIKE 风格将使复选框以普通按钮的形式显示:选中时显示为按下状态,未选中时显示为正常状态
3.单选钮 ------ BS_RADIOBUTTON 或 BS_AUTORADIOBUTTON
每一个按钮都对应一个频道,而且一次只能有一个按钮被按下;相互排斥;当第二次按单选按钮时,它的状态会保持不变
注:这句话没有理解: BS_PUSHLIKE 风格将使单选按钮以普通按钮的形式显示:选中时显示为按下状态,未选中时显示为正常状态
3.1 创建一个单选钮
CreateWindow (CTRL_BUTTON,"Auto Radio Button 2",WS_CHILD | BS_AUTORADIOBUTTON | WS_VISIBLE,IDC_RADIOBUTTON + 1,20, 160, 130, 30, hWnd, 0);
4.按钮消息
查询/设置复选框或者单选钮的选中状态: BM_GETCHECK、 BM_SETCHECK
查询/设置普通按钮或者复选框的按下或释放状态: BM_GETSTATE、 BM_SETSTATE
获取/设置位图按钮上的位图或者图标: BM_GETIMAGE、 BM_SETIMAGE
发送 BM_CLICK 模拟用户鼠标的单击操作
设置按钮选中状态
SendMessage (hwndButton, BM_SETCHECK, BST_CHECKED, 0);
wParam:BST_UNCHECKED(0) 未选中
BST_CHECKED(1) 已选中
BST_INDETERMINATE(2) 不可用状态
得到状态,可以选用BM_GETCHECK
设置按钮按下和释放状态
模拟按钮来回闪动: SendMessage (hwndButton, BM_SETSTATE, BST_PUSHED, 0) ;
SendMessage (hwndButton, BM_SETSTATE, 0, 0) ;
获取位图和图标信息
int ret_val = SendMessage (hwndButton, BM_GETIMAGE, (WPARAM)&image_type, 0) ;
设置位图和图标信息
int ret_val = SendMessage (hwndButton, BM_SETIMAGE, BM_IMAGE_BITMAP, btn_bmp) ;
SendMessage (hwndButton, BM_SETIMAGE, BM_IMAGE_ICON, btn_icon) ;
PBITMAP btn_bmp
HICON btn_icon;
5.消息通知码
BS_NOTIFY
BN_CLICKED:表明用户单击此按钮。
如果是在父窗口传递过来的:只需判断 MSG_COMMAND 消息的 wParam 参数是否等于按钮的标识符即可
BN_PUSHED:表明用户将此按钮按下
BN_UNPUSHED:表明用户将此按钮释放
BN_DBLCLK:表明用户在此按钮上进行了鼠标左键的双击操作。
BN_SETFOCUS:表明按钮获得了输入焦点。
BN_KILLFOCUS:表明按钮失去了输入焦点。
三十章.滚动型控件 ------ ScrollView
1.滚动型控件概念
滚动型控件中滚动显示的是列表项而不是控件
滚动型的主要用途: 是显示和处理列表
滚动型中的列表高度是可以由用户指定的,不同的列表项显示不同的高度
2.控件风格
在控件风格中 SVS_AUTOSORT scrollview style
则可以如下写:
SVM_SETITEMCMP myItemCmp;
SendMessage (hScrWnd, SVM_SETITEMCMP, 0, (LPARAM)myItemCmp);
SVM_SETITEMCMP的原型如下
typedef int (*SVITEM_CMP) (HSVITEM hsvi1, HSVITEM hsvi2);
对不具有 SVS_AUTOSORT
SVM_SETITEMCMP myItemCmp;
SendMessage (hScrWnd, SVM_SORTITEMS, 0, (LPARAM)myItemCmp);
3.滚动型控件消息
滚动型控件的相关消息主要用于列表项的添加、删除和访问等方面
3.1 列表项控件显示
SVITEM_DRAWFUNC myDrawItem;
SendMessage (hScrWnd, SVM_SETITEMDRAW, 0, (LPARAM)myDrawItem);
typedef void (*SVITEM_DRAWFUNC) (HWND hWnd, HSVITEM hsvi, HDC hdc, RECT *rcDraw);
滚动型窗口句柄 列表项句柄 图形设备上下文 列表项绘制的矩形区域
3.2 列表项操作函数的设置
SVITEMOPS myops;
SendMessage (hScrWnd, SVM_SETITEMOPS, 0, (LPARAM)&myops);
typedef struct _svitem_operations
{
SVITEM_INITFUNC initItem;
SVITEM_DESTROYFUNC destroyItem;
SVITEM_DRAWFUNC drawItem;
}SVITEMOPS;
创建列表项的初始化函数的句柄:typedef int (*SVITEM_INITFUNC) (HWND hWnd, HSVITEM hsvi);
销毁列表项的初始化函数的句柄:typedef void (*SVITEM_DESTROYFUNC) (HWND hWnd, HSVITEM hsvi);
3.3 列表项的操作
增加一个列表项
SVM_ADDITEM 和 SVM_DELITEM 消息分别用来添加和删除一个列表项
int idx;
HSVITEM hsvi; //滚动型控件列表项
SVITEMINFO svii; //每一项滚动型控件列表项信息
Idx = SendMessage (hScrWnd, SVM_ADDITEM, (WPARAM)&hsvi, (LPARAM)&svii);
typedef struct _SCROLLVIEWITEMINFO
{
int nItem; //item的标识符
int nItemHeight;//item的高
DWORD addData; //item的额外数据
}SVITEMINFO;
nItem 项为列表项的添加位置,如果 nItem 为负值,列表项将被添加到末尾
SVM_ADDITEM 消息返回所添加列表项的实际索引值
删除一个列表项
int idx;
HSVITEM hsvi;
SendMessage (hScrWnd, SVM_DELITEM, idx, hsvi);
hsvi 指定所要删除的列表项的句柄。如果 hsvi为0,idx 指定所要删除的列表项的索引值。
刷新一个列表项
int idx;
HSVITEM hsvi;
SendMessage (hScrWnd, SVM_REFRESHITEM, idx, hsvi);
获取列表项的附加数据
SendMessage (hScrWnd, SVM_GETITEMADDDATA, idx, hsvi);
设置列表项的附加数据
int idx;
DWORD addData;
SendMessage (hScrWnd, SVM_SETITEMADDDATA, idx, addData);
获取当前列表项的数量
int count = SendMessage (hScrWnd, SVM_GETITEMCOUNT, 0, 0);
SVM_RESETCONTENT 消息用来删除掉控件中所有的列表项
SendMessage (hScrWnd, SVM_RESETCONTENT, 0, 0);
3.4获取和设置当前高亮项
滚动型控件具有一个高亮列表项属性,列表项中仅有(如果有的话)一个列表项是当前高亮的列表项
设置控件的高亮列表项
SendMessage (hScrWnd, SVM_SETCURSEL, idx, bVisible);
获取控件的当前高亮列表项
int hilighted_idx = SendMessage (hScrWnd, SVM_GETCURSEL, 0, 0);
3.5列表项的选择和显示
高亮是唯一的,选中不是唯一的
列表项的选择
SendMessage (hScrWnd, SVM_SELECTITEM, idx, bSel);
idx 指定所要设置的列表项的索引值。 bSel 如果为 TRUE,该列表项将被设置为选中;反之为非选中。
列表项的显示
SendMessage (hScrWnd, SVM_SHOWITEM, idx, hsvi);
列表项的选择和显示
SendMessage (hScrWnd, SVM_CHOOSEITEM, idx, hsvi);
SVM_CHOOSEITEM 消息是 SVM_SELECTITEM 和 SVM_SHOWITEM 的组合
显示的优化 ---- MSG_FREEZE 的 wParam 参数为TURE则是冻结,反之是解冻
用于的场合:在使用 SVM_ADDITEM 消息或者 SVM_DELITEM 消息一次性增加或者删除很多列表项时,可以使用 MSG_FREEZE 消息进行一定的优化。用法是在操作之前冻结控件,操作之后解冻。
3.6设置可见区域范围
滚动型控件由内到外 可视区域 ----> 边缘区域 ------> 内容区域
SVM_SETMARGINS 消息可以对滚动型控件的边缘范围进行设置
设置边缘区域
RECT rcMargin;
SendMessage (hScrWnd, SVM_SETMARGINS, 0, (LPARAM)&rcMargin);
获取边缘区域的值
RECT rcMargin;
SendMessage (hScrWnd, SVM_GETMARGINS, 0, (LPARAM)&rcMargin);
SVM_GETLEFTMARGIN、SVM_GETTOPMARGIN、SVM_GETRIGHTMARGIN 和 SVM_GETBOTTOMMARGIN 消息分别用来获取左、上、右和下边缘值。
4.控件通知码
SVN_SELCHANGED:当前高亮列表项发生改变 ----- 被点击或当前的列表项
SVN_CLICKED:用户点击列表项
SVN_SELCHANGING:当前高亮列表项正发生改变 ----- 先前的高亮列表项句柄