• 22、深入浅出MFC学习笔记,MFC解剖相关


    1、需要的函数库

    Windows C Runtime函数库

    DLL Import函数库

    MFC 函数库[1,P264]

    2、传统SDK程序中WinMain所完成的工作现在由CWinApp的三个函数完成:

    virtual BOOL InitApplication();//内部管理初始化工作

    virtual BOOL InitInstance();//创建窗口

    virtual int Run();//分发消息

    WinMain只是扮演驾驭它们的角色。

    CFrameWnd取代WndProc的地位。

    一般CMyWinApp要改写CWinApp中的InitInstance,而不改写InitApplicationRun

    3、在创建窗口时,改变图标和鼠标光标形状的介绍,可以参见[1,P289]

    4、奇怪的窗口类名称 Afx:b:14ae:6:3e8f[1,P290]

    spy++ 这类工具观察窗口类名称, 却发现窗口类名称变成这幅奇怪模样, 原来是 Application Framework 玩了一些把戏, 它把这些窗口类名称转换为 Afx:x:y:z:w 的形式, 成为独一无二的窗口类的名称:

    x: 窗口风格(window style) hex

    y: 窗口鼠标光标的 hex

    z: 窗口后台颜色的 hex

    w: 窗口图标(icon)hex

    5MFC来龙去脉整理

    程序的诞生

    Application object 产生, 内存于是获得配置,初值亦设立了。

    AfxWinMain执行AfxWinInit,后者又调有AfxInitThread,把消息队列尽量加

    大到96

    AfxWinMain执行InitApplication。这是CWinApp的虚拟函数,我们通常不改写它

    AfxWinMain执行InitInstance。这是CWinApp的虚拟函数,我们必须改写它

    CMyWinApp:: InitInstance new”了一个CMyFrameWnd对象

    CmyFrameWnd构造函数调用Create,产生主窗口。我们在Create参数中指定的窗口类是NULL,于是MFC根据窗口种类,自行为我们注册一个名为“AfxFrameOrView42d”的窗口类。

    回到InitInstance中继续执行ShowWindow,显示窗口

    执行UpdateWindow,于是发出WM-PAINT

    回到AfxWinMain,执行Run,进入消息循环。

    程序开始运行:

    程序获得WM-PAINT消息(由CWinApp::Run中的::GetMessage循环)

    WM-PAINT经由::DispatchMessage送到窗口函数CWnd::DefWindowProc中。

    CWnd::DefWindowProc将消息传递到消息映射表格

    传递过程中发现有相符项目,于是调用项目中对应的函数。此函数是利用BEGIN_MESSAGE_MAPEND_MESSAGE_MAP之间的宏设立起来的。

    标准消息的处理程序亦有标准命名,例如WM-PAINT必由OnPaint处理

    程序的死亡:

    使用者单击File/Close,于是发出WM-CLOSE

    CMyFrameWnd并没有设置WM-CLOSE处理程序,于是交给默认的处理程序

    默认函数对于WM-CLOSE的处理方式是调用::DestroyWindow,并因而发出WM-DESTROY

    默认的WM-DESTROY处理方式是调用::PostQuitMessage,因此发出WM-QUIT

    CWinApp::Run收到WM-QUIT后会结束内部之消息循环,然后调用ExitInstance,这是CWinApp的一个虚拟函数;如果 CMyWinApp改写了ExitInstance,那么CWinApp::Run所调用的就是CMyWinApp::ExitInstance,否则就是CWinApp::ExitInstance

    最后回到AfxWinMain,执行AfxWinTerm,结束程序

    6Callback函数

    凡是由程序员设计而却由Windows 系统调用的函数,统称为callback 函数。这些函数都有一定的类型,以配合Windows的调用动作。

    要把某个函数用作callback 函数,就必须告诉C++ 编译器,不要放this 指针作为该函数的最后一个参数[5]

    两个方法可以做到这一点:

    1)不要使用类的成员函数(也就是说,要使用全域函数)做为callback 函数。

    2)使用static 成员函数。也就是在函数前面加上static 修饰词。

    为什么要这样呢?

    因为callback 函数是给Windows调用用的,Windows 并不经由任何对象调用这个函数,也就无法传递this 指针给callback 函数,于是导致堆栈中有一个随机变量会成为this 指针,而其结果当然是程序的崩溃了。

    内存中只会有一份类成员函数,但却可能有许多份类成员变量(每个对象拥有一份)。

    示例 LineDDA的使用

    The LineDDA function determines which pixels should be highlighted for a line

    defined by the specified starting and ending points. 这个函数以Bresenham算法计算出通过两点之间直线中的每一个屏幕像素坐标;每计算出一个坐标,就通知由LindDDA第五个参数所指定的callback函数。

    示例代码

    class CMyFrameWnd : public CFrameWnd
    {
    ....
    private:
    DECLARE_MESSAGE_MAP()     // Declare Message Map
    static VOID CALLBACK LineDDACallback(int,int,LPARAM);
    };
    

    .cpp

    void CMyFrameWnd::OnPaint()
    {
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(rect);
    dc.SetTextAlign(TA_BOTTOM | TA_CENTER);
    ::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2,
    (LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc);
    }
    //--------------------------------------------------------------------
    VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM lpdc)
    {
    static char szText[] = "Hello, MFC";
    ((CDC*)lpdc)->TextOut(x, y, szText, sizeof(szText)-1);
    for(int i=1; i<50000; i++);  //延迟
    }
    

    空闲时间的处理,通用对话框[1,P300]

    参考

    [1] 深入浅出MFC

    [2] MFC Technical Notes

    http://msdn.microsoft.com/en-us/library/h6h0eact%28VS.80%29.aspx

    [3] http://blog.163.com/zhoumhan_0351/blog/static/3995422720103401415721/

    [4] http://blog.163.com/zhoumhan_0351/blog/static/3995422720103411551637/

    [5] http://www.cnblogs.com/mydomain/archive/2011/02/25/1965310.html

  • 相关阅读:
    MongoDB使用命令列表
    关于.Net WebProxy【转】
    第七章、基本数据类型(tuple)
    第六章、基本数据类型(list)
    python JOB(作业)
    第五章、基本数据类型(int、str)
    第四章、Python运算符
    第三章、pycharm配置
    第二章、python初识以及变量
    第一章、python学习大纲
  • 原文地址:https://www.cnblogs.com/mydomain/p/1965788.html
Copyright © 2020-2023  润新知