Dec 4

对于有vb或者c#开发经验的程序员来说,窗体应用程序不过是拖拖控件了事,下面介绍一种比较古老的技术,也就所谓win32开发,使用windows函数库来创建windows应用程序

 

#define WIN32_LEAN_AND_MEAN
#define WindowsName "win1"

#include <Windows.h>
#include <WindowsX.h>

LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	PAINTSTRUCT ps;
	HDC hdc;

	switch(msg)
	{
		//创建
		case WM_CREATE:
			return 0;
			break;
		//重绘
		case WM_PAINT:
			hdc=BeginPaint(hwnd,&ps);
			return 0;
			break;
		//销毁
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			break;
	}

	return DefWindowProc(hwnd,msg,wparam,lparam);
}


int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpcmdline,int ncmdshow)
{
	//窗体类
	WNDCLASSEX winclass;
	HWND hwnd;
	MSG msg;

	winclass.cbSize=sizeof(WNDCLASSEX);
	winclass.style=CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
	winclass.lpfnWndProc=WindowProc;
	winclass.cbClsExtra=0;
	winclass.cbWndExtra=0;
	winclass.hInstance=hInstance;
	winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	winclass.hCursor=LoadCursor(NULL,IDC_ARROW);
	winclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	winclass.lpszMenuName=NULL;
	winclass.lpszClassName=WindowsName;
	winclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION);

	//注册窗体
	if(!RegisterClassEx(&winclass))
	{
		return 0;
	}

	//创建
	if(!(hwnd=CreateWindowEx(NULL,
		WindowsName,
		"我的第一个窗体",
		WS_OVERLAPPEDWINDOW|WS_VISIBLE,
		0,
		0,
		400,
		400,
		NULL,
		NULL,
		hInstance,
		NULL
		)))
	{
		return 0;
	}



	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);

		DispatchMessage(&msg);
	}

	//while(true)
	//{
	//	if(PeekMessage(&msg,hwnd,0,0,PM_REMOVE) && PeekMessage(&msg,hwnd,0,0,PM_REMOVE))
	//	{
	//		MessageBox(NULL,"test","标题",NULL);
	//		if(msg.message==WM_QUIT)
	//		{
	//			break;
	//		}
	//		TranslateMessage(&msg);
	//		DispatchMessage(&msg);
	//	}
	//}

	return msg.wParam;
}

这段代码可以在vs2010中的c++项目中编译成功,有空会写出相应的文章

短短80多行代码足以创建一个黑色背景的窗体

涵盖了:

1、注册windows类

2、创建窗体

3、事件处理

4、主事件循环

 

我尝试每句话都解释一下

 

#define WIN32_LEAN_AND_MEAN

 

这句话的意思是不想要使用MFC来开发,具体什么是MFC,请另百度搜索

 

#define WindowsName "win1"

#include <Windows.h>
#include <WindowsX.h>

 

第一句为宏定义,把WindowsName定义为"win1"的别名,用来给窗体起名字的

第二和第三句分别导入两个函数库,用来进行windows开发的最基本函数库

 

LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	PAINTSTRUCT ps;
	HDC hdc;

	switch(msg)
	{
		//创建
		case WM_CREATE:
			return 0;
			break;
		//重绘
		case WM_PAINT:
			hdc=BeginPaint(hwnd,&ps);
			return 0;
			break;
		//销毁
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			break;
	}

	return DefWindowProc(hwnd,msg,wparam,lparam);
}

 

这是回调函数。

对窗体产生的事件进行处理

比如有

WM_CREATE创建,WM_PAINT绘制,WM_DESTROY销毁

而触发这三种事件的条件是传入了怎样的消息msg

当msg符合创建条件时,就会进入switch条件分支的WM_CREATE中(这简直“太容易理解了”)

总之msg的赋值你并不需要关注,这是系统替我们赋值的

 

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpcmdline,int ncmdshow)

 

这句话是win32程序的标准main函数,也就所谓大门,main方法不必过多赘述,跟其他语言一个意思

只不过是多了一点点其他的东西,比如这个int WINAPI WinMain的写法就是十分奇葩,其实就是int WinMain中间多了一个WINAPI

这个WINAPI规定了函数参数的入栈方式是最右边先入栈,这不需要过多的关注,在以后的研究中会搞明白入栈方式对编程的影响。

 

//窗体类
WNDCLASSEX winclass;
HWND hwnd;
MSG msg;

 

第一句话注册了一个窗体类,由于win32编程是用c语言开发的,说是类,但没有class关键字,经过一步步F12追踪源代码,我发现WNDCLASSEX是一个结构体struct, 用来规定窗体长什么样子

HWND hwnd是一个窗体句柄,也就所谓窗体的一个身份标识,再简单的理解,就是身份证

MSG msg是消息,用来确定是执行绘制窗体还是创建窗体,或者是销毁窗体

 

        winclass.cbSize=sizeof(WNDCLASSEX);
	winclass.style=CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
	winclass.lpfnWndProc=WindowProc;
	winclass.cbClsExtra=0;
	winclass.cbWndExtra=0;
	winclass.hInstance=hInstance;
	winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	winclass.hCursor=LoadCursor(NULL,IDC_ARROW);
	winclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	winclass.lpszMenuName=NULL;
	winclass.lpszClassName=WindowsName;
	winclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION);

 

规定了很多,如窗体的样式,光标,鼠标,背景颜色等等,其中有两句很重要

winclass.lpfnWndProc=WindowProc;

winclass.lpszClassName=WindowsName;

第一句话规定了本窗体的回调函数是谁,第二句话规定了本窗体的名字叫什么

 

	//注册窗体
	if(!RegisterClassEx(&winclass))
	{
		return 0;
	}

 

用RegisterClassEx来注册窗体,只有注册过的窗体才能使用,注册失败就让WinMain主函数返回0

 

	//创建
	if(!(hwnd=CreateWindowEx(NULL,
		WindowsName,
		"我的第一个窗体",
		WS_OVERLAPPEDWINDOW|WS_VISIBLE,
		0,
		0,
		400,
		400,
		NULL,
		NULL,
		hInstance,
		NULL
		)))
	{
		return 0;
	}

创建窗体,规定了大小之类的琐事

 

	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);

		DispatchMessage(&msg);
	}

消息循环,用来转发消息,确定你是要做什么事,比如WM_CREATE创建,WM_PAINT绘制,WM_DESTROY销毁

而且这还是个while循环,不停的在判断是否有事件发生

 

----------备注------------

简单先写这些,本文未完成,对关键函数以及变量的解释不够,在后面的研究深入中慢慢加入