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

来源:互联网 发布:新加坡管理大学 知乎 编辑:程序博客网 时间:2024/05/16 11:21

从个人的学习经验看来。为了少走弯路,在深入学习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(光标)的IDwcex.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 wcexHWND hwnd;MSG msg;// 窗口注册Init(){//窗口的注册,完成一些必要的初始化;//主要用到了 WNDCLASS wcex 这个结构个各种字段;//以及重要的  wcex.lpfnWndProc  = WindowProc;//让系统找到 窗口消息函数}//注册窗口 注册失败返回0, 退出程序if( !Register()){return 0;}//完成窗口的创建 并将返回值赋值给 hwndhwnd = 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上 查到了 然后粘贴复制的问题罢了。

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

 

原创粉丝点击