win32开发第一篇——“第一个”windows窗体

Roc posted @ 2012年12月04日 22:37 in Win32开发备忘录 , 2166 阅读

对于有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循环,不停的在判断是否有事件发生

 

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

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

 

 

 

 

 

 

 

 

Avatar_small
teletalk.com.bd 说:
2022年8月27日 22:06

Bangladesh All Education Board has announced PSC Scholarship Result 2022 on last week of December 2022 for all divisional educational boards under DPE, and they have going to issue Primary Britti 2022 to all qualified student, and the DPE is going to announce likely on March or April 2022 with school wise selection list for Talent Pool Scholarship and General Grade Scholarship to all eligible student under Prathomik Somaponi Result 2022. Every year the All Education Board Bangladesh has announced a selected candidate list school wise and district wise to all divisional boards of Dhaka, Chittagong, Comilla, Rajshahi, Sylhet, Barisal, Jessore, teletalk.com.bd Dinajpur, and Madrasah Board working under DPE and this year also going to declare PSC Scholarship Result 2022 with selection list and type of scholarship through PSC Britty 2022.

Avatar_small
seo service UK 说:
2024年1月16日 15:12

This is truly an practical and pleasant information for all. Thanks for sharing this to us and more power


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter