• 深入浅出MFC——Win32程序基本概念(一)


    1. Windows程序分为“程序代码”和“UI资源”,下图所示:

    2. Windows支持动态链接(应用程序所调用的Windows API函数是在“执行时期”才链接上的)。Windows程序调用的函数可分为如下两部分:

      (1)C Runtimes:LIBC.LIB(C Runtime 函数库的静态链接版本)、MSVCRT.LIB(C Runtime函数库动态链接版本(MSVCRT40.DLL)的Import 函数库。如果链接这一函数库,你的程序执行时必须有MSVCRT40.DLL在场。

      (2)Windows API:由操作系统本身(主要是Windows三大模块GDI32.DLL、USER32.DLL、KERNEL32.DLL)提供。虽说动态链接是在执行时期才发生”链接“事实,但在链接时期,链接器仍需先为调用者准备一些适当的信息,才能够在执行时期顺利”跳“到DLL中执行。如果该API所属的函数库尚未加载,系统也才因此知道要先行加载该函数库。这些适当的信息放在所谓的”import 函数库”中。32为的Windows 的三大模块所对应的import函数库分别为GDI32.DLL、USER32.DLL、KERNEL32.DLL。

    3. 所有 Windows程序都必须载入 WINDOWS.H(三大模块所提供的API函数)。

    4. Windows程序的进行系依靠外部发生的事件来驱动(消息循环,通过消息映射表(Message Map)实现),也即,以消息为基础的事件驱动系统。接受并处理消息的主角就是窗口。每一个窗口都有一个所谓的“窗口函数”负责处理消息(由于窗口函数是被Windows系统所调用,也就所谓的“Callback函数”,意思是指“在你的程序中,被Windows系统调用”的函数。故而一般是全局函数或static成员函数)。

    5. 窗口的生命周期:

     

    6. 消息队列和空闲时间:当“系统中没有任何消息等待处理”,也即空闲时间。程序采用GetMessage(如果没有消息,则过门不入,操作系统执行其他的线程),PeekMessage(如果没有消息,仍取回控制权,是程序得以执行一段时间)。

    7. 说到Windows程序,一定得有WinMain、消息循环、窗口函数。与之对应的则是console程序("DOS-like"程序,而且仍然可以调用部分的、不牵扯到图形使用者(GUI)的Win32 API)。DOS程序则为过去在DOS环境下开发的程序。DOS程序时所谓的MZ格式(MZ ,Mark Zbikowski,它是DOS系统的一位主要建构者)。console程序的格式和所有的Win32程序一样,是所谓的PE(Portable Executable)格式,意思是它可以被拿到任何Win32平台上执行。

    8. Visual C++ 共有六个C Runtimes函数库

      (/ML)Single-Threaded(static) - libc.lib

      (/MT)Multithreaded(static) - libcmt.lib

      (/MD)Multithreaded DLL - msvcrt.lib

      (/MLd)Debug Single-Threaded(static) - libcd.lib

      (/MTd)Debug Multithreaded(static) - libcmtd.lib

      (/MDd)Debug Multithreaded DLL - msvcrtd.lib

    9. 可以说核心对象是系统的一种资源。系统给予核心对象一个计数值作为管理只用。核心对象包括下列数种:

    注:process对象——程序代码的执行时线程的工作(执行事实发生在线程身上),“process对象”只是一个数据结构,系统用它来管理进程。

    10. 进程的诞生与死亡

    注:只要把子进程以CloseHandle(WINDOWS.H)关闭,就达到“割断脐带”的目的。

    11. Windows程序除了调用Win32 API 外,通常也很难避免调用任何一个C Runtime函数。为了保证多线程情况下的安全,C Runtime函数库必须为每一个线程做一些登记工作。没有这些记录,C Runtime 函数库就不知道要为每一个线程配置一块新的内存,作为线程的区域变量用。因此,CreateThread有一个名为_beginthreadex的外包函数,负责额外的登记工作(其不是个标准的ANSI C Runtime函数)。(详见 《Win32多绪程序设计》)

    --------------------------------------------------------------------------------------------------------------

    C++基础:

    12. MFC有两个十分重要的虚函数:与document有关的Serialize函数和与View有关的OnDraw函数。

    13. 考虑下面代码:

    class Base
    {
        public:
            void func()
            {
                serialize();
            }
            virtual void serialize(){cout << "Base serialize ~" << endl;}
    };
    class Derived : public Base
    {
        public:
            virtual void serialize() {cout << "Derived serialize ~" << endl;}
    };
    
    void main()
    {
        Derived od;
        Derived *pod = new Derived;
    
        od.func();                             // test1: Derived serialize ~
        ((Base*)(&od))->func();      //test2: Derived serialize ~
        pod->func();                        //test3: Derived serialize ~
    
        ((Base)(od)).func();               //test4: Base serialize ~
    
    }

    注:test1-3,通过子类对象,或者父类指针(强制类型转换),或者子类指针,由于子类重写了父类的虚函数,故而均调用子类的serialize。test4中,由于((Base)(od)).func()是传值而非传址操作,编译器以所谓的拷贝构造函数,把Base对象内容复制了一份使得od的vtable内容与Base对象的vtable相同
    14. 不要把static成员变量的初始化操作安排在类的构造函数中,应为构造函数可能一再被调用,而变量的初值却只应该设定一次。设定static成员变量初值时,不受任何存取权限的束缚(public、protected、private)。但存取static变量则需要将其设为public。可以通过类名,也可以通过对象来存取static成员变量。

    15. C++ 的new运算子和C的malloc函数都是用于配置内存,但前者比之后者的优点是,new 不但配置对象所需的内存空间,同时会引发构造函数的执行

    16. 四种不同的对象生存方式(in stack、in heap、global、local static):

    17. RTTI(Runtime Type Information,运行时类型识别),MFC的RTTI能力牵扯到一组非常神秘的宏(DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC)和一个非常神秘的类(CRuntimeClass)。

    18. MFC支持动态创建,靠的是一组宏(DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE)和一组类(CRuntimeClass)。

    19. Templates的编译与链接:

  • 相关阅读:
    Go 工作空间 深度解析
    go语言中获取变量类型的三种方法
    go语言实现分布式对象存储系统之单体对象存储
    curl命令用法
    删除Git服务器文件但是保留本地文件
    pycharm之gitignore设置
    通过pycharm使用git
    python 有关datetime时间日期 以及时间戳转换
    Please, commit your changes or stash them before you can merge
    jinkins配置python虚拟环境
  • 原文地址:https://www.cnblogs.com/yyxt/p/4847176.html
Copyright © 2020-2023  润新知