第八章 子窗体控件
来源:互联网 发布:js去除class样式 编辑:程序博客网 时间:2024/06/15 23:43
http://dec3.jlu.edu.cn/webcourse/T000024/files/bjjx/bjjx8.htm
第八章 子窗体控件
图形界面和消息处理是任何一个基于Windows的应用程序必须认真考虑的事情。在前面的章节中已经介绍了Windows应用程序消息处理的机制,这种机制对于所有对象的消息处理都是一致的,即实行客户(用户操作或请求)到操作系统(捕获消息)到应用程序(接收消息并执行处理代码)的机制。而图形界面则包含丰富的内容,主要是指各种各样的控件,不仅包括前面章节中介绍的主窗口,还包括按钮、编辑框、滚动条等具有窗口风格的子窗口。丰富的图形界面元素为建立界面友好的应用程序提供了可能,而完整的消息处理机制则为应用程序的功能提供了高效集成的保证。
概述
子窗口的概念包含两方面的含义:
从创建子窗口的过程来看,Createwindow函数为创建各类窗口提供了统一的函数,并且子窗口的类型唯一由第一个参数确定;从窗口的界面风格来看,这些子窗口都拥有窗口的许多性质。
设计含有子窗口的程序都从调用函数 CreateWindow开始,它一共有 11个参数,指定待创建的子窗口的类型、标题、风格等非常重要的性质。
CreateWindow函数的原型定义如下:
HWND CreateWindow(LPCTSTR lpClassName, // 指定子窗口的类名
LPCTSTR lPWindowName, // 指定窗口名称
DWORD dwSty1e, // 指定窗口风格
int x, // 指定窗口左上角顶点的水平坐标
int y, // 指定窗口左上角顶点的垂直坐标
int nWidth, // 指定窗口宽度
int nHeight, // 指定窗口高度
HWND hWndParent, //父窗口句柄,允许为NULL
HMENU hMenu, //窗口的菜单句柄或者是子窗口自己的标识符
HANDLE hInstance, //应用程序句柄,可以为NULL
LPVOID lpParam //指向lParam数值的指针);
当子窗口创建成功后,返回子窗口的句柄,否则返回NULL。在11个参数中 lpClassName、dwStyle和hMenu是三个最重要的参数。下面分别讲述它们的意义。 lpClassName指定子窗口的类名,它们的取值可以是如表所示的值。
dwStyle指定子窗口的风格。这里只讲述一般窗口的风格,表所列的子窗口的风格在后面内容中分别讲述。一般窗口的风格取值如表所示。
创建具有最大按钮的子窗口。
WS_MINIMIZE同WS_ICONIC。WS_MINIMIZEBOX创建最小按钮的子窗口。WS_SIZEBOX创建可缩放边框的子窗口。WS_SYSMENU使子窗口有系统菜单。WS_TABSTOP指定用户第一次接下Tab键时输入焦点所属的子窗口。WS_THICKFRAME同WS_SIZEBOX。WS_VISIBLE创建初始化可视的窗口。WS_VSCROLL使窗口具有垂直滚动条。 参数hMenu指定菜单句柄或者子窗口的标识符。例如,已建立的菜单资源标识符为IDM_MENU, 窗口需要加载该菜单,则 hMenu参数可为 IDM_NENU子窗口的标识符可以是字符或者数字,但同一个应用程序中不同子窗口的 标识符必须相异,并且前面加上(hMENU)来满足参数类型兼容的要求。
应用程序运行后,首先创建主窗口,并发送WM_CREATE消息,由于在该消息的处理代码中含有创建子窗口的代码,于是就创建了子窗口。当子窗口的WS_VISIBLE风格指定后,子窗口就显示出来。
同前所讲的消息处理机制类似,子窗口的消息也主要依靠参数lParam和wParam来完成。
应用程序创建子窗口后,在主窗口的消息处理函数中一般使用SendMessase向子窗口发送消息。当用户对子窗口进行某种操作后,将向父窗口发送WM_COMMAND类型的通知消息。其中,lParam包含子窗口的句柄;wParam参数的高位字节为通知代码,低位子代表子窗口的标识符。
下面将分别讲述各种子窗口的特有风格以及消息循环,并结合实例介绍子窗口的应用。
一、Button子窗口
Button(按钮)是Windows子窗口的最常用的元素之一。例如安装程序中选择Next或者Back按钮。
1. 按钮类型
依据操作的类型可以把按钮分为按键按钮、单选按钮、复选按钮,另外还有存放单选按钮和复选按钮的按钮组合框(GroupBox)。
按键按钮一般执行某项功能,例如弹出新的窗口。在创建子窗口的函数中,如果需要创建按键按钮,则dwStyle参数指定为BS_PUSHBUTTON。
当某些选择相互排斥时,需要用到单选按钮,例如字体或者颜色。单选按钮的左端为一个圆圈,选中单选按钮,则显示实心,相反为空心圆。在同一个按钮组合框里的众多单选按钮中,用户只能选择一个。如果需要单选按钮,则dwStyle 参数必须指定为BS_RADIOBUTTON。
当某些选择可以相互并存时,需要用到复选按钮。复选按钮的风格与单选按钮类似,左端为圆圈或者小空心正方形。在同一个按钮组合框里的复选按钮可以同时被选中几个。如果需要创建,则dwStyle参数设置为BS_CHECKBOX。
在复选按钮中还有一类特殊的按钮,即三态按钮。顾名思义,三态按钮允许有三种状态:选中(Selected)、本选中(Unselected)、显灰(Grayed)。三态按钮在需要把单选按钮和复选按钮放在同一个组合框里时才有应用的价值,若要创建三态按钮,则把dwStyle参数设置为BS_3STATE。
按钮的风格取值如表所示。
按钮有自己特殊的消息类型。当用户选择了按钮时,它将向父窗口发送WM_COMMAND消息,这些通知消息包含在wParam的高位字节中。按钮的通知代码如表所示。
2.Button子窗口的创建和使用示例
#include <windows.h>
Struct //定义按钮的风格和显示文本
{
long style ;
char *text ;
}
button[] = //定义9类按钮
{
BS_PUSHBUTTON, "按键按钮",
BS_DEFPUSHBUTTON, "默认按键按钮",
BS_CHECKBOX, "检查按钮",
BS_AUTOCHECKBOX, "自动检查按钮",
BS_GROUPBOX, "复选框",
BS_3STATE, "检查按钮",
BS_AUTO3STATE, "三状态自动检查按钮",
BS_AUTORADIOBUTTON, "自动圆按钮",
BS_RADIOBUTTON, "圆按钮",
};
//取得按钮的数目
#define NUM (sizeof button/sizeof button[0])
//定义应用程序的名字
static char szAppName[] = "BtnLook" ;
//预先声明消息处理、窗口类申请和初始化函数
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
//函数:WinMain
//作用:主应用函数
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
MSG msg ;
//申请窗口类
MyRegisterClass(hInstance);
//应用程序的初始化
if(!InitInstance(hInstance,iCmdShow))
{
return FALSE;
}
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
//函数:MyRegisterClass
//作用:注册窗口类
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
return RegisterClassEx (&wndclass) ;
}
//函数:InitInstance
//作用:初始化应用程序
BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
{
HWND hwnd ;
hwnd = CreateWindow(szAppName, "按钮设计",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
if(!hwnd)return FALSE;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
return TRUE;
}
//函数:WndProc
//作用:消息处理函数
LRESULT CALLBACK WndProc (HWND hwnd,UINT iMsg, WPARAM wParam,LPARAM lParam)
{//窗口上显示提示信息
static char szTop[]="消息 参数wParam 参数lParam",
szUnd[] = "____ ______ ______",
szFormat[] = "%-16s%04X-%04X %04X-%04X",
szBuffer[50] ;
//定义需要建立的按钮
static HWND hwndButton[NUM] ;
static RECT rect ;
static int cxChar, cyChar ;
HDC hdc ;
PAINTSTRUCT ps ;
int i ;
TEXTMETRIC tm ;
switch (iMsg)
{
case WM_CREATE :
//取得图形设备描述表的句柄
hdc = GetDC (hwnd) ;
SelectObject(hdc,GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
//创建按钮
for (i = 0 ; i < NUM ; i++)
hwndButton[i] = CreateWindow("button",
button[i].text,
WS_CHILD|WS_VISIBLE|button[i].style,
cxChar,cyChar * (6+ 2 * i), 22 * cxChar,
7 * cyChar / 4,
hwnd,
(HMENU) i,
((LPCREATESTRUCT) lParam) -> hInstance,
NULL) ;
return 0 ;
//取得文本显示区域的大小
case WM_SIZE :rect.left = 24 * cxChar ;
rect.top = 2 * cyChar ;
rect.right = LOWORD (lParam) ;
rect.bottom = HIWORD (lParam) ;
return 0 ;
//重画文本
case WM_PAINT :InvalidateRect (hwnd, &rect, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetBkMode (hdc, TRANSPARENT) ;
//输出文本头
TextOut(hdc, 24 * cxChar, cyChar, szTop, sizeof (szTop) - 1) ;
TextOut(hdc, 24 * cxChar, cyChar, szUnd, sizeof (szUnd) - 1);
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DRAWITEM :
case WM_COMMAND :
ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;
hdc = GetDC (hwnd) ;
SelectObject(hdc, GetStockObject (SYSTEM_FIXED_FONT));
//输出新的消息
TextOut(hdc,24 * cxChar,
cyChar * (rect.bottom / cyChar - 1),
szBuffer,wsprintf(szBuffer,
szFormat,
iMsg == WM_DRAWITEM?"WM_DRAWITEM" : "WM_COMMAND",
(int)(wParam), (int)(wParam),
HIWORD(lParam), LOWORD(lParam))) ;
//释放图形设备资源
ReleaseDC (hwnd, hdc) ;
//重新描绘客户区域
ValidateRect (hwnd, &rect) ;
//弹出消息对话框
switch(LOWORD(wParam))
{
case 0:
case 1:
case 2:
case 3:
MessageBox(hwnd,"Good","Yes",MB_OKCANCEL);
break ;
//推出应用程序
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam) ;
}
}
本应用程序主要创建各种各样的按钮,并把有关按钮的高位、低位字节信息显示出来。程序首先定了一个记录按钮风格和名称的结构体变量类型,然后定义按钮的结构体变量数组,代码如下: // 定义按钮的风格和显示文本
Struct{
long style;
char*text;
}
button[]//定义 9类按钮
{
BS_PUSHBUTTON, “按键按钮”,
BS_DEFPUSHBUTTON,“默认按键按钮”,
BS_CHECKBOX “检查按钮”,
BS_AUTOCHECAnOX “自动检查按钮”,
BS_GROUPBOX “复选框”,
BS_3STATE “检查按钮”,
BS_AUTO3STATE,“三状态自动检查按钮”,
BS_AUTORADIOBUTTON “自动圆按钮”,
BS_RADIOBUTTON, “圆按钮”
};
这样定义的好处是便于程序在调用CreateWindow函数时可以方便地通过for循环语句取得按钮风格值,从而大大精简了代码。
在CreateWindow函数中,参数hMenu的值为(HMENU)i,这里i代表按钮的标识符,在消息循环处理函数中可以通过i来访问按钮,代码如下:
switch(LOWORD(wParam))
case 0:
case l:
case 2:
case 3:
MessageBox(hWnd”Good”,”Yes”,MB_OKCANCEL);
程序编译、运行后,结果如图所示。
按下任意按钮,将显示按钮的有关信息。图中WM_COMMAND表示按下按钮发给主窗口的消息类型是WM_COMMAND,按下按钮的结果如图所示。
编辑框
编辑框的主要作用是让用户输入文本,例如要求用户在编辑框中输入密码的文本。
1.基础知识
编辑框里的文本可以是单行,也可以是多行,后者的风格取值为 ES_MULTILINE。一般对于多行文本编辑框还需设置 ES_AUTOVSCROLL,这样用户可以输入多行文本,并自动滚动。在默认的状况下,编辑框是没有边框的,如果需要边框,设置WS_BORDER即可。另外还可规定编辑框里的文本是否只读,风格属性设置为ES_READONLY。当需要建立密码编辑框时,只要设置ES_PASSWORD风格属性即可。
编辑框的全部风格如表所示。
Windows系统把编辑框的操作以 WM_COMMAND的形式发送给父窗口。消息的有关信息仍然包含在参数wParam和IParam中。wParam的低位字节包含编辑框的标识符,高位字节包含通知消息的类型,lParam包含编辑框的句柄。编辑框的通知消息如表所示。
在默认的情况下,当用户用鼠标右击后自动弹出菜单,形式如图3所示。
2.应用程序举例编辑框应用程序:
#include <windows.h>
#include "resource.h"
//定义应用程序的名字
char szAppName[] = "Edit Note";
//预先申明消息处理、注册窗口类以及应用程序初始化的函数
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
BOOL APIENTRY DlgProc (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
MSG msg ;//注册窗口类
MyRegisterClass(hInstance);//应用程序的初始化
if(!DialogBox(hInstance,"IDD_DIALOG1",NULL,(DLGPROC)DlgProc))
{
MessageBox(NULL,"Sorry","Password Check",MB_OKCANCEL);
return FALSE;
}
if(!InitInstance(hInstance,iCmdShow))
{
return FALSE;
}
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
//详细定义申请窗口类的函数
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = "IDR_MENU1";
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
return RegisterClassEx (&wndclass) ;
}
//详细定义初始化应用程序的函数
BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
{
HWND hwnd ;
hwnd = CreateWindow (szAppName,
"编辑框设计",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
if(!hwnd)
{
return FALSE;
}
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
return TRUE;
}
BOOL APIENTRY DlgProc (HWND hwnd,UINT iMsg, WPARAM wParam,LPARAM lParam)
{
int i;
BOOL truth=TRUE;
//标志密码是否输入正确
char ss[]="55555"; //定义密码文本
//设置密码符号,本例中设置为"@"
SendDlgItemMessage(hwnd,IDC_EDIT1,EM_SETPASSWORDCHAR,(WPARAM)'@',(LPARAM)0);
//设置密码文本字符的数目,本例中设置为5
SendDlgItemMessage(hwnd,IDC_EDIT1, EM_SETLIMITTEXT,(WPARAM)5,(LPARAM)0);
switch(iMsg)
{
case WM_COMMAND:
//取出编辑框里的文本
SendDlgItemMessage(hwnd,IDC_EDIT1,EM_GETLINE,(WPARAM)0,(LPARAM)ss);
switch(LOWORD(wParam))
{//如果用户选择OK按钮,则判断密码是否正确
case IDOK:
MessageBox(NULL,ss,ss,MB_OKCANCEL);
for(i=0;i<5;i++)
{
if(ss[i]!='1')
{
truth=FALSE;//密码不对,则标志为FALSE;
break;
}
if(truth==TRUE)
{
EndDialog(hwnd,TRUE);//结束对话框
return TRUE;
}
EndDialog(hwnd,FALSE);
case IDCANCEL:
//如果选择Cancel按钮,直接结束对话框
EndDialog(hwnd,FALSE);
return TRUE;
default:
return FALSE;
}
}
return FALSE;
}
//函数:WndProc
//作用:消息处理
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg,WPARAM wParam,LPARAM lParam)
{
//定义编辑框句柄
static HWND hwndEdit ;
switch (iMsg)
{//定义创建窗口的事件
case WM_CREATE :
//创建编辑框,其中第一个参数"edit"定义了创建的窗口是编辑框
hwndEdit = CreateWindow("edit", NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |WS_BORDER
| ES_LEFT | ES_MULTILINE |ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 0, 0,
hwnd, (HMENU) 1,
((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
return 0 ;
//设定输入焦点
case WM_SETFOCUS :
SetFocus (hwndEdit) ;
return 0 ;
//移动窗口
case WM_SIZE :
MoveWindow(hwndEdit,0,0,LOWORD(lParam),HIWORD(lParam),TRUE) ;
return 0 ;
//定义消息处理函数
case WM_COMMAND :
if (LOWORD (wParam) == 1)
if (HIWORD (wParam) == EN_ERRSPACE || HIWORD (wParam) == EN_MAXTEXT)
MessageBox(hwnd, "Edit control out of space.",szAppName, MB_OK | MB_ICONSTOP);
return 0 ;
//退出应用程序
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
本程序的主要功能是实现密码设置,当用户输入的密码正确后才能进入应用程序的主界面,相反只能重新输入。该应用程序首先建立对话框资源,标识符为IDD_DIALOGI。然后在主应用程序中显示该对话框(密码对话框),代码如下:
if(!DialogBox(hInstance,"IDD_DIALOG1", NULL,(DLGPROC)DlgProc))
{
MessageBox(NULL,"Sorry","Password Check",MB_OKCANCEL);
return FALSE;
}
程序通过DialogBox函数显示已经创建的对话框,当输入的密码不对时,则弹出出错消息,并退出应用程序。上述代码指定了对话框自身的消息处理函数DlgProc,它的定义形式与主窗口消息处理函数一样,其作用主要用来判断密码输入是否正确。
在WinProc函数中首先把编辑框设置为密码编辑框,符号为“@”,然后设置密码的最大输入字符,代码如下:
SendDlgItemMessage(hwnd,IDC_EDIT1,EM_SETPASSWORDCHAR,(WPARAM)'@',(LPARAM)0);
//设置密码文本字符的数目,本例中设置为5
SendDlgItemMessage(hwnd,IDC_EDIT1,EM_SETLIMITTEXT,(WPARAM)5,(LPARAM)0);
接着程序判断当前用户按下的按钮,如果是Cancel按钮,就直接返回FALSE;如果是OK按钮被按下,消息处理函数立即判断密码是否正确。首先把输入的密码文本取出来,存放到字符串指针ss中,然后再对ss进行判断,如果正确,则返回TRUE,从而进入应用程序主窗口。
获取编辑框里的密码文本的代码如下:
SendDlgItemMessage(hWnd,IDC_EDIT,EM_GETLINE,(WPARAM)00,(LPARAM)ss);
这样密码文本被存放到字符串指针ss中,EM_GETLINE表示得到编辑框里的一行文本。
在主窗口的消息处理函数中,除文本越界处理外,编辑框的消息全部由Windows自己完成,并且能完成一般编辑框所需要的剪切、拷贝、粘贴等常用功能。处理文本越界的代码如下:
if (LOWORD (wParam) == 1)
if(HIWORD (wParam) == EN_ERRSPACE || HIWORD (wParam) == EN_MAXTEXT)
MessageBox (hwnd, "Edit control out of space.",szAppName, MB_OK | MB_ICONSTOP) ;
当文本内存空间不够或者输入的字符数目大于最大设置的数目时,将弹出出错消息框。程序编译、运行后,首先弹出密码对话框,如图所示。
当用户输入的密码有误时,则弹出消息框,把用户输入的密码文本显示出来,当单击“确定”按钮后,则显示密码输入错误的消息,单击“确定”或“取消”按钮,退出本程序。如果密码输入正确,就弹出应用程序的主窗口,如图所示。
可以在编辑框里输入文本,也可以从剪贴板上粘贴文本,当右击选中的某段文本后,则弹出浮动菜单。
编辑控件实例2
#include <windows.h>
HINSTANCE hInst;
HWND hMainWnd;
HWND hCtl;
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
hInst = hInstance;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance,IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL,IDC_ARROW);
wcex.hbrBackground = (HBRUSH)COLOR_WINDOW;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "MainWndClass";
wcex.hIconSm = LoadIcon(hInstance,IDI_APPLICATION);
if(!RegisterClassEx(&wcex)) return FALSE;
int SW_XFS = GetSystemMetrics(SM_CXSCREEN);
int SW_YFS = GetSystemMetrics(SM_CYSCREEN);
hMainWnd = CreateWindowEx(WS_EX_CLIENTEDGE,
"MainWndClass",
"Main window of the edit control",
WS_OVERLAPPEDWINDOW,
0, 0, SW_XFS, SW_YFS,
NULL,
NULL,
hInstance,
NULL);
if(!hMainWnd) return FALSE;
ShowWindow(hMainWnd,nCmdShow);
UpdateWindow(hMainWnd);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static int wwp,whp;
RECT rect;
switch(message)
{
case WM_CREATE:
GetClientRect(hWnd,&rect);
wwp = rect.right-rect.left;
whp = rect.bottom-rect.top;
hCtl = CreateWindowEx(WS_EX_CLIENTEDGE,
"EDIT",
NULL,
WS_CHILD|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE
|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL,
wwp/4, whp/4, wwp/2,whp/2,hWnd,
NULL, hInst, NULL);
if(!hCtl) PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
return 0;
}
列表框
列表框允许用户从多个对象中选择一项或多项,这些对象可以是文本、文件和位图等。当列表框的项不能全部显示出来时,可以用滚动条来滚动显示。
1. 基础知识
默认的列表框只允许用户单选,需要多选时,须把列表框的风格定义为 LBS_ MULTIPLESEL 和 LBS_EXTENDEDSEL 。列表框提供的其他风格取值可以控制列表框的外观和操作。例如是否按照列表框各项的名称排序,是否多行排列,是否有滚动条等。
当用户对列表框进行了操作时,就会向主窗口发送一条消息。列表框的消息类型比较简单,主要是单击、双击和选择等。同编辑框一样,列表框也会遇到内存不够的问题,所以消息类型中含有这一项。消息总是通过WM_COMMAND的形式发送给主窗口的。其中,wParam的低位字节表示列表框的标识符,高位字节表示消息的类型,lParam表示主窗口句柄。列表框的消息类型如表所示。
列表框也是通过调用函数CreateWindow来创建的,第一参数设置为ListBox即可。风格取值可以取表所示的值。在主窗口里的消息一般是在 WM_ COMMAND里处理表中以LBN开头的消息。下面以一个具体的例子介绍列表框的常见操作。
2.应用程序举例列表框的应用:
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#define MAXENV 4096
static char szAppName[]="Environ";
//预先申明消息处理、申请窗口类以及应用程序初始化的函数
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
//函数:WinMain
//作用:主应用函数
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
MSG msg ;
//申请窗口类
MyRegisterClass(hInstance);
//应用程序的初始化
if(!InitInstance(hInstance,iCmdShow)) return FALSE;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
return RegisterClassEx (&wndclass) ;
}
//函数:InitInstance 作用:初始化应用程序
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hwnd ;
hwnd = CreateWindow(szAppName, "Environ List Box",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
if(!hwnd) { return FALSE; }
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
return TRUE;
}
//函数:WndProc
//作用:消息处理函数
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
//定义字符串变量,必须是静态变量
static char szBuffer[MAXENV + 1] ;
static HWND hwndList, hwndText,hwndEdit,AddButton,DeleteButton;
//定义设备描述表句柄
HDC hdc ;
int i ;
//定义文本区域尺寸
TEXTMETRIC tm ;
switch (iMsg)
{
case WM_CREATE :
//获取设备描述表句柄
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
//创建列表框,第一个参数"ListBox"表示将创建列表框
hwndList = CreateWindow("ListBox", NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD|LBS_SORT|WS_VSCROLL,
tm.tmAveCharWidth*4, tm.tmHeight * 3,
tm.tmAveCharWidth * 30 + GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 10,
hwnd, (HMENU) 1,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ;
//建立静态文本框,第一个参数"static“表示将建立静态文本框
hwndText = CreateWindow("static", NULL,
WS_CHILD | WS_VISIBLE | SS_LEFT,
tm.tmAveCharWidth*2, tm.tmHeight-10,
tm.tmAveCharWidth * MAXENV/2, tm.tmHeight,
hwnd, (HMENU) 2,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ;
//建立编辑框,主要用来编辑向
//列表框添加的文本
hwndEdit = CreateWindow("edit","ItemEdit",//定义初始值为"ItemEdit"
WS_CHILD | WS_VISIBLE |WS_BORDER | ES_LEFT | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
tm.tmAveCharWidth * 35+GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 3,
tm.tmAveCharWidth*20+GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 2,
hwnd, (HMENU)3,
((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
//创建添加按钮,当按下该按钮时,列表框添加编辑框里的文本
AddButton = CreateWindow ("button","Add",
WS_CHILD | WS_VISIBLE |BS_PUSHBUTTON,
tm.tmAveCharWidth *39,
tm.tmHeight*6,
tm.tmAveCharWidth*9,
tm.tmHeight*2,
hwnd, (HMENU)4,
((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
//创建删除按钮,当按下按钮时,列表框里
//的当前项被删除
DeleteButton= CreateWindow ("button","Del",
WS_CHILD | WS_VISIBLE |BS_PUSHBUTTON,
tm.tmAveCharWidth*50,
tm.tmHeight*6,
tm.tmAveCharWidth*9,
tm.tmHeight*2,
hwnd, (HMENU)5,
((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
//添加一个列表框选项
SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM)"good") ;
return 0;
case WM_SETFOCUS :
//将输入焦点设置在编辑框
SetFocus (hwndEdit) ;
return 0 ;
case WM_COMMAND :
//显示列表框里选中的项
if (LOWORD (wParam) == 1 && HIWORD (wParam) == LBN_SELCHANGE)
{
i = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
i = SendMessage (hwndList, LB_GETTEXT, i,(LPARAM) szBuffer) ;
SetWindowText (hwndText, szBuffer);
return 0;
}
switch(LOWORD(wParam))
{
//当单击增加按钮时,当前编辑框里的文本
//被增加到列表框里,并自动排序
case 4:
GetDlgItemText(hwnd,3,szBuffer,10);
SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) szBuffer) ;
return 0;
case 5: //当单击删除按钮时,则当前列表
//框里的选中的项被删除获取当前选中的项
//的位置值
i = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
//发送删除消息
SendMessage(hwndList,LB_DELETESTRING,i,wParam);
//选中上一个项
SendMessage (hwndList, LB_SETCURSEL,i-1,0) ;
default:
return 0;
}
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
本应用程序主要实现列表框的创建、选项的删除和添加等功能。在程序中分别创建了五个子窗口,它们分别是静态文本框、编辑框、列表框和两个按钮。
静态文本框也属于子窗口,用CreateWindow函数创建时只需要把第一个参数设置为Static即可,调用代码如下:
hWndText = CreateWindow(“static”, NULL,
WS_CHILD|WS_VISIBLE|SS_LEFT,
tm.tmAveCharWidth*2,tm.tmHeight-10,
tm.tmAveCharWidth*MAXENV,tm.tmHeight,
hWnd, (HMENU)2,
(HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE),
NULL);
其中第二个参数设置为NULL表示静态文本框的文本初始值为空,它的主要作用是显示当前列表框被选中项的名称。编辑框主要用来编辑需要增加项的名称。创建列表框的代码如下:
hwndList = CreateWindow("ListBox", NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD|LBS_SORT|WS_VSCROLL,
tm.tmAveCharWidth*4, tm.tmHeight * 3,
tm.tmAveCharWidth * 30 + GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 10,
hwnd, (HMENU) 1,
(HINSTANCE) GetWindowLong (hwnd,
GWL_HINSTANCE),NULL) ;
由第三个参数的设置可知,列表框只能单选,可自动排序,并带有垂直滚动条。创建列表框后,向列表框增加一项。名称为good,可用如下代码:
SendMessage(hWndList,LB_ADDSTRING,0,(LPARAM)"good");
两个按钮的名称分别为Add和Del,其创建过程在前节中已有详细介绍,这里不再剖析。
本应用程序的消息处理比较复杂,它包括跟踪当前列表框选中的项,并在静态文本框里显示出来;从编辑框里取出文本;向列表框增加项,删除当前选中的项等。
显示当前列表框选中的项的代码如下:
if (LOWORD (wParam) == 1 && HIWORD (wParam) == LBN_SELCHANGE)
{
i = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
i = SendMessage (hwndList, LB_GETTEXT, i,(LPARAM) szBuffer) ;
SetWindowText (hwndText, szBuffer);
return 0;
}
程序首先获得当前选中项的序号,然后得到当前选中项的文本,并把文本拷贝到字符串指针szBuffer中,最后,用函数SetWindowText发送到静态文本框,从而实现了列表框选项的显示。
当用户按下Add按钮后,将把编辑框里当前的文本增加进列表框,并重新排序,代码如下:
case 4:
GetDlgItemText(hWnd,3,szBuffer,10);
SendMessage(hWndList,LB_ADDSTRING,0,(LPARAM)SzBuffer);
return 0;
首先从编辑框中取得文本,然后向列表框发送LB_ADDSTRING消息,把文本增加到列表框里,同时由于列表框在创建时具有LBS_SORT风格,所以列表框在增加了新的选项后立即自动排序,用户只能看到在新的排序下增加的选项的情况。
当用户按下Del按钮后,将把选中的选项删除,代码如下:
case 5: //当单击删除按钮时,则当前列表框里的选中的项被删除
//获取当前选中的项的位置值
i = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
//发送删除消息
SendMessage(hwndList,LB_DELETESTRING,i,wParam);
//选中上一个项
SendMessage (hwndList, LB_SETCURSEL,i-1,0) ;
首先取得当前选项的序号,然后向列表框发送LB_ DELETESTRING消息,这样就删除了指定的选项。然后又向列表框发送LB_SETCURSEL消息,使当前焦点自动转移到刚删除的选项的上一项。程序编译、运行后出现如图所示的界面。
当按下Add按钮后,将向列表框添加一项;也可以按下Del键,从而删除选中的那如图所示。
组合框
组合框兼具编辑框和列表框的功能,既能编辑选项,又能显示多个项。在Windows程序设计中可以见到大量组合框的应用实例,例如文件对话框里的目录搜索组合框。
1.基础知识
组合框的风格主要有三种,分别是简单组合框( Simple ComboBox)、下拉式组合框(DropDown ComboBox)和下拉式列表框( DropDown ListBox)。
下拉式列表框和下拉式组合框平时只显示编辑区域,只在打开时才显示组合框的各项,这样有利于节省屏幕空间。这三种组合框的基本功能如表所示。
组合框的风格取值定义了组合框的具体属性,包括是否自动排序,是否有滚动条。这些风格取值如表所示。
创建一个组合框只需把CreateWindow的第一个参数设置为ComboBox,然后取表中的值即可。组合框创建后,需要初始化,即通过向组合框发送CB_ADDSTRING增加最初的项,这类似于列表框。如果没有定义CBS_SORT风格,新增的项将被增加到组合框的末尾。
应用程序的父窗口主要通过 WM_COMMAND消息与组合框通信,应用程序可以用CB_FINDSTRINGEXACT搜索指定的项,还可以发送CB_DELETESTRING删除指定的项,当需要删除所有的项时,发送消息CB_RESETCONTENT即可。
组合框的编辑区域用来显示当前选中的项或者编辑组合框里没有的项。可以用CB_LIMITTEXT来限制输入文本的大小;为了获得编辑区域的文本,可发送CB_GETTEXT消息,这样就把文本复制到指定的字符串中,当需要设置编辑区域的文本时,只需要发送CB_SETTEXT消息。
Windows API为组合框提供了文件显示和搜索的功能,它们主要通过函数DlgDirListComboBox和DlgDirSelectComboBox来实现。本节的应用程序中将用到这些函数,并把文件的内容显示在窗口里。
2.应用程序举例
组合框的应用:
#include <windows.h>
#include <string.h>
#include <direct.h>
#define MAXPATH 256
#define MAXREAD 8192
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ListProc (HWND, UINT, WPARAM, LPARAM) ;
WNDPROC fnOldList;
//定义应用程序的名字
static char szAppName[] = "Head" ;
//预先申明消息处理、申请窗口类以及应用程序初始化的函数
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
//函数:WinMain
//作用:主应用函数
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
MSG msg ; //申请窗口类
MyRegisterClass(hInstance); //应用程序的初始化
if(!InitInstance(hInstance,iCmdShow)) {return FALSE;}
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
//函数:MyRegisterClass
//作用:详细定义申请窗口类
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
return RegisterClassEx (&wndclass) ;
}
//函数:InitInstance 作用:初始化应用程序
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hwnd ;
hwnd = CreateWindow(szAppName, "组合框",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
if(!hwnd) {return FALSE;}
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
return TRUE;
}
//函数:WndProc
//作用:消息处理
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
//定义文件是否合法的标志
static BOOL bValidFile ;
//定义文件存放字符串和文件名字符串
static char sReadBuffer[MAXREAD],szFile[MAXPATH] ;
//定义目录列表框和文件名文本框
static HWND hwndList, hwndText ;
static OFSTRUCT ofs ;
//定义文本显示区域
static RECT rect ;
char szBuffer[MAXPATH + 1] ;
HDC hdc ;
int iHandle, i ;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;
switch (iMsg)
{
case WM_CREATE :
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
rect.left = 1* tm.tmAveCharWidth ;
rect.top = 3 * tm.tmHeight ;
//建立组合框
hwndList = CreateWindow("ComboBox", NULL,
WS_CHILDWINDOW | WS_VISIBLE | CBS_AUTOHSCROLL|CBS_SORT,
tm.tmAveCharWidth*40, tm.tmHeight * 3,
tm.tmAveCharWidth * 13 +GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 10,
hwnd, (HMENU) 1,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ;
//建立静态文本框,显示文件内容
hwndText = CreateWindow("static", getcwd (szBuffer, MAXPATH),
WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,
tm.tmAveCharWidth, tm.tmHeight,
tm.tmAveCharWidth * MAXPATH, tm.tmHeight,
hwnd, (HMENU) 2,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ;
//建立组合框的消息处理函数对应机制,其中最后一个参数"ListProc"
//表示组合框的消息处理函数名称,这样就使组合框的事件和处理联系起来
fnOldList = (WNDPROC) SetWindowLong (hwndList, GWL_WNDPROC, (LPARAM) ListProc) ;
//"*.*"表示组合框中的上一级目录
SendMessage (hwndList, CB_DIR, 0x37, (LPARAM) "*.*") ;
return 0 ;
//取得窗口的尺寸,并赋值给矩形变量
case WM_SIZE :
rect.right = (LOWORD (lParam))/2 ;
rect.bottom = HIWORD (lParam) ;
return 0 ;
case WM_SETFOCUS :
SetFocus (hwndList) ;//设置输入焦点
return 0 ;
case WM_COMMAND :
if(LOWORD(wParam) == 1 && HIWORD (wParam) == CBN_DBLCLK)
{
//跟踪组合框的选项
if(CB_ERR==(i=SendMessage(hwndList,CB_GETCURSEL, 0, 0L)))
break ;
//把组合框当前选项传送到字符串
SendMessage(hwndList, CB_GETLBTEXT, i,(LPARAM) szBuffer) ;
//判断是否能打开文件
if (-1 != OpenFile (szBuffer, &ofs, OF_EXIST | OF_READ))
{
bValidFile = TRUE ;
//把文件中的内容送给字符串
strcpy (szFile, szBuffer) ;
getcwd (szBuffer, MAXPATH) ;
if (szBuffer [strlen (szBuffer) - 1] != '\\') strcat (szBuffer, "\\") ;
//显示文件目录和名称
SetWindowText (hwndText, strcat (szBuffer, szFile)) ;
}
else
{
bValidFile = FALSE ;
szBuffer [strlen (szBuffer) - 1] = '\0' ;
chdir (szBuffer + 1) ;
getcwd (szBuffer, MAXPATH) ;
SetWindowText (hwndText, szBuffer) ;
SendMessage (hwndList, CB_RESETCONTENT, 0, 0L) ;
SendMessage (hwndList, CB_DIR, 0x37, (LONG) "*.*") ;
}
InvalidateRect (hwnd, NULL, TRUE) ;//重新绘制窗口
}
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetTextColor (hdc, GetSysColor(COLOR_BTNTEXT)) ;
SetBkColor (hdc, GetSysColor (COLOR_BTNFACE)) ;
//判断是否能打开文件
if (bValidFile && -1 != (iHandle =OpenFile (szFile, &ofs, OF_REOPEN | OF_READ)))
{
i = _lread(iHandle,sReadBuffer,MAXREAD) ;
_lclose (iHandle) ;
//在矩形区域内显示文件内容
DrawText (hdc, sReadBuffer, i, &rect,
DT_WORDBREAK |DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX) ;
}
else bValidFile = FALSE ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
//定义组合框的消息处理函数
LRESULT CALLBACK ListProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
if (iMsg == WM_KEYDOWN && wParam == VK_RETURN)
//判断是否有键按下,在把消息送给主窗口处理
SendMessage (GetParent (hwnd), WM_COMMAND, 1,MAKELONG (hwnd, CBN_DBLCLK)) ;
return CallWindowProc (fnOldList, hwnd, iMsg, wParam, lParam) ;
}
本应用程序主要利用组合框的文件搜索功能自动显示文件内容。
程序首先创建组合框,代码如下:
hwndList = CreateWindow("ComboBox", NULL,
WS_CHILDWINDOW | WS_VISIBLE | CBS_AUTOHSCROLL|CBS_SORT,
tm.tmAveCharWidth*40, tm.tmHeight * 3,
tm.tmAveCharWidth * 13 + GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 10,
hwnd, (HMENU) 1,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ;
由第三个参数的设置可看出,创建的组合框能自动排序,并有垂直滚动条。
然后组合框当前选中项的文本显示到静态文本框里,代码如下:
SendMessage(hwndList,CB_GETLBTEXT,i,(LPARAM) szBuffer) ;
SetWindowText (hwndText, strcat (szBuffer, szFile)) ;
最后显示文件的内容,代码如下:
if(bValidFile && -1!=(iHandle=OpenFile(szFile,&ofs, OF_REOPEN | OF_READ)))
{
i = _lread (iHandle, sReadBuffer, MAXREAD) ;
_lclose (iHandle) ;
//在矩形区域内显示文件内容
DrawText (hdc, sReadBuffer, i, &rect,
DT_WORDBREAK |DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX) ;
}
程序首先打开文件,并把文件的内容读人sReadBuffer字符串,然后再用DrawText函数显示出来。
滚动条
滚动条既可以是许多子窗口(如编辑框、列表框)的附件,又可以独立成为子窗口。
1.基础知识
滚动条的主要用途在于对某个在一定范围内变化的属性值或者变量进行动态设置。例如用滚动条可以方便地控制颜色的深浅,设置线条的宽度;滚动条也用来显示某个任务的进度,这样滚动条又被称为进度条。
滚动条的风格如表所示。
滚动条的消息类型如表所示。
滚动条有一些重要的函数和方法,下面分别介绍。
用来设置滚动条类型和活动状态的函数是EnableScrollBar,其原型定义如下:
BOOL EnableScrollBar(
HWND hwnd // 指向父窗口或者滚动条的句柄
UINT wSBflags,//标志滚动条的类型
UINT wArrows //滚动条的滚动按钮设置
);
wSBflag用来设置滚动条的类型,可以取表所示的任意值。
wSBflag的取值参数
wArrows设置滚动条滚动按钮的活动状态,取值如表所示。
显示或隐藏滚动条的函数是ShowScrollBar,
其原型定义如下:
BOOL ShowScrollBar(
HWND hwnd ,//指向父窗日的句柄
int wBar ,//滚动条活动状态的标志
BOOL bShow//滚动条是否可见,当为TRUE时可见,相反则隐藏
);
其中参数 wBar取值如表所示。
2.应用程序举例
滚动条的应用:
#include <windows.h>
#include <stdlib.h>
LRESULT CALLBACK ScrollProc (HWND, UINT, WPARAM, LPARAM) ;
WNDPROC fnOldScr[3] ;
//定义全局变量,包括滚动条、标签、
// 颜色值和客户区
HWND hwndScrol[3], hwndLabel[3],HWND hwndValue[3], hwndRect ;
int color[3], iFocus,i;
//定义三种颜色
static char *szColorLabel[] = { "红色", "绿色", "蓝色" } ;
static char szAppName[]="颜色调整";
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
//函数:WinMain
//作用:主应用函数
Int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
MSG msg ;
//注册窗口类
MyRegisterClass(hInstance);
//应用程序的初始化
if(!InitInstance(hInstance,iCmdShow))
{
return FALSE;
}
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
//函数:MyRegisterClass
//作用:注册窗口类
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground =(HBRUSH)GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
return RegisterClassEx (&wndclass) ;
}
//函数:InitInstance
//作用:初始化应用程序
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hwnd ;
hwnd = CreateWindow(szAppName, "颜色选择",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
return TRUE;
}
//函数:WndProc
//作用:消息处理函数
LRESULT CALLBACK WndProc (HWND hwnd,UINT iMsg, WPARAM wParam, LPARAM lParam)
{//定义颜色结构变量
static COLORREF crPrim[3] = { RGB (255, 0, 0), RGB (0, 255, 0),RGB (0, 0, 255) } ;
static HBRUSH hBrush[3], hBrushStatic ;
static int cyChar ;
//定义颜色改变区域
static RECT rcColor;
char szbuffer[10] ;
int i, cxClient, cyClient ;
//定义静态文本区域
HWND hwndstatic;
HINSTANCE hInstance;
hInstance=(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE)
switch (iMsg)
{
case WM_CREATE :
for (i = 0 ; i < 3 ; i++) hBrush[i] = CreateSolidBrush (crPrim[i]) ;
//定义画刷
hBrushStatic = CreateSolidBrush ( GetSysColor (COLOR_BTNHIGHLIGHT)) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;
//创建文本区域,用来存放滚动条
hwndRect = CreateWindow("static", NULL,
WS_CHILD | WS_VISIBLE | SS_WHITERECT, 0, 0, 0, 0,
hwnd, (HMENU) 9, hInstance, NULL) ;
//创建文本区域,显示应用程序当前状态
hwndstatic = CreateWindow("static","颜色调整",
WS_CHILD | WS_VISIBLE|SS_CENTER,
400,300,100,30,
hwnd, (HMENU) 9, hInstance, NULL) ;
//用For 循环来苏实现滚动条、标签、数值的显示
for (i = 0 ; i < 3 ; i++)
{
hwndScrol[i] = CreateWindow("scrollbar", NULL,
WS_CHILD | WS_VISIBLE |SBS_HORZ,
0, 0, 0, 0,
hwnd, (HMENU) i, hInstance, NULL) ;
hwndLabel[i] = CreateWindow("static", szColorLabel[i],
WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 0, 0,
hwnd, (HMENU) (i + 3), hInstance, NULL) ;
hwndValue[i] = CreateWindow("static", "0",
WS_CHILD | WS_VISIBLE | SS_CENTER,
0,0,0,0,
hwnd, (HMENU) (i + 6), hInstance, NULL) ;
fnOldScr[i] = (WNDPROC) SetWindowLong (hwndScrol[i], GWL_WNDPROC,(LONG) ScrollProc) ;
//设置滚动条滚动范围
SetScrollRange (hwndScrol[i], SB_CTL, 0, 255,FALSE) ;
//设置滚动条初始位置
SetScrollPos (hwndScrol[i], SB_CTL, 20,FALSE) ;
}
return 0 ;
case WM_SIZE :
//获取客户区大小
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
//设置颜色变化区域
SetRect (&rcColor, 0, 0, cxClient/2, cyClient) ;
MoveWindow (hwndRect, cxClient/2,0,cxClient / 2, cyClient, TRUE) ;
//设置滚动条的位置
for (i = 0 ; i < 3 ; i++)
{
MoveWindow (hwndScrol[i],
cxClient/2+60,(i+2)*cyClient/6-100,
cxClient/3,
cyClient/12,TRUE) ;
MoveWindow (hwndLabel[i],
cxClient/2+20,(i+2)*cyClient/6-100,
40,cyClient/12, TRUE) ;
MoveWindow (hwndValue[i],
cxClient-40,(i+2)*cyClient/6-100,
40, cyClient/12, TRUE) ;
}
SetFocus (hwnd) ;
return 0 ;
case WM_SETFOCUS :
SetFocus (hwndScrol[iFocus]) ;
return 0;
case WM_HSCROLL :
i = GetWindowLong ((HWND) lParam, GWL_ID) ;
//设置滚动条滚动的步长
switch (LOWORD (wParam))
{
case SB_PAGEDOWN :
color[i] += 15 ;
case SB_LINEDOWN :
color[i] = min (255, color[i] + 1) ;
break ;
case SB_PAGEUP :
color[i] -= 15 ;
case SB_LINEUP :
color[i] = max (0, color[i] - 1) ;
break ;
case SB_TOP :
color[i] = 0 ;
break ;
case SB_BOTTOM :
color[i] = 255 ;
break ;
case SB_THUMBPOSITION :
case SB_THUMBTRACK :
color[i] = HIWORD (wParam) ;
break ;
default :
break ;
}
//从滚动条的位置读取颜色值
SetScrollPos (hwndScrol[i], SB_CTL,color[i], TRUE) ;
//显示颜色值
SetWindowText (hwndValue[i], itoa (color[i],szbuffer, 10)) ;
//释放画刷资源
DeleteObject ((HBRUSH);
SetClassLong(hwnd, GCL_HBRBACKGROUND,(LONG);
CreateSolidBrush(RGB (color[0], color[1], color[2])))) ;
//重画颜色变化区域
InvalidateRect (hwnd, &rcColor, TRUE) ;
return 0 ;
case WM_CTLCOLORSCROLLBAR :
//获取当前活动资源的标识符
i = GetWindowLong ((HWND) lParam, GWL_ID) ;
return (LRESULT) hBrush[i] ;
case WM_CTLCOLORSTATIC :
//获取当前活动资源的标识符,如果大于3且小于8则读取系统颜色值
i = GetWindowLong ((HWND) lParam, GWL_ID) ;
if (i >= 3 && i <= 8)
{
SetTextColor ((HDC) wParam, crPrim[i % 3]) ;
SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNHIGHLIGHT));
return (LRESULT) hBrushStatic ;
}
break ;
case WM_SYSCOLORCHANGE :
DeleteObject (hBrushStatic) ;
hBrushStatic = CreateSolidBrush ( GetSysColor (COLOR_BTNHIGHLIGHT)) ;
return 0 ;
case WM_DESTROY :
//释放画刷资源
DeleteObject ((HBRUSH);
SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG) GetStockObject (WHITE_BRUSH))) ;
for (i = 0 ; i < 3 ; DeleteObject (hBrush[i++])) ;
DeleteObject (hBrushStatic) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
//函数:ScrollProc
//作用:滚动条消息处理
LRESULT CALLBACK ScrollProc (HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
int i = GetWindowLong (hwnd, GWL_ID) ;
switch (iMsg)
{
case WM_KEYDOWN :
//响应TAB键,当i小于3时,则转向下一个滚动条,否则重新开始
if(wParam == VK_TAB) SetFocus(hwndScrol[(i+(GetKeyState(VK_SHIFT)< 0 ? 2 : 1))%3]) ;
break ;
case WM_SETFOCUS :
iFocus = i ;
break ;
}
Return CallWindowProc(fnOldScr[i],hwnd,iMsg,wParam,lParam);
}
本应用程序的主要功能是创建三个滚动条,分别控制红、黄、蓝三种颜色的深浅。
程序在消息循环函数中首先创建滚动条,代码如下:
hwndScrol[i] = CreateWindow ("scrollbar", NULL,
WS_CHILD | WS_VISIBLE |SBS_HORZ,0, 0, 0, 0,
hwnd, (HMENU) i, hInstance, NULL) ;
第一个参数为“scrollbar”,表示创建的子窗口是滚动条;第三个参数中的SBS_ HORZ表示滚动条是水平的;由于有三个滚动条将被创建,所以第九个参数为(HMENU)i,作为滚动条的标识符。
滚动条有自己的消息处理函数,但是必须在应用程序中指定消息处理函数的句柄,并分配给相应的滚动条,代码如下:
fnOldScr[i] = (WNDPROC) SetWindowLong ( hwndScrol[i], GWL_WNDPROC, (LONG) ScrollProc) ;
第一个参数hWndScrol为滚动条的名称,第三个参数ScrollProc则为指向滚动条消息处理函数的指针。
创建滚动条后,需要对它初始化,包括设置滚动条的初始位置以及滚动条滚动的范围,代码如下:
SetScrollRange (hwndScrol[i], SB_CTL, 0, 255,FALSE) ;
//设置滚动条初始位置
SetScrollPos (hwndScrol[i], SB_CTL, 20,FALSE) ;
其中,SetScrollRange函数的原型定义如下:
BOOL SetScrollRange(HWND hwnd,//指向父窗口的句柄
Int nBar,//滚动条的活动状态
Int nMinPos, //最小值
int nMaxPos, //最大值
BOOL bRedraw //重画的标志);
SetScrollPos用来设置滚动条初始位置值,原型定义如下:
int SetScrollPos( HWND hwnd ,//指向父窗口的句柄
int nBar, // 设置滚动条的活动状态
int nPos, // 设置滚动条位置值
BOOL bRedraw //重画的标志 );
当SetScrollPos函数执行成功后,将返回原来的位置值。初始化滚动条后,滚动条就能响应用户的操作,这些操作包括用户按下PageDown、PageUp以及方向键,而鼠标的拖动则由滚动条自动处理。
滚动条消息处理的代码如下:
case WM_HSCROLL:
I=GetWindowLong((HWND)lParam,GWL_ID);
SWitCh(LOWORD (Wpgram))
{
case SB_PAGEDOWN:
color[i]+=15
代码中首先判断用户操作的消息类型是否为WMNSCROLL,注意,如果创建滚动条时定义的风格为SB_VERT,则该消息类型应该为WM_VSCROLL。然后得到当前滚动条的标识符,消息中参数wParam的低位字节包含了消息的通知代码,例如程序中的SB_ PAGEDOWN、SB_PAGEUP、SB_LINEDOWN、SB_TOP。它们分别表示用户对键盘的操作。滚动条每次拖动的步长为15。
程序运行结果如图所示。
按钮控件实例2
#include <windows.h>
#define IDE_AUTOCHECKBOX 100
#define IDE_AUTORADIOBUTTON 200
#define IDE_AUTO3STATE 300
#define IDE_CHECKBOX 400
#define IDE_DEFPUSHBUTTON 500
#define IDE_PUSHBUTTON 600
#define IDE_RADIOBUTTON 700
HWND hWnd;
HWND hCtlButton[8];
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon= LoadIcon(NULL,(LPCTSTR)IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL,IDC_ARROW);
wcex.hbrBackground = (HBRUSH)COLOR_WINDOW;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "WndCls";
wcex.hIconSm = LoadIcon(NULL,(LPCTSTR)IDI_APPLICATION);
if(!RegisterClassEx(&wcex)) return FALSE;
int SW_XFS = GetSystemMetrics(SM_CXSCREEN);
int SW_YFS = GetSystemMetrics(SM_CYSCREEN);
hWnd = CreateWindowEx(NULL,
"WndCls",
"Demo of Button Control",
WS_OVERLAPPEDWINDOW,
0,
0,
SW_XFS,
SW_YFS-25,
NULL,
NULL,
hInstance,
NULL);
if(!hWnd) return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
?
hCtlButton[0] = CreateWindowEx( NULL, "BUTTON", "自动复选框(方框)",
WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
10,
10,
200,
30,
hWnd,
(HMENU)IDE_AUTOCHECKBOX,
hInstance,
NULL);
hCtlButton[1] = CreateWindowEx( NULL,"BUTTON",
"自动复选框(园框)",
WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON,
10, 40,200, 30,
hWnd,
(HMENU)IDE_AUTORADIOBUTTON,
hInstance,
NULL);
hCtlButton[2] = CreateWindowEx( NULL,"BUTTON",
"自动复选框(园框)",
WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON,
10,70, 200,30,
hWnd,
(HMENU)IDE_AUTORADIOBUTTON,
hInstance,
NULL);
hCtlButton[3] = CreateWindowEx( NULL,"BUTTON",
"三态复选框(方框)",
WS_CHILD|WS_VISIBLE|BS_AUTO3STATE,
10,100,200,30,
hWnd,
(HMENU)IDE_AUTO3STATE,
hInstance,
NULL);
hCtlButton[4] = CreateWindowEx(NULL,"BUTTON",
"复选框(方框)",
WS_CHILD|WS_VISIBLE|BS_CHECKBOX,
10,130,200,30,
hWnd,
(HMENU)IDE_CHECKBOX,
hInstance,
NULL);
hCtlButton[5] = CreateWindowEx(NULL,"BUTTON",
“下压式按钮”,
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
10,160,200,30,
hWnd,
(HMENU)IDE_DEFPUSHBUTTON,
hInstance,
NULL);
hCtlButton[6] = CreateWindowEx(NULL,"BUTTON",
“下压式按钮”,
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
10,190,200,30,
hWnd,
(HMENU)IDE_PUSHBUTTON,
hInstance,
NULL);
hCtlButton[7] = CreateWindowEx(NULL,"BUTTON",
“复选框(园框)”,
WS_CHILD|WS_VISIBLE|BS_RADIOBUTTON,
10,220,200,30,
hWnd,
(HMENU)IDE_RADIOBUTTON,
hInstance,
NULL);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
return 0;
}
- 第八章 子窗体控件
- 子窗体访问父窗体控件
- # winform 用子窗体刷新父窗体,子窗体改变父窗体控件的值
- C# winform 用子窗体刷新父窗体,子窗体改变父窗体控件的值
- winform 用子窗体刷新父窗体,子窗体改变父窗体控件的值
- 实现子线程上操作窗体控件
- WPF获取子、父窗体控件
- 子窗体中操作主窗体上的控件
- Access子窗体引用父窗体的控件
- js 子窗体获取父窗体控件中的值
- 子窗体如何调用父窗体的控件?
- C# 子窗体向父窗体控件传值
- c# 【委托】子窗体调用父窗体控件实例
- winform在子窗体调用父窗体的控件
- 子窗体向父窗体控件传值
- C# MDI 子窗体被父窗体控件挡住
- C#父窗体跟子窗体的控件操作
- 子窗体在父窗体指定的控件中显示
- makefile .PHONY 伪目标
- google checkout android/java 编程
- linux sudo 命令详解
- 析构函数的使用与调用
- VBA 合并单元格
- 第八章 子窗体控件
- java和.net 交互加密解密
- 图像处理的一些资料(1)【引】
- UVa 573 - The Snail
- hdu 1827 强连通缩点
- new Bookmark
- SQL语句中插入标识列获取标识ID的两种方式
- 32位系统下编译Android2.3系统需要做得更改
- Android自动化测试工具——Monkey