您的位置:首页 > 其它

MFC——1.浅谈Windows程序内部运行机制

2016-02-23 16:21 267 查看

======写在前面=====

这一系列的MFC笔记,主要参考了孙鑫老师的《VC++深入详解》和毛星云老师的《Windows游戏编程之从零开始》。

前面来源于孙鑫老师的VC++视频教程,如果大家有时间,可以在网上下载学习参考。

后面参考了毛星云老师的著作,这里也给上毛星云作者的博客地址:http://blog.csdn.net/poem_qianmo?viewmode=contents

============================

lesson1:浅谈Windows程序内部运行机制

1.Windows 消息响应机制

Windows程序不同于传统的dos方式的设计方法,它一种事件驱动的,是基于消息的,操作系统将用户的需要包装成消息,然后将消息投递到消息队列中,最后应用程序从消息队列中取走消息并进行响应。

Windows应用程序,操作系统,计算机硬件之间的相互关系:



箭头①表示操作系统能够操作输出设备,箭头③表示应用程序可以通知操作系统执行某个具体的动作,如操作系统能够控制声卡发出声音,但它并不知道应该何时发出何种声音,需要应用程序告诉操作系统该发出什么样的声音。箭头②表示操作系统能够感知输入设备状态的变换,箭头④表示操作系统能够将输入设备的变化上传给应用程序。如用户在某个程序活动时按了一下键盘,操作系统马上能够感知到这一事件,并且能够知道用户按下的是哪一个键,操作系统并不决定对这一事件如何作出反应,而是将这一事件转交给应用程序,由应用程序决定如何对这一事件作出反应。因此操作系统相当于是一个中介。

那么,应用程序是如何通知操作系统执行某个功能的呢?在应用程序中要完成某个功能,都是以函数调用的形式实现的,同样,应用程序也是以函数调用的方式来通知操作系统执行相应的功能的。操作系统所能够完成的每一个特殊功能通常都有一个函数与其对应,也就是说,操作系统把它所能够完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用就叫做系统调用,这些函数的集合就是Windows操作系统提供给应用程序编程的接口(Application
ProgrammingInterface),简称Windows API。

操作系统是怎样将感知到的事件传递给应用程序的呢?这是通过消息机制(Message)来实现的。操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序,参看MSDN。每一个应用程序都用一个消息队列,它是一个先进先出的缓冲队列,每一个元素都是一个消息。应用程序取得消息得知用户的操作。至于消息的处理,是通过消息响应程序处理的,操作系统自动调用消息响应函数,但消息的响应方式,即这个函数得自己编写。这个可以是用Windows自己默认的处理函数,和可以自己编写处理函数。MSG结构定义如下:

typedef struct tagMSG {

HWND hwnd; //窗口句柄,指定与消息相关的窗口

UINT message; //用无符号整型指定消息类型,Windows的消息都是提前用整数表示好的

WPARAM wParam; //指定消息的附加信息

LPARAM lParam; //指定消息的附加信息

DWORD time; //指定消息投递的时间

POINT pt; //指定消息投递时光标的位置

} MSG;

2. 创建一个完整的窗口需要经过下面四个操作步骤:

【1 设计一个窗口类】:窗口背景,鼠标,光标,窗口最大化,最小化,窗口名称,窗口设计时,有相应的窗口类,我们只需要给成员变量赋相应的值,达到我们需要的结果;

【2 注册窗口类】:向操作系统声明,有这样一种设计的窗口;

【3 创建窗口】:产生窗口;

【4 显示及更新窗口】:窗口发生变化时(移动),重新绘制窗口。

下面是程序代码,并附有完整的注释。

#include<windows.h>             //windows的头文件
#include<stdio.h>               //C语言的头文件

LRESULTCALLBACK WinSunProc(     //消息响应函数,函数原型的申明,以被后面调用
HWND hwnd,     <span style="white-space:pre">		</span>// handle to window
UINT uMsg,      <span style="white-space:pre">		</span>// message identifier
WPARAM wParam,  <span style="white-space:pre">		</span>// first message parameter
LPARAM lParam   <span style="white-space:pre">		</span>// second message parameter
);

