MFC
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程序生死
- CreateWindow 发送WM_CREATE给窗口函数,做初始化操作。
- 如果消息循环收到WM_QUIT, 结束消息循环
- DispatchMessage 分派消息给窗口
- 不断执行2,3
- 当系统发送WM_CLOSE,通常程序窗口不拦截此消息,于是DefWindProc处理它。
- DefWindProc 收到WM_CLOSE后,调用DestoryWindow清除窗口,并发送WM_DESTROY.
- WM_DESTROY的处理是调用PostQuitMessage
- 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]))
- _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,
....
};
- 窗口函数处理
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