Ui

MFC

程序启动流程

  • 系统shell加载程序的codedatadll并调用CreateProcess()创建了一个代表你程序的进程
  • 启动第一个线程(PCB,TCB等的创建)

MFC程序启动流程

  • _tWinMain –> AfxWinMain (WINMAIN.CPP 21)
  • AfxWinMain()负责调用CWinApp中的InitApplication(),InitInstance(),Run()等几个主要函数.

WinMain

int WINAPI WinMain(HINSTANCE hInstance/*当前进程句柄*/, HINSTANCE hPrevInstance/*win32:NULL*/, LPSTR cmd/*argv*/, int show/*maxmize...*/) {
	WNDCLASS wc = {0};
	wc.lpszClassName = "ZClass";
	wc.lpfnWndProc = (WNDPROC)ZWindowProc;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.style = CS_VERDRAW | CS_HREDRAW | CS_NOCLOSE/*禁止标题栏关闭*/;
	if (!RegisterClass(&wc)) { return 0; }

	// CreateWindow会产生WM_CREATE消息,这是窗口过程收到的第1个消息.
	HWND hWndMain = CreateWindow("ZClass", "caption", WS_OVERLAPPEDWINDOW, 0,0,8,8, NULL,NULL, hInstance, NULL);
	ShowWindow(hWndMain, SW_SHOW);
	// emit WM_PAINT, 这是窗口过程的第2个消息!
	UpdateWindow(hWndMain);

	/* 消息循环 */
	MSG msg;
	while (GetMessage(&msg, NULL, 0,0)) { // NULL:获取所有窗口消息;2个0:不过滤
		// 将WM_KEYDOWN翻译成WM_CHAR.
		TranslateMessage(&msg);
		// 将消息转发(OS)到窗口过程!
		DispatchMessage(&msg);
	}

	return 0;
}

Message Map

  • CObject实现了运行时类型识别功能: CObject::IsKindOf()
  • CCmdTarget实现了消息映射
  • CWinThread没有保存消息映射表,故不适用其父类:BEGIN_MESSAGE_MAP(CWinApp, CCmdTarget)
  • declare_message_map这些宏主要是为了使当前消息映射节点加入到消息映射的链表中去.
  • AFX_MSGMAP的类都保存了一张表,记录了"消息-处理函数"之间的对应关系

消息的种类

  • 命令消息: WM_COMAMDN,CCmdTarget; UI对象、菜单、工具栏、按钮
  • 控件消息: WM_NOTIFY,也属于命令消息的一种,是控件发送给父窗口的"通知消息";
  • 标准消息: WM_PAINT,WM_CREATE,WM_CHAR,WM_LBUTTONDOWN..除了上面两种之外的消息. CWnd不需要我们指定函数名!

AFX_MSGMAP

enum AfxSig {  // 消息映射响应函数参数及返回值的类型
	AfxSig_end = 0, // [marks end of message map]
	AfxSig_bD,      // BOOL (CDC*)
	AfxSig_bb,      // BOOL (BOOL)...
};
typedef void (CCmdTarget::*AFX_PMSG)(void);  // CCmdTarget类的void-void成员函数指针类型
struct AFX_MSGMAP_ENTRY {  // 记录(控件上的)消息所对应的"消息处理函数"----消息映射的节点
	UINT nMessage;  // WM_CREATE、WM_COMMAND、WM_MOVE、WM_SIZE、WM_PAINT...
	UINT nCode;     // 控件消息的控制码,如: BN_CLICKED、
	UINT nID;       // 控件ID:IDC_BUTTON1.., 0:标准消息
	UINT nLastID;   // 指定一定范围内的消息被映射,或两者一样
	UINT nSig;      // pfn函数类型.见上方AfxSig的定义
	AFX_PMSG pfn;   // 是一个指向CCmdTarget类非静态成员函数指针
};
struct AFX_MSGMAP { // 消息映射链表,便于从年轻的消息映射节点走访到最老的消息映射节点.
	const AFX_MSGMAP* pBaseMap;  // 记录基类的(baseClass)messageMap成员以便向上走访,基类消息映射表使子类可以走访到基类,类似于虚函数
	const AFX_MSGMAP_ENTRY* lpEntries;  // _messageEntries[]成员的地址
};

DECLARE_MESSAGE_MAP

下面都定义了_AFXDLL版本(动态连接到MFC-dll)

更多

Dart 3

Migration Guide

新特性

var (String name, _) = userInfo({});
const record = (a: 1, b: true);
print('${record.a} ${record.b}');

更多