• MFC基础类及其层次结构


    从类CCmdTarget派生出绝大多数MFC中的类,其层次结构如下图:

    从根类Cobject层层派生出绝大多数MFC中的类,层次结构如下图:

    MFC中重点类:

    CObject类是MFC的绝大部分类的基类。该类完成动态空间的分配与回收,支持一般的对象诊断、运行时类型标识,出错信息处理和文档序列化等。

          (1)对象诊断:利用成员函数AssertValid进行对象有效性检查;利用成员函数Dump输出对象的数据成员的值,诊断信息以文本形式放入一个数据流中,用于调试器的输出窗口信息显示。(只能用于Debug版的应用程序)

          (2)运行时类型识别GetRuntimeClass根据对象的类返回一个相关联的指向CRuntimeClass结构的指针,它包含了一个类的运行信息;函数IsKindOf用于测试对象与给定类的关系。

          (3)通过与Carchive相结合CObject类为其派生类提供了序列化功能。要创建一个支持序列化的派生类,必须将DECLARE_SERIAL宏添加到类定义中,将IMPLEMENT_SERIAL添加到类的实现文件中。

      

      CCmdTarget:由CObject类直接派生,所有能实行消息映射MFC类的基类。将系统事件和窗口事件发送给响应这些事件的对象,完成消息发送、等待和派遣(调度)等工作,实现应用程序的对象之间协调运行,功能如下:

      (1)消息发送:MFC应用程序为每个CCmdTarget派生类创建一个称为消息映射表的静态数据结构,可将消息映射到对象所对应的消息处理函数上。

      (2)设置光标:程序正在进行某种操作:BeginWaitCursor()将光标改为沙漏形状;操作完成:EndWaitCursor()将光标改回到之前的形状;处于等待状态时由于某些操作改变了光标形状后,RestoreWaitCursor()用于将光标还原为等待状态。

      (3)支持自动化:CCmdTarget类支持程序通过COM接口进行交互操作,自动翻译COM接口的方法。方法是调用EnableAutomation()、FromIDispatch()、GetIDispatch()、IsResultExpected()和 OnFinalRelease()。

      CWinThread类:

      由CCmdTarget派生,主要工作是创建和处理消息循环

      CWinApp: 从CWinThread类派生而来。CWinThread类用来完成对线程的控制,包括线程的创建,运行,终止和挂起等。成员函数InitApplication()、InitInstance()、Run()。

    MFC应用程序中有且仅有一个CWinApp派生类的对象,代表程序运行的主线程,代表应用程序本身

      CDocument: 文档类,包含了应用程序在运行期间所用到的数据。从CCmdTarget派生,作为用户文档的基类,代表了用户存储或打开一个文件。主要功能是把对数据的处理从对用户的界面处理中分离出来,同时提供一个与视图类交互的接口。常用的成员函数有:

    OnNewDocument():建立新文档。

    OnOpenDocument():打开一个文档。

      CWnd: 通用的窗口类,用来提供windows中所有的通用特性。由CCmdTarget类直接派生,是MFC中最基本的GUI对象。公共变量m_hWnd用于存放供API函数调用的窗口句柄。CWnd类和消息映射机制隐藏了窗口函数WndProc。一个Windows消息通过消息映射发送到相应的CWnd类OnMessage成员函数,可以重载。

      CView: 用于让用户通过窗口来访问文档以及负责文档内容的显示。文档视图结构中的用户操作区。

      CFrameWnd: 从CWnd继承来的,并实现了标准的框架应用程序。主要用来掌管一个窗口。其对象是一个框架窗口,包括边界、标题栏、菜单、最大化按钮、最小化按钮和一个激活的视图

      其常用成员函数:

        GetActiveDocument():得到当前文档的指针。

        GetActiveView():得到当前视图的指针。

        SetActiveView():激活一个视图。

        GetTitle():得到框架窗口的标题。

        SetTitle():设置框架窗口的标题。

        SetMessageText():设置状态栏文本。

      CDialog: 用来控制对话框窗口。

      CMDIFrameWnd和CMDIChildWnd: 分别用来多文档应用程序的主框架窗口和文档子窗口的显示和管理。

      CMiniFrameWnd:一种简化的框架窗口,没有最大化和最小化窗口按钮,也没有窗口系统菜单,很少用。

            WinApp封装了程序的主入口WinMain,WinMain就和C语言的main函数地位一样,是Win32程序的入口。在MFC的封装中,一个程序启动,Windows调用WinMain,这个WinMain函数现在由MFC事先写好藏好了,你不能也不需要修改,在这个预定义的WInMain里面会调用CWinApp的IniInInstance函数。在InitInstance函数,CMainFrame的对象被创建,文档模板被创建,主窗口通过ShowWindow(SW_SHOW)被显示出来。

      CMainFrame是个框架,是你整个应用程序的主窗口,负责管理应用程序的菜单,工具栏,状态栏等。中间的区域是客户区,由View类来管理,View类也是一个窗口,是MainFrame的子窗口。OnDraw函数负责绘制客户区的内容,你调用View类的UpdateWindow,或者在Document类中调用UPdateAllViews等等,MFC会自动调用OnDraw。他还会被Window调用,Windows在需要刷新窗口的时候发送给窗口WM_PAINT消息,MFC事先预定义了,在响应WM_PAINT消息的时候会调用OnDraw。 那么什么时候窗口会发送WM_PAINT消息呢,比如窗口从最小化还原,比如窗口被用户改变了大小等等。

      程序在进入WinMain函数之前做很多事情,初始化DOS头,分配函数表,初始化全局变量,之后才进入WinMain。

      MFC对Windows API进行封住请。MFC编译器链接器把源文件编译成PE文件格式,存储在磁盘上。程序执行的时候,从PE文件头开始执行,在进入Winmain函数之前,进行一系列的必备的初始化。

      MFC对这个过程进行封装,提供给编程人员的第一个裸露程序入口就是CWinApp的InitInstance(),其实程序的入口依然是WinMain()函数。

      每个程序都有一个进程,每个进程至少有一个线程就是主线程。CWinThread类是MFC用来封装线程的。这个主线程就是在WinMain函数中创建的,包括UI线程和工作者线程。因此每个MFC程序至少使用一个CWinThread派生类。被MFC程序员熟知的CWinApp应用类就从这里派生。

      InitInstance是CWinThread的一个虚函数,它是在实例创建时首先被调用的。应用程序总是要重载这个虚函数,进行系统设置,创建运行环境。主窗口一定要在InitInstance()中创建,因为该函数退出后就进入该线程的消息循环。

      MFC执行流程:_tWinMain(WinMain别名)-》AfxWinMain-》初始化线程,调用InitInstance初始化窗口,调用Run函数进入消息循环。

      MFC中DoDataExchange的作用:将界面上的控件与一个变量或对象关联。

    程序入口和执行流程

    1) WIN32 API程序当中,程序入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用程序窗口函数。而在MFC程序当中我们找不到类似WinMan这样的程序入口,取而代之的是一系列派生类的声明和定义以及一个从CWinApp类派生而来的类的全局对象。CWinApp类被称为应用程序对象,在一个MFC程序中只允许有一个应用程序对象。由于CWinApp的派生类对象是全局的,因此这个对象的构造函数会在所有的其他代码运行之前调用,而由于CWinApp类当中包含了HWND、HINSTANCE等句柄的存在,其构造函数就执行了对这些成员数据的初始化操作。

    2) 调用CWinApp的构造函数后,AfxWinMain函数被调用,而这个函数可以被看做MFC程序的入口函数。在这个函数当中调用全局AfxGetApp()函数获得应用程序对象,这时将调用AfxInit全局函数,功能是使用操作系统传递给AfxWinMain函数的参数初始化应用程序对象当中的相关句柄数据成员。

    3) AfxWinMain函数调用CWinApp::InitApplication()成员函数,初始化应用程序对象当中的关于文档部分的内容

    4) AfxWinMain函数调用CWinApp::InitInstance成员函数,函数中,用new在堆上声明一个框架窗口对象,框架窗口对象的构造函数被调用,构造函数当中调用Create函数来创建窗口,而调用的create函数一般将WNDCLASS参数设置成NULL,,这样就由MFC内部调用PreCreateWindow函数,在这个函数当中由MFC注册几个默认的WNDCLASS供框架窗口的Create使用。这时程序控制权交还给CWinApp::InitInstance成员函数内部,由这个函数调用CWnd::ShowWindow显示窗口并且调用CWnd::UpdateWindow向窗口发送WM_PAINT消息。调用完CWinApp::InitInstance成员函数后由AfxWinMain函数调用CWinApp::Run成员函数,并由这个函数来创建和处理消息循环,并且在没有消息的时候处理OnIdle空闲处理。至此整个程序的创建过程完成。

    5)在程序的运行过程当中,由操作系统源源不断的发送消息给应用程序,并且由CWinApp::Run当中的消息循环处理并且分发给相关的窗口对象的DefWindowProc成员函数,并由这个成员函数查询窗口对象的消息映射表,如果查到对应项,则由登记在消息映射表当中的类成员函数处理,否则则按照Message Route当中的顺序象父层类发送。

    6)在消息运行结束,用户按下关闭按钮后,操作系统向程序发送WM_CLOSE消息,默认状况下程序调用DestoryWindow并且发送WM_DESTORY消息,应用程序接受到这个消息以后的默认操作是调用PostQuitMessage函数,由这个函数发送WM_QUIT消息。当程序对象接受到WM_QUIT消息后消息循环结束,由AfxWinMain函数调用AfxTerm函数清理程序使用过的资源并且结束整个程序。

    消息机制

    1 消息机制的要点:

      消息队列:先进先出

      消息循环:通过循环while,不断的从消息队列中取得队首消息,并分发消息。

      消息处理:根据不同的消息类型做不同的处理

      事件:事件响应函数

    2 消息机制

    _tWinMain

    {

    // 注册窗口类

    if(!AppRegisterClass(hInstance)) // hInstance 是应用程序句柄,把这个和winproc注册上。

    {

    return (FALSE);

    }

    // 初始化应用程序窗口

    if (!InitInstance (hInstance, nCmdShow)) // 注册之后开始初始化应用窗口(createWindow得到g_hWnd ;ShowWindow(); UpdateWIndow)_)

    {

    return FALSE;

    }

    // 消息循环

    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))

    {

    TranslateMessage(&msg);

    DispatchMessage(&msg);

    }

    return (int) msg.wParam;

    }

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) //定义消息处理函数

    wndProc会根据message类型调用对应的事件响应函数。

    onDraw () // 每次刷新的时候都会重新绘制。

    对于每一个正在执行的Windows应用程序,系统为其建立一个"消息队列",也就是应用程序队列

    DispatchMessage会将消息传递给窗口函数,也就是WndProce函数。

    WndProc是一个回调函数,在注册窗口时通过wcex.lpfnWndProc将其传递给了OS,所以DispatchMessage分发消息后,OS会调用

    Wndproc去处理。

    消息的定义和类型:

    windows消息都以WM_为前缀,WM_PAINT. 

    typedef struct tagMsg

    HWND hwnd; //接受该消息的窗口句柄

    UINT message; //消息常量标识符,也就是我们通常所说的消息号

    WPARAM wParam; //32位消息的特定附加信息,确切含义依赖于消息值

    LPARAM lParam; //32位消息的特定附加信息,确切含义依赖于消息值

    DWORD time; //消息创建时的时间

    POINT pt; //消息创建时的鼠标/光标在屏幕坐标系中的位置

    }MSG;

    消息主要有3种类型:

    A: 命令消息:

    B: 标准窗口消息:

    C: Notification:

    队列消息和非队列消息: 按照是否需要放入队里

    POSMessage 与 SendMessage:

    POSMessage:发送到消息对列

    SendMessage:非对列消息。直接发送窗口,等待执行结束。

    常见面试题

    1:应用程序类

    CTestOneApp::InitInstance

    可以看做是MFC程序的入口函数,main函数隐藏在这个函数中。实际开发中一般不需要对这个类进行操作,但如果要在建立主对话框之前处理一些数据或者准备工作,就可以把代码添加到这个函数中,主对话框显示之前。

    这里有两个比较典型的应用:

    1)启动界面之前弹出个登录界面。

    2)启动界面之前,弹出一个项目配置界面。

    2:对话框类

    // CTestOneDlg 对话框类,继承自CDialogEx类。对话框类负责与用户交互,处理用户消息,接收用户输入。

    class CTestOneDlg : public CDialogEx

    {

    public:

    // 标准构造函数

    CTestOneDlg(CWnd* pParent = NULL);

    // 对话框数据

    enum { IDD = IDD_TESTONE_DIALOG }; 

    protected:

    // 动态数据交换,负责控件与变量之间的关联

    virtual void DoDataExchange(CDataExchange* pDX); 

    protected:

    //应用程序句柄

    HICON m_hIcon;

    //重载初始化对话框

    virtual BOOL OnInitDialog();

    //定义消息WM_SYSCOMMAND处理函数

    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

    //定义消息WM_PAINT处理函数

    afx_msg void OnPaint();

    //定义消息ON_WM_QUERYDRAGICON处理函数

    afx_msg HCURSOR OnQueryDragIcon();

    //消息映射

    DECLARE_MESSAGE_MAP()

    };

    这个类看出以下几点:

    1)控件与数据关联,可以简单的交给框架

    2)在MFC框架上开发主要是针对消息处理机制

    添加一个button,并且添加一个事件后:会有如下变化

    PUSHBUTTON "Button1",IDC_BTN_TEST,151,57,50,14 // RC 文件拿这个ID作为控件的标示

    #define IDC_BTN_TEST 1001 /resource.h 定义一个ID号。

    afx_msg void OnBnClickedBtnTest(); // 事件响应函数

    BEGIN_MESSAGE_MAP(CTestOneDlg, CDialogEx)

    ON_WM_SYSCOMMAND()

    ON_WM_PAINT()

    ON_WM_QUERYDRAGICON()

    ON_BN_CLICKED(IDC_BTN_TEST, &CTestOneDlg::OnBnClickedBtnTest) // 把事件,响应函数, 行为三者绑定到一起

    END_MESSAGE_MAP()

    void CTestOneDlg::OnBnClickedBtnTest() //事件响应函数

    {

    // TODO: 在此添加控件通知处理程序代码

    }

    3 SendMessage和 postMessage 区别

    SendMessage : 同步, 返回值表示处理消息后的返回值。

    postMessage: 异步,只是把消息放入队列,返回值仅表示post是否正确。

    同一个线程内:PostMessage只把消息放入队列,然后通过消息循环Dispatch到达窗口。SendMessage发送消息时,系统直接调用目标窗口的消息处理程序,并将结果返回。

    不同线程:最好用PostThreadMessage代替PostMessage。 SendMessage发送消息到目标窗口所属线程的消息队列,然后发送的线程等待,直 到处理完。

    4 onpaint() 和 ondraw()

    窗口改变后,产生无效区域,需要重绘,windows会发送WM_PAINT通知客户区变化,客户区的重绘需要自己完成。

    CVIew派生自CWnd, 而OnPaint()是CWnd 的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW的成员,没有响应消息功能。

    要想在屏幕上绘图,首先要建立设备环境DC,DC是一个数据结构,包含输出设备的绘图属性的描述。MFC提供了CPaintDC 类和CWindowDC 类

    实时响应,CPaintDC支持重画。

    当视图无效时(大小,移动,被遮盖)Windows将WM_PAINT消息发送给它 该视图的OnPaint处理函数通过创建CPaintDC类的DC对象来响应

    该消息并调用视图的OnDraw成员函数,通常不用重写ONpaint函数。

    void CView::OnPaint()

    CPaintDC dc(this);

    OnPreparDC(&dc);

    OnDraw(&dc); //调用了OnDraw

    }

    OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。

    void CMyView::OnDraw( CDC* pDC )

    CMyDoc* pDoc = GetDocument(); 

    CString s = pDoc->GetData(); // Returns a CString

    CRect rect;

    GetClientRect( &rect ); 

    pDC->SetTextAlign( TA_BASELINE | TA_CENTER ); 

    pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );

    }

    5 强制重画窗口

    InvalidateRect(&Rect) :使得指定的区域无效。

    Invalidate():使得整个窗口无效,形成无效矩形。

    UpdateWindow(): 立即发送WM_PAINT,不过在它发送前,先调用GetUpdateRect(hWnd,NULL,TRUE)看有无可 绘制区域,如果没有则不发送消息。

    RedrawWindow()是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。

    6  CView 与 CDcoument关系

    CVIew 有一个成员变量CDocument, 指向相关的Document.

    CView 与 Document交谈的过程:

    A:使用者在View做动作,取得Document指针,更改资料内容。

    B: View调用Document的UpdatedAllViews.

    C: 其他的view的onUpdate() 被调用, 各种view的画面就更新了。

    D:CVIew:Onupdate()被调用,代表通知他:document的内容已经改变了,你更新画面吧。 也可以用一种低效率的方式: invaalidate(TRUE),把窗口

    整个设为重绘区,产生WM_paint,再让Cview::OnDraw()。 

    7 你熟悉预编译指令么?条件编译是用来做什么的?你会写么?

    预编译指令: 在编译之前做一些事。

    #include : 文件包含

    #define: 宏替换

    # if, #ifndef, #ifdef, #endif, #undef : 条件编译。

    #pragma :布局控制。 主要是设定编译器的状态。 #pragma once                #pragma pack(n)

    8  C++ 中的string/WString

    string就是*char, wstring wchar_t, 用来处理中文,是宽字符。

    9 MFC用的是Unicode

    10 stdafx.h   头文件预编译

    把一个工程中使用的一些MFC标准头文件(windows.h Afxwin.h)预先编译,以

    后该工程编译时,不再编译这部分头文件。

    11 MFC包含几种类型程序?其中MFC应用程序又包含哪几类

    单文档(画图),多文档(vs 2015), 对话框.

    12 MFC的消息机制

    MFC使用一种消息映射机制来处理消息,一个消息与消息处理函数一一对应的消息映射表,以及消息处理

    函数的声明和实现代码。当窗口接收到消息的时候,会到消息映射表中查找消息的处理函数,然后消息处理函数进行

    处理

    13 消息映射

    Windows程序都维护有自己的消息队列,保持队列消息(当然也有非队列消息,他们直接发给窗口),并用消息循环

    对消息进行处理。

    消息循环首先通过GetMessage取得消息并从队列中移除,对于加速键,会调用TranslateAccelerator函数,对其进行

    翻译和处理,如果处理成功就不在调用translateMessge. 

    否则进行消息的转换和派发。让目的窗口的窗口过程来处理消息。

    while (GetMessage(&msg, NULL, 0, 0)) 

    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 

    TranslateMessage(&msg); 

    DispatchMessage(&msg); 

    真正处理消息的是所谓的窗口过程(LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)),这个函数的参数记录了过程对应的窗口、消息的ID以及参数,在其内部开发者可以实现。

    14 自定义消息

    A、自定义消息号:#define WM_CCTRY_MSG (WM_USER+100)

    B、在头文件中添加消息响应函数的声明:afx_msg LRESULT OnCcTryMsg(WPARAM wParam, LPARAM lParam);

    C、在CPP文件中添加消息响应函数的实现:

    LRESULT CXXXDlg::OnCcTryMsg(WPARAM wParam, LPARAM lParam) {

    //相关代码;

    }

    D、在 BEGIN_MESSAGE_MAP 与 END_MESSAGE_MAP 之间加入消息的映射代码:ON_MESSAGE(WM_CCTRY_MSG, &CDlgTestDlg::OnCcTryMsg)

    然后在想触发消息的地方:sendMessage(),就可以。

    15. MFC的对话框的种类,各自怎么使用?及相关函数。

    模态对话框和非模态对话框。

    模态对话框:工作时其父窗口无效。 DoModal();

    非模态对话框: dlg.Create(;)

    15 进程间通信

    管道(匿名): 半双工。只适合父子进程之间通信。传输的是流。所以进程间通信必须约定好数据格式。创建管道时,

            分配一个页面作为数据缓冲区,进程对缓冲区进行读写。

    有名管道:非父子进程也可以通信,有传输格式。

    消息队列:放在内核中的消息链表,

    信号量:

    共享内存:分配一块能被其他进程访问的内存。共享的内存被映射到两个进程的虚拟空间。但是需要自己提供同步机制。

    信号量,互斥锁都可以。

    这个效率最高,管道和消息队列需要在内核和用户空间数据拷贝。

    16 MFC程序的初始化http://www.jizhuomi.com/software/267.html

    建立MFC窗口很容易,只用两步:

    CWinApp派生一个应用程序,然后创建应用程序对象。initInstance()里面创建窗口就行。

    WinMain()函数:

    InitInstance 是程序入口点,是虚函数,应用程序初始化(其实也winmain函数调用它的)

    注意: 全局变量的的构造函数在main函数之前执行

    基本流程:

    注册窗口:注册后才能从系统中找到它,获得句柄,然后向窗口发送消息。

    创建窗口:

    显示更新窗口:show, update()

    消息循环:

    回调函数:

    17  消息映射机制的原理及实现。

    在每个能接收和处理消息的类中,定义一个消息和消息函数静态对照表,将消息与消息处理函数绑定。当处理消息的时候到这个表中去查就行了。

    BEGIN_MESSAGE_MAP() 宏中定义。

    18  ASSERT() ,是函数还是宏 

    预处理宏, assert(expr), 先计算表达式expr, 如果为假,那么它会输出信息并终止程序执行。

    如果用if else实现同样功能的话,就会从函数开始括到函数尾。

    assert是宏不是函数,定义在cassert头文件中。

    使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销;

    完成调试后,不必从源代码中删除assert()语句,因为宏NDEBUG有定义时,宏assert()的定义为空,

    即可以通过在包含#include assert.h>或#include< csaaert >的语句之前插入 #define NDEBUG 来禁用assert调用:

    assert只有在Debug版本中才有效,如果编译为Release版本则被忽略(程序一般分为Debug 版本和Release 版本,

    Debug 版本用于内部调试,Release 版本发行给用户使用);

    assert用法注意:

    A:不要一起判断多个条件,否则不知道是哪个有问题。

    B:不能改变变量的值、

    C: assert语句后面空一行。

    19 MFC消息三种类型

          在MFC应用程序中传输的消息有三种类型:窗口消息、命令消息和控件通知。  

    (1)窗口消息:WM_XXX,除WM_COMMAND之外,所有以WM_开头的消息

          窗口消息(Window Message)一般与窗口的内部运作有关,如:创建窗口、绘制窗口和销毁窗口等。通常,消息是从系统发送到窗口,或从窗口发送到窗口。  

    (2)命令消息:WM_COMMAND

          命令消息一般与处理用户请求相关,当用户单击一个菜单项或工具栏时,命令消息产生,并被发送到能处理该请求的类对象(如:装载文件、编辑文本和保存选项等)。  

    (3)控件通知:有多种格式

          通常,控件通知在某些重要事件发生时,由控件窗口发送到父窗口,如打开一个组合框。控件通知为父窗口进一步控制子窗口提供了机会。例如,打开一个组合框时,父窗口可以用组合框初建时得不到的消息填充它。  

          BN_XXXX是CButton产生的消息,EN_XXXX是CEdit产生的消息,等等。

    现在就可以知道为什么有ON_MESSAGE ,ON_COMMAND, , ON_NOTIFY了。

    ON_MESSAGE是处理所有的Windows的消息的,因为所有的消息都以相同的格式传送,也就是ID, WPARAM, LPARAM.

    ON_COMMAND是专门处理WM_COMMAND消息的,这样我们就不用自己解开WM_COMMAND中wParam和lParam中传送的控件ID, 事件种类…(所有的都在MFC内部解决了:),当然方便了。

    ON_NOTIFY更是不用说了,看看他的处理函数,是不是把NMHDR解出来了。

    20 MFC绘图有哪几类DC?各自的类名,及区别

       设备描述表(DC)是Windows中的一种数据结构,它包含GDI需要的所有关于显示界面情况的描述字段,包括相连的物理设备和各种各样的状态信息。从而提供了应用程序设计的平台无关性。

    HDC:设备上下文句柄(可以理解为指向DC结构的指针),它指向一块描述设备的相关的内容的内存块。

    CDC:是MFC里面的一个类,且这类封装了几乎所有关于HDC的操作,由于类的内部包含一个m_hWnd的句柄,

    所以,CDC封装的操作(函数)与SDK平台中与关于HDC的操作都缺少一个指向设备上的句柄(不是没有,而是这个句柄在被封装起来)。

    1)、HDC到CDC的转换:

    方法一: 此方法在设备结束时不会销毁原来的资源(即:hDC,hBitmap)

    CDC *pDC = CDC::FromHandle(hDC);

    方法二:此方法在设备结束时会销毁原来的资源(即:hDC,hBitmap)

    CDC dc;

    dc.Attach(hDC);

    2)、CDC到HDC的转换:

       CDC  dc;

       HDC  hDC;

       hDC = dc.GetSafeHdc();

    CPaintDC:

    CClientDC:

    CWindowDC:

    21:  MFC的线程有哪几类?相互有什么区别?各自的创建方法是什么

     两种:界面线程:有消息循环,能响应用户的界面操作,必须继承自CWinThread.

                工作线程:

      AfxBeginThread(RUNTIME_CLASS(MyThread));   二者的参数有区别。

    22 MFC常用控件?通用对话框?

    23 MFC的文件类?文件查找类?

  • 相关阅读:
    Kafka:ZK+Kafka+Spark Streaming集群环境搭建(三)安装spark2.2.1
    Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二)安装hadoop2.9.0
    JPA(七):映射关联关系------映射双向多对一的关联关系
    Kafka:ZK+Kafka+Spark Streaming集群环境搭建(一)VMW安装四台CentOS,并实现本机与它们能交互,虚拟机内部实现可以上网。
    JPA(六):映射关联关系------映射单向一对多的关联关系
    JPA(五):映射关联关系------映射单向多对一的关联关系
    Java-Shiro(四):Shiro Realm讲解(一)Realm介绍
    JPA(四):EntityManager
    JPA(三):JPA基本注解
    Java-Shiro(三):Shiro与Spring MVC集成
  • 原文地址:https://www.cnblogs.com/blogpro/p/11426696.html
Copyright © 2020-2023  润新知