SDK编程之理解Window应用程序框架

本文主要介绍Window应用程序框架的基础,强调理解框架对深入学习Visual C++ 和MFC编程的重要性。通过示例代码,解释宏的使用以及窗口设计过程,并提供Window程序的基本框架思路。建议初学者参考MSDN来深入学习相关系统函数。
摘要由CSDN通过智能技术生成

从个人的学习经验看来。为了少走弯路,在深入学习Visual C++ 面向对象与可视化程序设计时,很有必要先对 Window应用程序框架来个初步的深刻的理解 并以此过度到真正的MFC编程中。

好了 废话少说 直奔主题

提示:Window 的一些 函数名称,类型,宏 等都是比较人性化的,所谓的人性化就是与英文的拼写比较接近,这一特征在一下代码有所体现

这里说一下  宏  的定义:C++  宏 是将一个标识符定义为一个字符串(百度百科上的解释) 这里说一下为什么需要使用宏,

我个人理解使用宏的最重要的一个原因  就是减轻程序猿的记忆负担,将一个毫无规律可循的字符串用一个(有规律可循的,比较好认的)标识符来表示,同时也可以使程序看起来美观吧。举个简单的例子  我们在程序中经常使用的

 

const  double  pi = 3.1415926;  //定义一个常量PI

但我们也可以用 宏来完成:

#define PI 3.1415926

我们先看一段代码:

这里我为了将 Window 应用程序框架表示的更清晰

用 Init()函数封装了 窗口的设计过程. 然后窗口设计中用到的一些局部变量我就以引用的

方式传给Init() 在传给 函数内部使用了

#include<tchar.h>
#include<Windows.h>

LRESULT CALLBACK WindowProc(  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
  );  

void Init(WNDCLASS &wcex,HINSTANCE &hInstance);
// 以上是各种函数的函数声明,函数使用前必须声明啊,系统函数除外,这里必须说明下消息循环函数不是系统函数,
// 有程序员编写, 因此函数名就可以自己去 不过一般不改变,在此我使用WindowProc , 我们也可以改为WndProc(..)
// 我们可以发现 WindowProc 函数在返回值 LRESULT(这是一个 宏 我们并不需要深究他 只知道他是一个类型就OK 类似于int) 
// 前面有 CALLBACK 这是怎么回事呢 ? CALLBACK  回调, 有CALLBACK 修饰的函数成为回调函数, 我们可以简单理解为
// 由程序员写的 但是由系统调用的函数成为回调函数

int WINAPI WinMain(  HINSTANCE hInstance,      // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,          // command line
  int nCmdShow              // show state
  )
{
	WNDCLASS wcex;  //创建一个WNDCLASS结构对象
	HWND hwnd;		//创建过个窗口句柄
	MSG msg;		//创建一个MSG结构对象

	Init(wcex, hInstance);			//设计窗口

	// 设计完一个类接下来就是  注册这个类了 
	//这就好比我们设计了一个好东西,为了防止别人抄袭,我们需要去注册它
	
	if( ! RegisterClass(&wcex))  //注册窗口 我们用RegisterClassEx这个系统提供的函数 ,注意前来有个 ! 运算符
							//从函数命名可以知道这是用来注册用的,至于参数,暂时不管,后面解释 
	{
					
		//MessageBox(NULL,"窗口注册失败","窗口注册",NULL); //MessageBox()其实就是弹出一个(提示)消息框,我们使用电脑时经常也遇到
		return 0;			// 如果注册失败 返回0;
	}
	
	//注册完窗口开始创建窗口了,我们调用系统函数CreateWindow(),
	//注意他返回的是一个窗口句柄, 我们之前创建的 窗口句柄就是用来 接受它的返回值的
	hwnd  = CreateWindow("可视化编程","程序讲解",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,
							CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,
							hInstance,NULL);// 注意 创建窗口只需要调用一个函数就完成了,参数过长可以分多行写

	if( ! hwnd)// 如果创建窗口失败 hwnd值为NULL  !hwnd 为真,返回0 退出WinMain函数
	{
		//MessageBox(NULL,"窗口注册失败","窗口注册",NULL);
		return 0;			
	}
	//创建完还不行啊,要给使用者看啊。因此需要显示窗口

	ShowWindow(hwnd,nCmdShow);  //注意两个参数,第一个参数就是CreateWindow返回的 hwnd,而第二个
								//参数就是 我们的WinMain 函数的最后一个参数,窗口的初始状态(是最大化的
								//还是最小化的))
	//回想一下我们注册窗口是的背景,我们是用白色是粉刷的,但是结合实际,我们
	//平常常用的程序一进去并不是白色的,因此我们这里也一样,显示了窗口之后,必要对窗口作一下必要的初始化
	//用到UpdateWindow() 这个系统函数

	UpdateWindow(hwnd);  //参数也是使用前面的hwnd; 至于为什么 先不管

	while(GetMessage(&msg,NULL,0,0))   //进行消息循环
	{
		TranslateMessage(&msg);     // 将虚拟键转化为字符消息,
									//用键盘进行输入时将按键虚拟键转化为字符消息,一边显示出来


		DispatchMessage(&msg);     //将消息"发送"到指定的窗口函数 即 WindowProc 
	}
	// 至此,一个应用程序的基本框架就完成了,等等,不是说消息循环是Window程序主体么? 
	//为什么没看到调用窗口消息处理函数,其实程序内部已经调用了 只是我们不知道而已,那么系统是如何调用的?
	// 我们发现 注册窗口时 Init()函数内 有这么一个表达式 wcex.lpfnWndProc  = WindowProc; 系统就是从这里得知消息处理函数的,
	// 函数地址都已经知道了 调用岂不是容易事, 好了,他的内部操作我们就不深入了

	return (int) msg.wParam;  // 程序对出之后我们返回这个消息的某些参数 wParam是MSG 结构的一个字段
}

