前段时间忙着找工作,好久没有更新了,现在准备开一个Win32学习的简单教程。教会大家快速入门。之所以不直接做MFC的教程,主要是因为MFC的封装比较高,不能比较深入的理解win编程的细节。而且学完WIN32的开发会发现MFC其实已经会了80%了。所以请跟我一起进入学习吧。
===============================================================================
窗口是屏幕上的一块矩形区域,是 Windows 应用程序与用户进行交互的接口。 利用窗口可以接收用户的输入、以及显示输出。一个应用程序窗口通常都包含标题栏、菜单栏、系统菜单、最小化框、最大化框、 可调边框,有的还有滚动条。
窗口可以分为客户区和非客户区,客户区是窗口的一部分, 应用程序通常在客户区中显示文字或者绘制图形。 标题栏、 菜单栏、 系统菜单、 最小化框和最大化框、 可调边框统称为窗口的非客户区, 它们由 Windows 系统来管理, 而应用程序则主要管理客户区的外观及操作。
在 Windows 应用程序中, 窗口是通过窗口句柄( HWND) 来标识的。 我们要对某个窗口进行操作, 首先就要得到这个窗口的句柄。 句柄( HANDLE) 是 Windows 程序中一个重要的概念, 使用也非常频繁。 在 Windows 程序中, 有各种各样的资源( 窗口、 图标、光标,画刷等), 系统在创建这些资源时会为它们分配内存, 并返回标识这些资源的标识号, 即句柄。
操作系统感知事件,将事件包装成一个消息,投递到应用程序的消息队列中,然后应用程序从消息队列中取出消息并进行响应。
下面是消息的结构体
typedef struct tagMSG {
HWND hwnd; 主窗口句柄
UINT message; 具体消息名称
WPARAM wParam; 附加消息 键盘消息
LPARAM lParam; 附加消息 鼠标消息 左右键
DWORD time; 消息产生时间
POINT pt; 附加消息 鼠标消息 x y
#ifdef _MAC
DWORD lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
每一个 Windows 应用程序开始执行后, 系统都会为该程序创建一个消息队列, 这个消息队列用来存放该程序创建的窗口的消息。
Windows 将产生的消息依次放到消息队列中, 而应用程序则通过一个消息循环不断地从消息队列中取出消息, 并进行响应。 这种消息机制, 就是 Windows程序运行的机制。
WinMain 是 Windows程序的入口点函数,与 DOS 程序的入口点函数 main 的作用相同,当 WinMain 函数结束或返回时,Windows 应用程序结束。
WinMain函数声明:
int WINAPI WinMain(
HINSTANCE hINstance,//应用程序的实例句柄
HINSTANCE hPreINSTANCE,//上一个应用程序句柄,在win32环境下,参数一般为NULL,不起作用了
LPSTR lpCmdLine,//char * argv[]
int nCmdShow//显示命令 最大化 最小化 正常
);
if(GetMessage(&msg,NULL,0,0)== FALSE)
{
break ;
}
case WM_CLOSE:
{
//所有以Window结尾的方法,都不会进入消息队列,而是直接直接执行
DestroyWindow(hwnd); //DestroyWindow发送另一个消息 WM__DESTROY
break;
}
case WM_DESTROY:
PostQuitMessage(0); //此时GetMessage()的值为FALSE,窗口才会被关掉
窗口过程中接收WM_LBUTTONDOWN消息,调用int xPos = LOWORD(lparam); int yPos = HIWORD(lparam);获取坐标值,MessageBox可弹出一个消息窗口
case WM_LBUTTONDOWN: //鼠标左键按下
{
int xPos = LOWORD(lparam);//获取鼠标按下的坐标
int yPos = HIWORD(lparam);
wchar_t buf[1024];
wsprintf(buf,TEXT("x = %d,y = %d"),xPos,yPos);
MessageBox(hwnd,buf,TEXT("鼠标左键按下"),MB_OK);
break;
}
MessageBox(hwnd,//消息框属于的父窗口,若为NULL表示无父窗口
buf,//消息框的内容
TEXT("鼠标左键按下"),//消息框的标题
MB_OK);//决定对话框的内容和行为的位标志集
按钮
按钮参数 | 含义 |
---|---|
MB_OK | 默认值。有一个确认按钮在里面。 |
row 2 col 1 | row 2 col 2 |
MB_YESNO | 有是和否在里面。 |
MB_ABORTRETRYIGNORE | 有Abort(放弃),Retry(重试)和Ignore(跳过) |
MB_YESNOCANCEL | 消息框含有三个按钮:Yes,No和Cancel |
MB_RETRYCANCEL | 有Retry(重试)和Cancel(取消) |
MB_OKCANCEL | 消息框含有两个按钮:OK和Cancel |
图标
参数 | 含义 |
---|---|
MB_ICONEXCLAMATION | 一个惊叹号出现在消息框 |
MB_ICONWARNING | 一个惊叹号出现在消息框 |
MB_ICONINFORMATION | 一个圆圈中小写字母i组成的图标出现在消息框 |
MB_ICONASTERISK | 一个圆圈中小写字母i组成的图标出现在消息框 |
MB_ICONQUESTION | 一个问题标记图标出现在消息框 |
MB_ICONSTOP | 一个停止消息图标出现在消息框 |
MB_ICONERROR | 一个停止消息图标出现在消息框 |
MB_ICONHAND | 一个停止消息图标出现在消息框 |
窗口过程中接收WM_KEYDOWN消息
case WM_KEYDOWN:
MessageBox(hwnd,TEXT("键盘按下"),TEXT("键盘按下"),MB_OK);
break;
当窗口重新显现或改变大小时会发生重绘。窗口过程中接收WM_PAINT消息
case WM_PAINT: //绘图
{
PAINTSTRUCT ps;//绘图结构体
HDC hdc = BeginPaint(hwnd,&ps);
//绘制文本
SetTextColor(hdc,RGB(10,0,255));//文本颜色
TextOut(hdc,100,100,TEXT("HELLO"),strlen("HELLO"));//文本位置和内容
//绘制图形
HBRUSH hb = CreateSolidBrush(RGB(0,255,0)); //创建画刷
HBRUSH orgBrs = (HBRUSH)SelectObject(hdc, hb); // 画刷选择到当前DC中
Ellipse(hdc,235,35,202,170); // 填充图形
SelectObject(hdc, orgBrs); // 选回原先的画刷
EndPaint(hwnd,&ps);
break;
}
代码实例:
#include //底层实现窗口的有文件
//窗口过程函数声明
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
//程序入口函数
//WINAPI 代表__stdcall 参数的传递顺序:从右到左依次入栈,并且在函数返回前清空栈
int WINAPI WinMain(
HINSTANCE hINstance,//应用程序的实例句柄
HINSTANCE hPreINSTANCE,//上一个应用程序句柄,在win32环境下,参数一般为NULL,不起作用了
LPSTR lpCmdLine,//char * argv[]
int nCmdShow//显示命令 最大化 最小化 正常
)
{
//1、 设计窗口
WNDCLASS wc;
wc.cbClsExtra = 0;//类的额外的内存
wc.cbWndExtra = 0;//窗口的额外内存
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//设置背景
wc.hCursor = LoadCursor(NULL,IDC_ARROW);//设置光标,如果第一个参数为NULL,代表使用的是系统自带的光标
wc.hIcon = NULL; //设置图标
wc.hInstance = hINstance;//应用程序实例句柄,传入WinMain中的形参即可
wc.lpfnWndProc = WindowProc;//窗口过程的函数名
wc.lpszClassName = TEXT("WIN"); //指定窗口类名称
wc.lpszMenuName = NULL;//菜单名称
wc.style = 0;//显示风格,0代表默认风格
//2、 注册窗口类
RegisterClass(&wc);
//3、 创建窗口
HWND WINAPI hwnd = CreateWindow(wc.lpszClassName,TEXT("WINDOWS"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hINstance,NULL);
/*lpClassName, 类名
lpWindowName, 标题名
dwStyle, 风格 一般用WS_OVERLAPPEDWINDOW,是一种混合风格
x, y, 坐标 nWidth, nHeight, 窗口的大小 都可以使用默认值CW_USEDEFAULT
hWndParent, 父窗口
hMenu, 菜单
hInstance, 实例句柄
lpParam, 附加值 NULL
*/
//4、 显示和更新
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
//5、 通过循环取消息
MSG msg;
/*
typedef struct tagMSG {
HWND hwnd; 主窗口句柄
UINT message; 具体消息名称
WPARAM wParam; 附加消息 键盘消息
LPARAM lParam; 附加消息 鼠标消息 左右键
DWORD time; 消息产生时间
POINT pt; 附加消息 鼠标消息 x y
#ifdef _MAC
DWORD lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
*/
while(1)
{
/*
_Out_ LPMSG lpMsg, 消息
_In_opt_ HWND hWnd, 捕获窗口 填NULL代表捕获所有窗口
_In_ UINT wMsgFilterMin, 最小过滤消息 一般填0 捕获所有消息
_In_ UINT wMsgFilterMax 最大过滤消息 一般填0 捕获所有消息
*/
if(GetMessage(&msg,NULL,0,0)== FALSE)
{
break ;
}
//在分发前翻译消息
TranslateMessage(&msg);//组合按键是需要翻译的,翻译好的消息重新排队
//其他消息,分发
DispatchMessage(&msg);
}
//6、 窗口过程(处理消息)
return 0;
}
//窗口处理函数定义
//CALLBACK 代表__stdcall 参数的传递顺序:从右到左依次入栈,并且在函数返回前清空栈
LRESULT CALLBACK WindowProc(
HWND hwnd, //消息所属的窗口句柄
UINT message, //具体的消息名称
WPARAM wparam, // 键盘附加消息
LPARAM lparam) // 鼠标附加消息
{
switch(message)
{
case WM_CLOSE:
{
//所有以Window结尾的方法,都不会进入消息队列,而是直接直接执行
DestroyWindow(hwnd); //DestroyWindow发送另一个夏溪 WM__DESTROY
break;
}
case WM_DESTROY:
PostQuitMessage(0); //此时GetMessage()的值为FALSE,窗口才会被关掉
case WM_LBUTTONDOWN: //鼠标左键按下
{
int xPos = LOWORD(lparam);//获取鼠标按下的坐标
int yPos = HIWORD(lparam);
wchar_t buf[1024];
wsprintf(buf,TEXT("x = %d,y = %d"),xPos,yPos);
MessageBox(hwnd,buf,TEXT("鼠标左键按下"),MB_OK);
break;
}
case WM_KEYDOWN:
MessageBox(hwnd,TEXT("键盘按下"),TEXT("键盘按下"),MB_OK);
break;
case WM_PAINT: //绘图
{
PAINTSTRUCT ps;//绘图结构体
HDC hdc = BeginPaint(hwnd,&ps);
//绘制文本
SetTextColor(hdc,RGB(10,0,255));//文本颜色
TextOut(hdc,100,100,TEXT("HELLO"),strlen("HELLO"));//文本位置和内容
//绘制图形
HBRUSH hb = CreateSolidBrush(RGB(0,255,0)); //创建画刷
HBRUSH orgBrs = (HBRUSH)SelectObject(hdc, hb); // 画刷选择到当前DC中
Ellipse(hdc,235,35,202,170); // 填充图形
SelectObject(hdc, orgBrs); // 选回原先的画刷
EndPaint(hwnd,&ps);
break;
}
}
//返回默认值处理方式
return DefWindowProc(hwnd, message, wparam, lparam);
}