孙鑫C++视频01:Windows程序内部运行原理

前言

从去年开始学C++后,然后学MFC后,就在纠结一个问题,到底要不要深入学windows和MFC,经常看见有人说MFC不行了,没人用了,大家都用QT,JAVA,C#,但是我想了想,学这些东西要有项目锻炼,而实验室用的还是MFC,所以今天我下定决心每天花一点时间学习MFC。

看CSDN论坛里,都说看孙鑫的视频,我绝对还是刷一遍。

本文只是自己的学习记录,无任何参考价值,有兴趣可以B站看视频(无广告舒服),百度下pdf《VC++深入详解》,个人建议看完视频再看书。

应用程序、操作系统、硬件的关系

                                                   

 上图的关系,很重要。①箭头代表操作系统能控制输出设备,如控制声卡发声;②箭头代表操作系统能得到输入设备信息,如键盘输入;箭头③代表应用程序通知操作系统执行某具体操作,如让声卡发出什么声音,操作系统的确有的发出声音的功能,但他不知道发出什么声音,这些需要应用程序来告诉。问题是应用程序如何告诉操作系统完成什么操作,操作系统提供一系列函数集合,也就是Windows操作系统提供给应用程序的接口(Application Programming Interface),简称API。④箭头将输入设备的变化告诉应用程序,操作系统能得到输入设备的信息,如键盘输入,但是操作系统不做处理,而是把此信息传递给应用程序,由应用程序来决定进行什么操作。对事件做出反应的过程,就是消息响应。

应用程序通过调用操作系统API可以对输出设备进行操作,但是操作系统如何将感知到事件传递给应用程序?通过消息机制!操作系统将每个事件都包装成一个称为消息的结构体MSG来传递给应用程序。

MSG

typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;

 窗口句柄HWND:首先介绍下句柄和

               

 message:消息,用整数来表示消息,比如说按键消息。但是一般上用宏来表示更直观,如WM_LBUTTONDOWN鼠标左键按下消息,记忆宏更方便。

WPARAM和LPARAM:都是两个整形,用于指定消息的附加信息。如按下字母A键,但是不管按下什么键都收到一个WM_CHAR键,如果要知道按下具体什么键,就要将字母A键的ASCII码放到WPARAM中。但是这两个其实都是整形,为什么要重新定义呢,容易让人知道这是消息的附加参数。

DWORD:4个字节,消息被传递出去的时间

POINT:点的结构体(x,y坐标),当消息被投递时,光标在屏幕的位置

 

关于消息队列,每个应用程序,操作系统都会创建一个消息队列(先进先出的缓冲区)。应用程序通过从消息队列获取消息,就可以知道当前按下的是什么键,然后对消息进行处理(也就是要写程序处理,可能会调用API),即消息响应。其实消息代表了用户的操作和状态,应用程序获取消息,对其响应,即让操作系统去操作具体的事情。

WinMain函数

                               

WinMain函数里的参数都是操作系统提供的,这个函数是由操作系统调用的。

第一个是实例句柄,第二个是先前实例句柄(NULL);

第三个是一个长指针,pCmdLine是一个以空终止的字符串,指定传递给应用程序的命令行参数。例如:在D盘下有一个sunxin.txt文件,当我们用鼠标双击这个文件时将启动记事本程序(notepad.exe),此时系统会将D:\sunxin.txt作为命令行参数传递给记事本程序的WinMain函数,记事本程序在得到这个文件的全路径名后,就在窗口中显示该文件的内容。要在VC++开发环境中向应用程序传递参数,可以单击菜单【Project】→【Settings】,选择“Debug”选项卡,在“Program arguments”编辑框中输入你想传递给应用程序的参数。

第四个是表现状态(最大化最小化)。如SW_MINIMIZE:最小化指定的窗口,并且激活在系统表中的顶层窗口。

WinMain是win32 application的入口函数,里面可以调用Windows API,而main()是控制台入口函数。

而WINAPI的定义是:#define WINAPI__stdcall。关于_stdcall后面在了解。

窗口的创建

窗口的创建包括4部分:1 窗口类的创建(窗口的图标等);2 注册窗口类;3 创建窗口;4 显示及更新窗口

 窗口类就是一个结构体。

style就是窗口类的类型。如水平重画(改变水平方向大小重画)。

看到这个,突然想到平常MFC那些宏的意义了。。。 果然还是要多看啊。

第二个参数,是个函数指针,也就是回调函数。回调函数真是处处可见!

后面关于参数就不详细记录了,可以百度或者翻书,这样效率太慢了。只记录那些有意义的。书籍可以参考:《VC++深入详解》。

后面的依次为类附加字节(0),窗口附加字节(0),hIcon图标句柄,hCursor光标句柄,画刷(画刷这里用到了强制转换),菜单名字,类名字。

 

窗口注册:RegsiterClass()函数

创建句柄:CreateWindow()函数

显示窗口:ShowWindow()函数

更新窗口:UpdateWindow()函数

 

之后,需要写一个消息循环,不断地从消息队列中取出消息,并进行响应。

:GetMessage函数从消息队列里取出消息,当消息为WM_QUIT时,返回为0或者出现错误返回-1,其他消息都为非零值。

消息循环代码:

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

TranslateMessage:对消息进行转换,将虚拟按键消息(按下和弹起)转换成字符消息。字符消息被投递到调用线程的消息队列中,当下一次GetMessage()被取出。

DispatchMessage函数将消息传给回调函数,也就是回传给操作系统。由操作系统调用窗口过程函数对消息进行处理。

                  

 窗口过程函数(回调函数)

    

 这个回调函数的4个参数和MSG一样,所以DispatchMessage(&msg)将消息参数传给回调函数。回调函数中有对不对消息的处理。

这段话,主要理解下啥叫DC。 DC后面再单独讨论,也是个重要话题。

WM_PAINT消息的响应,终于理解啥时候会执行WM_PAINT了。                                                                                                                          

                      

有点晕啊,那MFC中OnPaint()、OnSize又是啥,带着疑问学习吧。

总结

首先我想说,这视频(或者说这本书)对我的帮助实在是太大了,之间虽然也会用MFC,遇到问题就百度,但是看完看完第一章才知道自己理解的是多么肤浅。了解系统,了解了原理,用别人的轮子才会用的好。

因为时间的原因,第一章还有很多没有深入理解,我再啃个2~3遍。之前也看侯捷的《深入浅出MFC》,但是看不下去,但是感觉看完这视频,有点顿悟,回头在一起看下,相互互补下。

猜你喜欢

转载自blog.csdn.net/songsong2017/article/details/81708755