intWINAPI WinMain(              //Windows程序入口点函数 WinMain函数
HINSTANCE hInstance,          // handle to current instance 当前运行实例句柄
HINSTANCE hPrevInstance,      // handle to previous instance 先前一实例句柄(同一个应用程序之间)
LPSTR lpCmdLine,              // command line  命令行参数
int nCmdShow                  // show state  状态显示,指定程序窗口如何显示(最大化,最小化,隐藏等)
)
{
WNDCLASS wndcls;        //【第一步 设计一个窗口类】</span>
wndcls.cbClsExtra=0;    //额外的类的附加内存空间,附加字节数,通常设为0
wndcls.cbWndExtra=0;    //窗口的附加内存空间,附加字节数
wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);   //窗口背景  HBRUSH是数据类型强制转换
wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);                  //光标
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);                      //图标
wndcls.hInstance=hInstance;                                 //应用程序的实例号
wndcls.lpfnWndProc=WinSunProc;                              //窗口过程函数,就是消息响应函数。操作系统自动调用这个函数,但消息响应函数得自己写收到消息时的处理动作
wndcls.lpszClassName="Weixin2003";                          //类名
wndcls.lpszMenuName=NULL;                                   //菜单名字(没有菜单)
wndcls.style=CS_HREDRAW |CS_VREDRAW;                        //窗口刷新类型是水平和垂直重画,移动窗口时发生(水平/垂直坐标变换),
//如果没有重绘,窗口移动时,上面的图片或文字不发生变化
RegisterClass(&wndcls);                                     //【第二部 注册窗口类】</span>以被调用

HWND hwnd;                                                  //【第三部 创建窗口】</span>定义句柄
hwnd=CreateWindow("Weixin2003","北京维新科学技术培训中心",WS_OVERLAPPEDWINDOW,
0,0,600,400,NULL,NULL,hInstance,NULL);               //(类名,窗口名字,窗口类型,窗口坐标x,y和窗口大小高、宽,
//副窗口,菜单,实例的句柄,窗口创建的数据)

ShowWindow(hwnd,SW_SHOWNORMAL);                             //【第四部 显示及更新窗口】</span>
UpdateWindow(hwnd);

MSG msg;                                                    //消息循环
while(GetMessage(&msg,NULL,0,0))     //获得消息,返回值为真,为假程序退出所有消息都获取(消息信息,窗口句柄指定哪个窗口的消息<span style="font-family: Arial, Helvetica, sans-serif;">null表示获取所有消息,</span>                                            //最后两参数为消息过滤,最小消息值(第一个鼠标消息或键盘消息),最大消息值,当两个为0 ,表示所有消息)
{
TranslateMessage(&msg);                               //转换消息并投递到消息队列中
DispatchMessage(&msg);                                //将消息从消息队列中取出并传递给窗口的过程函数(回调函数CALLBACK)
}                                                            //可以理解为它把消息给操作系统,然后操作系统做出相应动作,动作是我们编写的CALLBACK函数
return 0;
}

LRESULTCALLBACK WinSunProc(                                         //编写的响应消息的回调函数CALLBACK函数
HWND hwnd,      // handle to window
UINT uMsg,      // message identifier
WPARAM wParam,  // first message parameter
LPARAM lParam   // second message parameter
)
{
switch(uMsg)
{
case WM_CHAR:                                                    //输入字符
char szChar[20];                                          //定义字符数组
sprintf(szChar,"char is%d",wParam);                       //格式化文本到内存buffer中
MessageBox(hwnd,szChar,"weixin",0);                       //弹出窗口内容  文本内容szChar 标题weixin 窗口类型0
break;
case WM_LBUTTONDOWN:                                             //左单击鼠标
MessageBox(hwnd,"mouseclicked","weixin",0);               //弹出消息框
HDC hdc;                                                  //定义HDC结构体 ,设备上下文句柄,device contest句柄,DC帮助我们与显示程序交互
hdc=GetDC(hwnd);
TextOut(hdc,0,50,"计算机编程语言培训",strlen("计算机编程语言培训"));  //在0,50输出内容
ReleaseDC(hwnd,hdc);                                      //释放
break;
case WM_PAINT:                                                   //窗口重绘
HDC hDC                                                   //定义
PAINTSTRUCT ps;                                           //定义结构体
hDC=BeginPaint(hwnd,&ps);                                 //开始,这对函数只能在WM_PAINT中使用
TextOut(hDC,0,0,"维新培训",strlen("维新培训"));
EndPaint(hwnd,&ps);                                       //结束
break;
case WM_CLOSE:                                                   //关闭窗口
if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO))   //判断是否结束
{
DestroyWindow(hwnd);                               //销毁窗口,此函数Y会传递一个消息位WM_DESTORY
}                                                         //即下一个case的地方
break;
case WM_DESTROY:                                                 //销毁窗口
PostQuitMessage(0);                                       //退出
break;
default:                                                         //返回缺省的窗口处理方式
returnDefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}


程序思路很简洁,WinMain为主函数,主函数进行设计、注册、产生和重绘窗口。在设计窗口的时候指定了窗口的消息响应函数WinSunProc,因此每一个消息都用WinSunProc函数进行处理。

下面是附加的参考文献:

1. 消息函数 typedef structtagMSG

参考 http://blog.ifeng.com/article/2683896.html
2. 窗口建立函数 int WINAPI WinMain

参考 http://blog.csdn.net/seawave/article/details/1338879
程序运行截图:







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: