Windows编程入门的常见问题
(a)Windows编程的构架中至少需要哪些函数?这些函数至少包含哪些内容?
必须至少包括WinMain与Wndproc函数,即入口函数和窗口函数
WInMain函数
基本功能
1.注册窗口类,建立窗口并执行必要的初始化
2.进入消息循环,局接受的消息调用相应的处理过程
3.检索到WM_QUIT时终止程序
原型:
int WINAPI WinMain
(
HINSTANCE hThisInst,//当前实例句柄
HINSTANCE hPrevlnst,//其他实例句柄
LPSTR IpszCmdLine, //指向程序命令行参数的指针
Int nCmdShow //窗口显示方式的整数值
)
WndProc窗口函数
基本功能
1.消息处理函数,执行对应的消息
2.当遇到WM_DESTROY时退出消息循环
原型:
LRESULT CALLBACK WndProc(HWND hwnd,UINT messege,WPARAM wParam,LPARAM IParam)
{
switch(message)//使用switch-case结构处理消息
{
case……:
……
break;
……
case WM_DESTROY:
PostQuitMessage(0);//当遇到WM_DESTROY消息时执行PostQuitMessage退出循环
default:
return DefWindowProc(hwnd,message,wParam,IParam);//为未定义的处理消息提供缺省处理
}
return(0);
}
(b)Windows编程构架中所涉及的句柄有哪些?其结构是如何定义的?
句柄是一个8字节长(相对64位操作系统)的数值,用于标识应用程序中不同的对象和同类对象中不同的实例
常见句柄如下:
HWND 窗口句柄
HDC 设备环境句柄
HBITMAP 位图句柄
HCURSOR 光标句柄
HICON 图标句柄
HFONT 字体句柄
HMENU 菜单句柄
HPEN 画笔句柄
HFILE 文件句柄
HBRUSH 画刷句柄
HINSTANCE 当前实例句柄
- -
(c)在进行窗口类定义与注册过程中,具体怎么完成?
定义即为WNDCLASS对象赋值的过程,WNDCLASS包括10个成员,分别如下:
typedef struct _WNDCLASS
{
UINT style; // 窗口类型
WNDPROC lpfnWndProc;//窗口处理函数
int cbClsExtra;//窗口扩展
int cbWndExtra;//窗口实例扩展
HINSTANCE hInstance;//实例句柄
HICON hIcon;//窗口的最小化图标
HCURSOR hCursor;//窗口鼠标光标
HBRUSH hbrBackground;//窗口背景色
LPCTSTR lpszMenuName;//窗口菜单
LPCTSTR lpszClassName;// 窗口类名
} WNDCLASS
在最简单的窗口中是这样赋值的:
//假设窗口名为wndclass
wndclass.style = 0; //窗口类型为缺省类型
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 = lpszClassName;
//窗口类名为"窗口"
此外,还要特别关注这几个函数
1.Loadlcon 加载一个窗口图标
HICON Loadlcon(HINSTANCE hlnstance,LPCTSTP lplconName)
//指向实例窗口,NULL为预置图标,图标标识名
2.LoadCursor 加载一个窗口光标
HCURSOP LoadCursor(HINSTANCE hlnstance,LPCTSTR lpCursorName)
//指向实例窗口,光标类型
3.GetStockObject 获取系统提供的背景刷
HGDIOBJ GetStockObject(int nBrush);
//HBRUSH与HGDIOBJ类型虽然在本质上没有什么差别,但VS定义严格,必须加以强制转换
注册: 窗口要求先注册后使用,注册过程如下:
bool RegisterClass(&wndclass);//wndclass
if (!RegisterClass(&wndclass))
{
MessageBeep(0);
return false;
}
//MessageBeep(0)的含义是发生错误时响铃来提醒程序员
(d)消息循环的作用是什么?
while (GetMessage(&Msg, NULL, 0, 0)){ //获得消息
TranslateMessage(&Msg); //翻译消息(可跳过)
DispatchMessage(&Msg); //执行指令
}//消息循环
第一步获得信息,其中GetMessage函数的原型为:
Getmessage
(IpMSG, //指向MSG对象的指针
hwnd,
nMsgFilteMin,//最小消息长
nMsgFilterMax//最大消息长
)
第二部处理虚拟信息,如键盘键入的信息,当信息不需要转换时,这一步可以跳过
第三部则是将信息传入相应的图形处理函数,进行相应响应
(e)消息处理函数是如何调用的?在什么地方发生调用?
过程驱动:程序是按照我们预先定义好的顺序执行,每执行一步,下一步都已经按照预定的顺序 继续执行,直至程序结束。
事件驱动:程序的执行顺序是无序的。某个时间点所执行的代码,是由外界 通知。由于我们无法决定程序执行顺序。所以代码的执行也是无序的。
消息队列: 用于存储消息的内存空间,消息在队列中是先入先出.
消息处理函数即窗口函数,原型如下:
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam)
//窗口句柄,消息内容,附加信息
利用窗口处理函数从而进行对信息的处理加工,常见格式如下:
LRESULT CALLBACK WndProc(HWND hwnd,UINT messege,WPARAM wParam,LPARAM IParam)
{
switch(message)
{
case……
……
break;
……
case WM_DESTROY
PostQuitMessage(0);
default:
return DefWindowProc(hwnd,message,wParam,IParam);//为未定义的处理消息提供缺省处理
}
return(0);
}//仅仅定义了关闭窗口的函数
Windows编程部分这几个问题搞定了,这个部分的后续相关专题的学习就很简单了。
附:最简单的窗口编程源代码
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPreInst, LPSTR IpszCmdLine, int nCmdShow)
{
HWND hwnd;
MSG Msg;
WNDCLASS wndclass;
LPCSTR lpszClassName = TEXT("windows");//窗口类名
LPCSTR lpszTitle = TEXT("My_Windows");//窗口标题名
//窗口类的定义
wndclass.style = 0; //窗口类型为缺省类型
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 = lpszClassName;
//窗口类名为"窗口"
//以下进行窗口类的注册
if (!RegisterClass(&wndclass))
{
MessageBeep(0);
return false;
}
//创建窗口
hwnd = CreateWindow
(
lpszClassName, //窗口类名
lpszTitle, //窗口实例的标题名
WS_OVERLAPPEDWINDOW, //窗口的风格
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口左上角坐标为缺省值
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口的高和宽为缺省值
NULL, //此窗口无父窗口
NULL, //此窗口无主菜单
hInstance, //创建此窗口的应用程序的当前句柄
NULL //不使用该值
);
//显示窗口
ShowWindow(hwnd, nCmdShow);
//绘制用户区
UpdateWindow(hwnd);
//消息循环
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam; //消息循环结束即程序终止时将信息返回系统
}
//窗口函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
default:
return DefWindowProc(hwnd, message, wParam, IParam);
}
return(0);
}