zoukankan      html  css  js  c++  java
  • 定位MFC中SDK用于创建窗口的API

     

    本文是i春秋论坛作家「flag0」表哥原创的一篇技术文章,关于定位MFC中SDK创建窗口API位置的相关内容,感兴趣的小伙伴快来学习吧。

    SDK中用于创建窗口的API

    在SDK中创建窗口的过程,我们可以将其称为为创建窗口6要素。其分别为:

    1、设计窗口类;

    2、创建窗口实例;

    3、显示窗口;

    4、更新窗口;

    5、建立消息循环;

    6、实现窗口过程函数。

    其中对应的API为:

    1、RegisterClass;

    2、CreateWindow;

    3、ShowWindow;

    4、UpdateWindow;

    5、GetMessage、TranslateMessage、DispatchMessage;

    6、WindowProc、DefWindowProc。

    在MFC中对其进行了封装,接下来我们通过一系列的操作来定位到MFC中对应的SDK窗口的创建过程。

    MFC单文件工程

    一、定位消息循环

    创建完项目后,配置项目属性。

    属性页->配置属性->高级->在静态库中使用MFC

    将其默认的在共享 DLL 中使用 MFC改成在静态库中使用MFC,就可以进行MFC框架的调试了。

     

    消息循环,使用F10无法步过,会陷入到函数里面,所以可以采用一路F10,然后依次跟进循环里面的方法来进行。

    按F10运行断到Main函数的位置。

     

    按F11跟进AfxWinMain函数中(此处如果不进行配置在静态库中使用MFC会进入到别的函数)。

     

    接下来一路F10,可以看到程序陷入了函数中。

     

    下断点,重新运行,F11进入该函数。

     

    接着F11进入CWinThread::Run( )

     

    可以看到for循环是一个死循环,接着一路F10,可以发现程序在do while语句之间一直循环。

     

    do while循环中有三个函数,我们进入PumpMessage( )函数进行查看:

     

    再紧接着进入AfxInternalPumpMessage( )函数中

     

    可以看到该函数中存在处理消息的APIGetMessage、TranslateMessage、DispatchMessage,据此可以判定,其为消息循环部分。

    二、定位窗口过程函数

    窗口过程函数是用来处理消息的,可以在发送消息处,下断点,通过栈回溯,找到窗口回调函数。

    在控件操作处下断点,然后运行,触发该操作。

    这里我们选择的是关于窗口的确定按钮控件。

     

    点击关于窗口的确定按钮

     

    可以看到断在了下断点的位置,打开调用堆栈窗口从上往下依次分析。

     

    窗口过程函数的参数为:

    • HWND hWnd
    • UINT Msg
    • WPARAM wParam
    • LPARAM lParam

    从上到下依次进行分析,哪个调用函数符合。

    最终定位到CALLBACK,其参数列表完全符合,可以确定其就是窗口过程函数。

     

    3、UpdateWindow && ShowWindow

    MSDN对该API描述如下:如果窗口的更新区域不为空,则通过向窗口发送WM_PAINT消息来更新指定窗口的客户端区域。该函数直接向指定窗口的窗口过程发送WM_PAINT消息,绕过应用程序队列。如果更新区域为空,则不发送消息。

    我们可以判断,其会发送WM_PAINT消息,所以我们寻找MFC中的绘制函数在绘制时会发送WM_PAINT消息,最终确定了OnDraw函数。

     

    在OnDraw函数内部下断点

     

    运行后查看调用堆栈

     

    双击进入该函数即可看到UpdateWindow API

     

    再往上回溯一层

     

    进入InitInstance( )可以看到ShowWindowAPI

     

    UpdateWindow当有效区存在时会调用窗口过程函数,发送WM_PAINT消息。

    关系链如下:

    UpdateWindow->(发送WM_PAINT消息)->WndProc->(处理WM_PAINT消息)->OnDraw

    因此可以通过栈回溯定位到UpdateWindow

    4、CreateWindow

    在返回之前,Create Window向窗口过程发送WM_CREATE消息。

    因此在处理WM_CREATE处下断点,通过栈回溯可以定位到CreateWindow。

    在MainFrm.cpp中的OnCreate函数处下断点。

     

    查看调用堆栈,进行分析。

     

    可以看到其参数与CreateWindowAPI的参数列表完全吻合

     

    可以判定其就是CreateWindowAPI

     

    5、定位RegisterClass

    通过CreateWindow的类名进行回溯RegisterClass

     

    查看调用堆栈中上一层的函数的调用。

     

    可以看到其也来源于上层函数调用,再往上回溯一层。

     

    此时可以看到类名来源于GetIconWndClass函数,按F9下断点,F5继续运行到当前断点后F11跟进去。

     

    我们关注该函数的返回值,可以看到其有两个返回,排除返回为NULL的那个,在另一个返回处下断点,跟进。

     

    我们同样关注该函数的返回,其有两个返回,从上到下依次进行分析,首先在GetClassInfo处下断点跟进。

     

    按F11发现其并没有进入函数内部,继续关注另一个函数AfxRegisterClass,下断点跟进。

     

    在该函数内部可以发现RegisterClass的宏定义,跟进后确定其RegisterClassAPI的位置。

     

    以上我们依次找到了创建窗口的六要素的位置。

    总结

    1、RegisterClass通过CreateWindow回溯ClassName。

    2、CreateWindow找到处理WM_CREATE消息处OnCreate,进行栈回溯。

    3、UpdateWindow找到处理WM_PAINT消息处OnDraw处下断点进行栈回溯。

    4、ShowWindow找到处理WM_PAINT消息处OnDraw处下断点进行栈回溯。

    5、消息循环F10,然后依次跟进循环内部进行分析。

    6、窗口过程函数在发送消息处,下断点,通过栈回溯,找到窗口回调函数。

    以上就完成了MFC单文件工程中,SDK创建窗口API的定位。

    以上是今天要分享的内容,大家看懂了吗?

  • 相关阅读:
    安装oracle 使用vnc无法打开terminal,解决办法
    linux服务器配置本地yum仓库
    less css 框架介绍
    html的概念
    html
    WEB前端第三十八课——js类和对象,继承,设计模式
    WEB前端第三十七课——jsBOM操作-DataParse、jsEngine、性能、history、道岔、closure
    WEB前端第三十六课——jsBOM操作-window、timer
    WEB前端第三十五课——事件绑定应用案例
    WEB前端第三十四课——js事件对象this、event
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/13364862.html
Copyright © 2011-2022 走看看