win32窗口
一、入口函数
File -> Win32 Application -> A simple Win32 application.
二、打印
在win32中没有控制台,所以需要输出需要手动添加一个头文件
Tools.h
void __cdecl OutputDebugStringF(const char *format, ...);
#ifdef _DEBUG
#define DbgPrintf OutputDebugStringF
#else
#define DbgPrintf
#endif
Tools.cpp
void __cdecl OutputDebugStringF(const char *format, ...)
{
va_list vlArgs;
char *strBuffer = (char*)GlobalAlloc(GPTR, 4096);
va_start(vlArgs, format);
_vsnprintf(strBuffer, 4096 - 1, format, vlArgs);
va_end(vlArgs);
strcat(strBuffer, "\n");
OutputDebugStringA(strBuffer);
GlobalFree(strBuffer);
return;
}
三、GetLastError
获取错误代码,如下
#include "stdafx.h"
#include "Tools.h"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MessageBox((HWND)1,0,0,0);
DWORD erroCode = GetLastError();
DbgPrintf("%d\n",erroCode);
return 0;
}
MessageBox第一个参数有误,用GetLastError会返回最后出现的错误的编号,然后利用这个编号去查找错误信息
四、事件
Windows中的事件是一个“动作”,这个动作可能是用户操作应用程序产生的,也可能是Windows自己产生的.
而消息,就是用来描述这些“动作”的,比如:
这个动作是什么时候产生的?
哪个应用程序产生的?
在什么位置产生的?
等等。。。
Windows为了能够准确的描述这些信息,提供了一个结构体:MSG,该结构体里面记录的事件的详细信息.
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG;
1、hwnd
窗口句柄
2、message
消息类型,是键盘还是鼠标,是鼠标左键还是右键
3、wParam 和 lParam
32位消息的特定附加信息,具体表示什么处决于message
4、time
消息创建时的时间
5、pt
消息创建时的鼠标位置
五、消息流程
1、系统/用户触发的某个动作(按下键盘或者点下鼠标)
2、系统将这些信息存储到MSG结构体中
3、系统将该消息存储到相关应用程序的消息队列中
4、从队列中获取消息
5、翻译消息(比如你按了下键盘上的a,message只记录了你按了下键盘,具体按了哪个键就需要翻译,翻译完之后封装成一个结构体)
6、分派消息(将消息翻译完之后,再把封装好的消息发给操作系统)
7、操作系统调用我们写的程序处理消息
六、创建窗口
1、设计窗口类
//窗口的类名
TCHAR className[] = "My First Window";
// 创建窗口类的对象
WNDCLASS wndclass = {0}; //一定要先将所有值赋值
wndclass.hbrBackground = (HBRUSH)COLOR_MENU; //窗口的背景色
wndclass.lpfnWndProc = WindowProc; //窗口过程函数
wndclass.lpszClassName = className; //窗口类的名字
wndclass.hInstance = hInstance; //定义窗口类的应用程序的实例句柄
2、注册窗口类
//注册窗口类
RegisterClass(&wndclass);
3、创建窗口
// 创建窗口
HWND hwnd = CreateWindow(
className, //类名
TEXT("我的第一个窗口"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口外观样式
10, //相对于父窗口的X坐标
10, //相对于父窗口的Y坐标
600, //窗口的宽度
300, //窗口的高度
NULL, //父窗口句柄,为NULL
NULL, //菜单句柄,为NULL
hInstance, //当前应用程序的句柄
NULL); //附加数据一般为NULL
4、判断是否创建成功
if(hwnd == NULL) //是否创建成功
return 0;
5、显示窗口
// 显示窗口
ShowWindow(hwnd, SW_SHOW);
6、消息循环
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
7、回调函数
-
窗口回调函数处理过的消息,必须传回0
-
窗口回调不处理的消息,由DefWindowProc来处理
LRESULT CALLBACK WindowProc(
IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch(uMsg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
//键盘消息
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
8、完整代码
// test.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
LRESULT CALLBACK WindowProc(
IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//
//窗口的类名
TCHAR className[] = "My First Window";
// 创建窗口类的对象
WNDCLASS wndclass = {0}; //一定要先将所有值赋值
wndclass.hbrBackground = (HBRUSH)COLOR_MENU; //窗口的背景色
wndclass.lpfnWndProc = WindowProc; //窗口过程函数
wndclass.lpszClassName = className; //窗口类的名字
wndclass.hInstance = hInstance; //定义窗口类的应用程序的实例句柄
//注册窗口类
RegisterClass(&wndclass);
// 创建窗口
HWND hwnd = CreateWindow(
className, //类名
TEXT("我的第一个窗口"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口外观样式
10, //相对于父窗口的X坐标
10, //相对于父窗口的Y坐标
600, //窗口的宽度
300, //窗口的高度
NULL, //父窗口句柄,为NULL
NULL, //菜单句柄,为NULL
hInstance, //当前应用程序的句柄
NULL); //附加数据一般为NULL
if(hwnd == NULL) //是否创建成功
return 0;
// 显示窗口
ShowWindow(hwnd, SW_SHOW);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(
IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch(uMsg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
七、窗口消息类型
//窗口创建
case WM_CREATE:
{
DbgPrintf("WM_CREATE %d\n",uMsg);
return 0;
}
1、根据消息类型WM_CREATE,查找IN WPARAM wParam, IN LPARAM lParam 这两个参数的意义
2、
//窗口移动
case WM_MOVE:
{
DbgPrintf("WM_MOVE %d %d\n",wParam,lParam);
POINTS points = MAKEPOINTS(lParam);
DbgPrintf("X Y %d %d\n",points.x,points.y);
return 0;
}
八、win32入口
1、入口有4个参数
- IN HWND hwnd //句柄
- IN UINT uMsg //永远为空
- IN WPARAM wParam //接受命令行参数
- IN LPARAM lParam //以什么方式显示最大化还是最小化等