void Init(WNDCLASS &wcex,HINSTANCE &hInstance)   //使用的是引用参数,注意我传入的两个参数
{
	wcex.style = 0;			// (这里表示将要创建的窗口的类型)
							//值为0是采用的是默认类型,我们用他默认类型就可以了
	wcex.cbClsExtra = 0;	//有兴趣的可以自己上网查查,这里不做介绍,
							//在SDK编程中用处也不大。
	wcex.cbWndExtra = 0;	//同上
	wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
							//这里表示的是将要创建的窗口的背景
							//背景需要用画刷(HBRUSH)填充 填充背景一般使用GetStockObject()函数
	wcex.hIcon	 = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_APPLICATION));
				//从函数名可以知道这里加载一个图标hIcon 中的h 表示这是一个Icon的句柄
				//IDI_APPLICATION 是一个宏,至于为什么是IDI_...
				//因为这是一个ID 并且是Icon的ID 取Icon首字母I 连起来就是IDI_
				//此函数的第二个参数一个指针参数,而IDI_APPLICATION只是一个数值,需要类型转换
				//因此就使用宏MAKEINTRESOURCE() 来转换,其实就是函数转换函数,
				//至于内部怎么操作的我们就不用管了
	wcex.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_ARROW));
							//理解如上,IDC_ARROW  表示ARROW(箭头)的Cursor(光标)的ID
	wcex.hInstance   = hInstance;	//窗口句柄,使用从WinMain函数中传进的hInstance句柄就可以了(至于为什么后面解释)
	wcex.lpfnWndProc  = WindowProc;	//lpfnWndProc中,lp表示长整形(l)的指针(p),WndProc 表示什么相信已经猜到了就是调用
									//WndProc(...)窗口函数,窗口函数就是消息循环函数的别称罢了
									//至于等号的右值函数的名称就是函数的地址
									//与他要求的指针类型完全匹配
	wcex.lpszClassName = _T("可视化编程"); 
						//这里要注意了,你设计窗口是定于的是什么classname(类名),你后面创建窗口时就必要
						//使用相同的名字,至于这里为什么要  _T("...") 主要是为了提高程序的移植性。当然也
						//可以直接用" 可视化编程" 窗口菜单,为了简化这里我们先不要菜单了 所以设值为NULL
						//就OK,其实0也可以,不过规范的编程中我们使用的是NULL 因为这是一个指针.指针为空时
						//我们让他指向NULL;

	wcex.lpszMenuName  = NULL;	
}

// 一下是消息处理函数实现代码

LRESULT CALLBACK WindowProc(  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
  )
{
	switch(uMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd,uMsg,wParam,lParam);
		//调用系统默认函数
		break;
	}
	return 0;
}


好了.

我们在来理清一下  Window程序的基本框架思路:(函数必要的返回值 参数我就省略了,这样子 看起来思路比较清晰);

WinMain()
{
	// 创建3钟特殊的结构的对象 以后用到
	WNDCLASS wcex
	HWND hwnd;
	MSG msg;

	// 窗口注册
	Init()
	{
		//窗口的注册,完成一些必要的初始化;
		//主要用到了 WNDCLASS wcex 这个结构个各种字段;
		//以及重要的  wcex.lpfnWndProc  = WindowProc;
		//让系统找到 窗口消息函数
	}
	//注册窗口 注册失败返回0, 退出程序

	if( !Register())
	{
		return 0;
	}
	
	//完成窗口的创建 并将返回值赋值给 hwnd
	hwnd = CreateWindow(){}

	if( ! hwnd)   //判断是否创建成功 不成功则返回 0 退出程序
	{
		return 0;
	}
	
	ShowWindow(); //显示窗口

	UpdateWindow(); //更新窗口

	//完成消息循环
	while( GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);      

		DispatchMessage(&msg); 
	}
	
	return msg.wParam //消息循环时 返回消息的某个字段
}


完成到这里,已经基本完成了,这篇文章主要介绍了 Window程序设计的框架,其他的就不在讨论范围了,  像一些系统函数的参数为什么这样  这些问题  只有MSDN 帮到你了

这里强烈建议 想学好的朋友 安装一个MSDN 

之前有一个朋友问过我 :你这么厉害啊 函数的参数表都记住了,,我说 ,你来记吧 谁会这么无聊记参数表,其实我只是在MSDN上 查到了 然后粘贴复制的问题罢了。

最后说明  本文写给刚刚进入可视化编程学习的朋友  希望对他们有帮助,,  另本文完成得比较仓促    文中有笔误或者不妥之处就请各位路过的大牛不吝指出,并一起讨论。一起学习了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值