- 首先创建一个win32程序
#include "stdafx.h" int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. return 0; }
- WinMain是程序入口,APIENTRY查找定义可知,是_cdecl的别名,_cdecl是一种内平栈的调用约定,这里就不细说了
- WinMain有四个参数,查询MSDN
int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state );
- 第一个参数 hInstance 表示该程序当前运行的实例的句柄,这是一个数值。当程序在 Windows 下运行时,它唯一标识运行中的实例。一个应用程序可以运行多个实例,每运行一个实例,系统都会给该实例分配一个句柄值,并通过 hInstance 参数传递给 WinMain 函数
- 第二个参数 hPrevInstance 表示当前实例的前一个实例的句柄。通过查看 MSDN 可以知道,在 Win32 环境下,这个参数总是 NULL ,即在 Win32 环境下,这个参数不再起作用
- 第四个参数 nCmdShow 指定程序的窗口应该如何显示,例如最大化、最小化、隐藏等。这个参数的值由该程序的调用者所指定,在调用ShowWindow()时可以使用到该值。
- 而第三个参数查询api文档,得知,是指向以null结尾的字符串的指针,该字符串指定应用程序的命令行,但不包括程序名。要检索整个命令行,请使用GetCommandLine函数。用debugview软件得到
接下来是创建一个WNDCLASS结构体,WNDCLASS结构包含由RegisterClass函数注册的窗口类属性。
typedef struct _WNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS, *PWNDCLASS;
这是编译器已经定义好的 结构体,如果要自己定义一个WNDCLASS,必须要为每个变量赋值,下面是必须赋值的变量
WNDCLASS wndclass = {0}; //一定要先将所有值赋值 wndclass.hbrBackground = (HBRUSH)COLOR_MENU; //窗口的背景色,是一个宏,相当于2 wndclass.lpfnWndProc = WindowProc; //窗口过程函数 wndclass.lpszClassName = “MyClass”; //窗口类的名字 自己定义 wndclass.hInstance = hInstance; //定义窗口类的应用程序的实例句柄 mian函数传进来的
其中WindowProc在后面我们要自己定义
LRESULT CALLBACK WindowProc( HWND hwnd, // 窗口的句柄 UINT uMsg, // 消息标识符 WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); 返回值是消息处理的结果,取决于发送的消息
下一步,注册窗口类,RegisterClass函数注册一个窗口类,以便随后在调用CreateWindow或CreateWindowEx函数时使用。
API文档 : ATOM RegisterClass(CONST WNDCLASS *lpWndClass ); RegisterClass(&MyClass); //注册窗口类
注意,RegisterClass函数已经被RegisterClassEx函数所取代。但是,如果不需要设置类的小图标,仍然可以使用RegisterClass。
创建窗口,CreateWindow函数创建一个重叠的、弹出的或子窗口。它指定窗口类、窗口标题、窗口样式以及(可选地)窗口的初始位置和大小。该函数还指定窗口的父窗口或所有者(如果有的话)以及窗口的菜单。除了CreateWindow支持的样式外,要使用扩展的窗口样式,请使用CreateWindowEx函数。
HWND CreateWindow ( LPCTSTR lpClassName, //注册的类名 LPCTSTR lpWindowName, //窗口名 DWORD dwStyle, // window style int x, //窗口的水平位置 int y, //窗口的垂直位置 int nWidth, //窗口宽度 int nHeight, //窗口高度 HWND hWndParent, //指向父窗口或所有者窗口的句柄 HMENU, //菜单句柄或子标识符 HINSTANCE, //应用程序实例的句柄 LPVOID lpParam //窗口创建数据 );
HWND hwnd = CreateWindow( // 创建窗口 MyClass, //类名 ,上面定义的 TEXT("我的第一个窗口"), //窗口标题 WS_OVERLAPPEDWINDOW, //窗口外观样式 可查询MSDN 10, //相对于父窗口的X坐标 10, //相对于父窗口的Y坐标 600, //窗口的宽度 300, //窗口的高度 NULL, //父窗口句柄,为NULL NULL, //菜单句柄,为NULL hInstance, //当前应用程序的句柄 NULL); //附加数据一般为NULL if(hwnd == NULL) //是否创建成功 return 0;
下一步,显示窗口
MSDN查询ShowWindow函数,
BOOL ShowWindow(
HWND hWnd, // handle to window
int nCmdShow // show state
);第二个参数,我选择SW_SHOW,SW_SHOW Activates the window and displays it in its current size and position.
激活窗口并以当前大小和位置显示它。ShowWindow(hwnd, SW_SHOW);
事件 消息
Windows中的事件是一个“动作”,这个动作可能是用户操作应用程序产生的,
也可能是Windows自己产生的.
而消息,就是用来描述这些“动作”的,
比如:这个动作是什么时候产生的? 哪个应用程序产生的?在什么位置产生的?
等等。。。
Windows为了能够准确的描述这些信息,提供了一个结构体:MSG,该结构体里面记录的事件的详细信息创建消息循环,下面是MSG结构体定义
typedef struct tagMSG {
HWND hwnd; 窗口的句柄,其窗口过程接收消息。
UINT message; 指定消息标识符。
WPARAM wParam; 指定关于消息的附加信息。确切的含义取决于消息成员的值。
LPARAM lParam; 指定关于消息的附加信息。确切的含义取决于消息成员的值。
DWORD time; 消息的时间。
POINT pt; 消息发布时的光标位置(以屏幕坐标表示)。} MSG, *PMSG;
其中 message
在Windows中,消息是由一个数值来表示的
但是由于数值不便于记忆,所以Windows将消息对应的 数值 定义为WM_XXX宏(WM == Window Message)
鼠标左键按下 WM_LBUTTONDOWN 键盘按下 WM_KEYDOWN// 消息循环 MSG msg; //创建一个结构体变量 while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); //函数将消息转换为字符消息。字符消息再发送到调用线程的消息队列, DispatchMessage(&msg); // 将消息传到为它分配的窗口程序 } 其中GetMessage函数如下,GetMessage返回非零时,循环接受消息 BOOL GetMessage( LPMSG lpMsg, // message information HWND hWnd, // handle to window UINT wMsgFilterMin, // first message UINT wMsgFilterMax // last message );
最后,定义之前的窗口过程函数 windowpro
LRESULT CALLBACK WindowProc( IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { switch(uMsg) { case 2: { MessageBox(0,"我点了关闭","gg",0); PostQuitMessage(0); return 0; } } return DefWindowProc(hwnd,uMsg,wParam,lParam); //未处理的消息,调用默认的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理。该函数确保每一个消息得到处理。 }
当点了关闭后
最后附上完整代码
#include "stdafx.h" //vc6.0创建工程时帮我们定义的头文件, 包含#include<windows.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { switch(Message) { case WM_DESTROY: { MessageBox(NULL, "关闭了程序!","Error!",0); PostQuitMessage(0); break; } default: return DefWindowProc(hwnd, Message, wParam, lParam); } return 0; } //主函数 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc={0}; HWND hwnd; MSG msg; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH) COLOR_WINDOW; wc.lpszClassName = "WindowClass"; if(!RegisterClass(&wc)) { MessageBox(NULL, "注册失败!","Error!",0); return 0; } hwnd = CreateWindow(, "WindowClass", "我的窗口", WS_VISIBLE|WS_OVERLAPPEDWINDOW, //窗口外观 20, /* x */ 20, /* y */ 640, /* width */ 480, /* height */ NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "创建失败!","Error!",0); return 0; } while(GetMessage(&msg, NULL, 0, 0) > 0 ) { TranslateMessage(&msg); /* Translate key codes to chars if present */ DispatchMessage(&msg); /* Send it to WndProc */ } return msg.wParam; }