菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
439
0

MFC

原创
05/13 14:22
阅读数 44324

Win32程序

消息队列

 系统消息队列,窗口消息队列

主要函数

WinMain 函数

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPCSTR lpCmdLine, int nCmdShow)

{

         MSG msg;

         if (!hPrevInstance )

         {

                   if (!InitApplication(hInstance))

                   {

                            return false;

                   }

         }

 

         if (!InitInstance(hInstace,nCmdShow))

         {

                   return false;

         }

        

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

         {

                   TranslateMessage(&msg);

                   DispatchMessage(&msg);

         }

}

 

InitApplication - 注册窗口

 

BOOL InitApplication(HINSTANCE hInstance)

{

         WNDCLASS wc;

         wc.style = CS_HREDRAW | CS_VERDRAW;

         wc.lpfnWndProc = (WNDPROC) WndProc;

         ....

         return (RegisterClass(&wc);

}

 

InitInstance - 产生窗口

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

{

         _hInst = hInstance;

         _hWnd = CreateWindow(appName, title, ...); // 发送 WM_CREATE

         if (!_hWnd)

         {

                   return FALSE;

         }

         ShowWindow(_hWnd, nCmdShow);

         UpdateWindow(_hWnd); // 发送 WM_PAINT

         return TRUE;

}

 

WndProc - 窗口函数

LRESULT CALLBACK WndProc(HWND hWnd, UNIT message, WPARAM wParam, LPARAM lParam)

{

         int wmId, wmEvent;

         switch(message)

         {

                   case WM_COMMAND:

                            wmId = LOWORD(wParam);

                            wmEvent = HIWORD(wParam);

                            swich(wmId)

                            {

                                     case IDM_ABOUT:

                                               DialogBox(...);

                                               break;

                                     case IDM_EXIT:

                                               DestroyWindow(hWnd);

                                               break;

                                     defualt:

                                               return (DefWindowProc(hWnd,message,wParam,lParam));

                            }

                            break;

                   case WM_DESTROY:

                            PostQuitMessage(0);

                            break;

                   default:

                            return (DefWindowProc(hWnd,message,wParam,lParam));

         }

         return (0);

}

 

Windows程序生死

  1. CreateWindow 发送WM_CREATE给窗口函数,做初始化操作。
  2. 如果消息循环收到WM_QUIT, 结束消息循环
  3. DispatchMessage 分派消息给窗口
  4. 不断执行2,3
  5. 当系统发送WM_CLOSE,通常程序窗口不拦截此消息,于是DefWindProc处理它。
  6. DefWindProc 收到WM_CLOSE后,调用DestoryWindow清除窗口,并发送WM_DESTROY.
  7. WM_DESTROY的处理是调用PostQuitMessage
  8. PostQuitMessage 没做什么只是发送WM_QUIT消息,结束循环。

MessageMap

MSGMAP_ENTRY
struct MSGMAP_ENTRY {

         UINT message;

         LONG (*pfn) (HWND, UINT, WPARAM, LPARAM);

}

# define dim(x) (sizeof(x) / sizeof(x[0]))

  1. _messageEntries[] , _commandEntries[]

struct MESASGE_ENTRY _messageEntries [] =

{

         WM_CREATE,  OnCreate,

         WM_PAINT,    OnPaint,

         WM_SIZE, OnSize,

         WM_COMMAND, OnCommand,

         WM_SETFOCUS, OnSetFocus,

         WM_CLOSE,   OnClose,

         WM_DESTROY,  OnDestroy

};

struct MESSAGE_ENTRY _commandEntries[] =

{

         IDM_ABOUT, OnAbout,

         IDM_FILEOPEN, OnFileOpen,

         ....

};

  1. 窗口函数处理

LRESULT CALLBACK WndProc(HWND hWnd, UINT mesage, WPARAM wParam, LPARAM lParam)

{

         int i;

         for(i=0; i<dim(_messageEntries); ++i)

         {

                   if (mesage == _messageEntries[i].nMessage)

                            return ((*_messageEntries[i].pfn)(hWnd,message,wParam,lParam));

         }

         return (DefWindowProc(hWnd,message,wParam,lParam);

}

 

LRESULT OnCommand(HWND hWnd, UINT mesage, WPARAM wParam, LPARAM lParam)

{

         int i;

         for(i=0; i<dim(_commandEntries); ++i)

         {

                   if (mesage == _commandEntries [i].nMessage)

                            return ((*_commandEntries [i].pfn)(hWnd,message,wParam,lParam));

         }

         return (DefWindowProc(hWnd,message,wParam,lParam);

}

Idle 处理

GetMessage, PeekMessage都从消息队列取消息。 如果抓不到消息,GetMessage 什么不做,于是操作系统再去关照其他人。PeekMessage 取回控制权执行一段时间

while(1)

{

         if (PeekMessage(&msg, NULL, 0, 0))

         {

                   TranslateMessage(&msg);

                   DispatchMessage(&msg);

         }

         else

         {

                   OnIdle();

         }

}

MFC 6 仿真技术

MFC Class hierachy

 

MFC 初始化过程

MFC 的 CWinApp 包含两个虚函数 InitApplication, InitInstance

MAIN:

InitApplication();

InitInstance();

Run();

RRTI 运行时类别

MFC 以链表的形式记录型别信息

struct CRuntimeClass

{

         LPCTSTR m_lpszClassName;

         int m_nObjectSize;

         UNIT m_wSchema;

         CObject* (PASCAL* m_pfnCreateObject)();

         CRuntimeClass* m_pBaseClass;

         static CRuntimeClass * pFirstClass;

         CRuntimeClass * pNextClass;

}

 

 

动态创建 Dynamic Creation

#define _RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))

#define _DECLARE_DYNAMIC(class_name) \

protected: \

    static CRuntimeClass* PASCAL _GetBaseClass(); \

public: \

    static CRuntimeClass class##class_name; \

    static CRuntimeClass* PASCAL GetThisClass(); \

    virtual CRuntimeClass* GetRuntimeClass() const; \

 

#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \

    CRuntimeClass* PASCAL class_name::_GetBaseClass() \

       { return RUNTIME_CLASS(base_class_name); } \

    AFX_COMDAT CRuntimeClass class_name::class##class_name = { \

       #class_name, sizeof(class class_name), wSchema, pfnNew, \

           &class_name::_GetBaseClass, NULL, class_init }; \

    CRuntimeClass* PASCAL class_name::GetThisClass() \

       { return _RUNTIME_CLASS(class_name); } \

    CRuntimeClass* class_name::GetRuntimeClass() const \

       { return _RUNTIME_CLASS(class_name); }

 

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \

    IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL)

 

#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \

    CObject* PASCAL class_name::CreateObject() \

       { return new class_name; } \

    IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \

       class_name::CreateObject, NULL)

 

永久保存

#define DECLARE_SERIAL(class_name) \

    _DECLARE_DYNCREATE(class_name) \

    AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

 

#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \

    CObject* PASCAL class_name::CreateObject() \

       { return new class_name; } \

    extern AFX_CLASSINIT _init_##class_name; \

    _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \

       class_name::CreateObject, &_init_##class_name) \

    AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); \

    CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \

       { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \

           return ar; }

消息传递

 

 

消息流向

1, 一般的WINDOWS WM_XXX消息, 派生类流向基类

2, WM_COMMAND

l  FRAME:   VIEW -> FRAME本身->CWinApp

l  View: View->Document

l  Document->Document template

 

发表评论

0/200
439 点赞
0 评论
收藏