第四章:Windows 图形界面
1.1 了解窗口
在图形化基于视窗的应用程序里,窗口就是屏幕上一块可视区域,应用程序的窗口包括标题栏,菜单栏,Windows系统菜单,最小化按钮,最大化按钮,恢复按钮,关闭按钮,可改变大小的边框,窗口客户区,垂直滚动条,水平滚动条.
窗口客户区是应用程序显示输出部分
1.2 窗口的创建
1.21 创建Win32工程和MessageBox函数
Windows 应用程序的主函数是:
int APIENTRY WinMain(HINSTANCE hInstance, //应用程序的实例句柄
HINSTANCE hPrevInstance, //Win16留下的废物,不用参数
LPSTR lpCmdLine, 命令行参数
int nCmdShow) //主窗口初始化的显示方式
Windows 弹出对话框的函数是:
::MessageBox(HWND hwnd, //一个窗口句柄,指定的对话框属于哪一个窗口所有
//设为NULL,表示没有窗口拥有该对话框
LPCSTR lpText, //对话框的正文
LPCSTR lpCaption, //对话框的标题
UINT uType) //对话框显示按钮种类和行为
nType 指示了对话框显示按钮的种类和行为,可以设成如下的值:
1: MB_OK 确定按钮
2: MB_OKCANCEL 包括两个按钮:确定和取消按钮
3: MB_ABORTRETRYIGNORE 包括三个按钮:终止,调试和忽略
4: MB_YESNOCANCEL 包括三个按钮:是,否和取消
5: MB_YESNO 是和否按钮
6: MB_RETRYCANCEL 重试和取消按钮
7: MB_ICONHAND 一个停止标志图标
8: MB_ICONQUESTION 一个询问标志图标
9: MB_ICONEXCLAMATION 一个感叹号图标
10: MB_DEFBUTTON1 第一个按钮是选中按钮
11: MB_DEFBUTTON2 第二个按钮是选中按钮
12: MB_DEFBUTTON3 第三个按钮是选中按钮
13: MB_DEFBUTTON4 第四个按钮是选中按钮
MessageBox 函数返回被选中按钮的ID号,ID号为一个整形数值,这个宏在WINUSER.H中定义:
ID号 = ID + 按钮单词
如果确定按钮被选中,将返回:IDOK
示例代码:
#include <windows.h> int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ int nSet = ::MessageBox(NULL,"Hello world","标题",MB_YESNOCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON3); if(nSet == IDYES) { ::MessageBox(NULL,"用户选择了是按钮","标题",MB_OK); } else if(nSet == IDNO) { ::MessageBox(NULL,"用户选择了否按钮","标题",MB_OK); } else if(nSet == IDCANCEL) { ::MessageBox(NULL,"用户选择了取消按钮","标题",MB_OK); } return 0;}
1.22 Windows 的消息驱动
创建窗口后,就要对窗口的行为负责,比如用户拖动窗口时,应跟随鼠标移动这个窗口.如果不这么做,程序将失去窗口界面的友好性,但是,如何知道用户在窗口上的动作呢
是操作系统告诉程序的,Windows不断向程序发送消息,通知用户在窗口上的动作
当 Windows向程序发送消息时,它调用程序中的一个函数,这个函数称为消息处理函数,它是一个自定义的回调函数,原形如下:
LRESULT CALLBACK WinProc(HWND hwnd, //窗口句柄
UINT message, //消息ID号
WPARAM wParam, //消息参数,其值取决于消息//的类型
LPARAM lParam) //消息参数,其值取决于消息
//的类型
例如,一般的应程序接受到 WM_CLOSE 消息时会试图销毁自己的窗口,下面代码为了关闭了记事本程序,向它的主窗口发送了 WM_CLOSE 消息,运行这个程序之前请先新建一个文本文档,然后再打开这个文本文档.
#include <windows.h> int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ HWND hwnd; BOOL bStart = FALSE; while(bStart == FALSE) { //查找标题为"新建文本文档.txt - 记事本"的窗口 hwnd = ::FindWindow("Notepad","新建文本文档.txt - 记事本"); if(hwnd != NULL) { //向窗口发送WM_CLOSE 消息 ::SendMessage(hwnd,WM_CLOSE,0,0); ::MessageBox(NULL,"新建文本文档.txt - 记事本窗口已关闭","消息提示",MB_OK); bStart = TRUE; } else { ::MessageBox(NULL,"请先启动新建文本文档.txt - 记事本窗口","消息提示",MB_OK); } } return 0;} 以上是一个应用程序向另一个应用程序发送窗口的过程,系统向应用程序发送消息的过程是类似的,系统为应用程序传递所有输入到它的各个窗口,每个窗口都关联一个消息处理函数,消息处理函数处理输入,然后再将控制权交给系统 1.2.3 创建第一个窗口.
下面是一个最简单的窗口程序源代码,它的作用是弹出一个典型的 Windows 程序窗口,这些代码可以做为今后用 API 写 Windows 程序的基本框架
#include <windows.h> //消息处理函数原形LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ char *szClassName = "WndClass"; WNDCLASSEX wndclass; //用描述主窗口的参数填充WNDCLASSEX 结构 wndclass.cbSize = sizeof(wndclass); //定义结构的大小 wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; //定义窗口样式 wndclass.lpfnWndProc = WndProc; //指定本窗口的消息处理函数 wndclass.cbClsExtra = 0; //没有额外的类内存 wndclass.cbWndExtra = 0; //没有额外的窗口内存 wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); //使用默认的图标 wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用默认的光标 wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); //定义窗口的背景颜色为灰色 wndclass.hInstance = hInstance; //实例句柄 wndclass.lpszClassName = szClassName; //窗口类名称 wndclass.lpszMenuName = NULL; //不使用菜单 wndclass.hIconSm = NULL; //没有类的小图标 //注册窗口类 ::RegisterClassEx(&wndclass); //创建主窗口 HWND hwnd = ::CreateWindowEx(0, //不定义扩展样式 szClassName, //类名 "Hello world", //窗口标题 WS_OVERLAPPEDWINDOW, //窗口风格 CW_USEDEFAULT, //默认的窗口X 轴坐标 CW_USEDEFAULT, //默认的窗口Y 轴坐标 CW_USEDEFAULT, //默认的窗口宽度 CW_USEDEFAULT, //默认的窗口高度 NULL, //没有父窗口句柄 NULL, //没有菜单句柄 hInstance, //程序实例句柄 NULL); //没有用户数据 if(hwnd == NULL) { ::MessageBox(NULL,"创建窗口出错","error",MB_ICONHAND); return -1; } //显示窗口 ::ShowWindow(hwnd,nCmdShow); //刷新窗口客户区 ::UpdateWindow(hwnd); //从消息队列中取出消息,交给消息处理函数处理,直到GetMessage 函数返回FALSE ,结束消息循环 MSG msg; while(::GetMessage(&msg,NULL,0,0)) { //转化键盘消息 ::TranslateMessage(&msg); //将消息发送给消息处理函数 ::DispatchMessage(&msg); } return msg.wParam;} LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){ char *szText = "My first window process "; HDC hdc; //声明设备环境句柄 PAINTSTRUCT ps; switch(msg) { case WM_PAINT: //窗口客户区需要重画 { //使无效的客户区变得有效,并取得设备环境句柄 hdc = ::BeginPaint(hwnd,&ps); ::TextOut(hdc,0,0,szText,strlen(szText)); ::EndPaint(hwnd,&ps); return 0; } case WM_DESTROY: //正在销毁窗口 { //向消息队列投递一个WM_QUIT 消息,促使GetMessage 函数返回0,结束消息循环 ::PostQuitMessage(0); return 0; } } // 将我们不处理的消息交给系统做默认处理 return ::DefWindowProc(hwnd,msg,wParam,lParam);}分析以上程序,可以得出在桌面上创建一个窗口的具体步骤(1) 注册窗口类(RegisterClassEx)(2) 创建窗口(CeateWindowEx)(3) 在桌面上显示窗口(ShowWindow)(4) 更新窗口客户区(UpdateWindow)(5) 进入无限的消息获取和处理消息的循环,首先是获取消息(GetMessage),如果有消息到达,则通过 DispatchMessage 函数将消息发送到指定的消息处理函数 WndProc;
创建窗口的知识要点:
(1).指定窗口类的样式:
wndclass.style = CS_HREDRAW | CS_VREDRAW;
这句代码指定了如果窗口宽度或高度改变了就重画整个窗口,在 WINUSER.H 中定义了窗口类的全部可用样式,可以组合使用各种样式
(2)指定窗口客户区重画时使用的画刷
wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
这句代码指定使用 windows 预定义的白色背景画刷,也可以自己创建一个画刷对象以便指定喜欢的颜色为窗口背景色,下面的代码将窗口的背景色改为了黄色
Wndclass.hbrBackground = (HBRUSH)::GetSolidBrush(RGB(255,255,0));
…………………
………………….
::DeleteObject(wndclass.hbrBackground); //最后别忘记在程序结束之前删除创建的刷子释放资源
(3)指定窗口的风格
CreateWindows 第四个参数指定了窗口的风格,下面列出了一些最常见的风格定义,它们是以 WS 为前辍的预定义的值
WS_BORDER 创建一个单边框的窗口
WS_CAPTION 创建一个有标题框的窗口(包括WS_BORDER风格)
WS_CHILD 创建一个子窗口,这个风格不能与 WS_POPVP 风格合用
WS_DISABLED 创建一个初始状态为禁止的子窗口,一个禁止状态的窗口不能接受来自用户的输入信息
WS_DLGFRAME. 创建一个带对话框边框风格的窗口,这种风格的窗口不能带有标题条
WS_HSCROLL 创建一个有水平滚动条的窗口
WS_VSCROOL 创建一个有垂直滚动条的窗口
WS_ICONIC 创建一个初始状态为最小化的窗口,与 WS_MINIMIZE 风格相同
WS_MAXIMIZE 创建一个初始状态为最大化的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格
WS_OVERLAPPED 产生一个层叠窗口,一个层叠的窗口有一个标题条和一个边框,与 WS_TILED 风格相同
WS_OVERLAPPEDWINDOW 创建一个具有 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,WS_THICKFRAME, WS_MINIMIZEBOX,WS_MAXMIZEBOX 风格的层叠窗口
WS_POPUP 创建一个弹出式窗口,该风格不能与WS_CHLD 风格同时使用
WS_POPUPWINDOW 创建一个具有 WS_BORDER, WS_POPUP, WS_SYSMENU, 风格的窗口,WS_CAPTION 和 WS_POPUPWINDOW 必须同时使用才能使窗口可见
WS_SIZEBOX 创建一个可调边框的窗口,与 WS_THICKFRAME. 风格相同
WS_SYSMENU 创建一个在标题条上带有窗口菜单的窗口,必须同时设定 WS_CAPTION 风格
WS_THICKFRAME. 创建一个具有可调边框的窗口,与 WS_SIZEBOX 风格相同
WS_VISBLE 创建一个初始状态为可见的窗口
(4)消息队列 MSG 结构
Windows 为每个线程维护了一个消息队列,每当有消息进入时,Windows 就利用GetMessage 函数调用线程的消息队列来填充 MSG 结构,这个结构定义了消息的所有属性
Typedef struct tagMSG
{
HWND hwnd; //消息要发往的窗口句柄
UINT message; //消息标识符,以WM_开头的预定义值
WPARAM wParam; //消息参数之一
LPARAM lParam; //消息参数之二
DWORD time; //消息放入消息队列的时间
POINT pt; //这是一个POINT 数据结构,表示消息放入消息队列时的鼠标位置
}MSG, &PMSG;v
TAG:
标题搜索
日历
|
|||||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
| 1 | 2 | 3 | 4 | 5 | |||||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 | |||
| 13 | 14 | 15 | 16 | 17 | 18 | 19 | |||
| 20 | 21 | 22 | 23 | 24 | 25 | 26 | |||
| 27 | 28 | 29 | 30 | 31 | |||||
我的存档
数据统计
- 访问量: 9644
- 日志数: 224
- 图片数: 2
- 商品数: 3
- 文件数: 1
- 影音数: 1
- 建立时间: 2007-06-19
- 更新时间: 2008-06-15

