AfxBeginthread();
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
只有在使用MFC框架时才有UI线程和工作线程之分。
UI线程与工作线程的区别是操作系统为UI线程创建并维护了一个消息队列。
UI线程,能够响应操作系统的特定消息(包括界面消息,鼠标键盘消息,自定义消息等),是在普通的工作线程的基础上加上消息循环来实现的。
工作线程原本没有消息队列,可强制加一个,一般线程中出现GDI的调用就会出现一个消息队列;
UI线程处理消息
UI线程启动一个消息循环(Message Loop),每次从本线程所对应的消息队列中取出一条消息,然后根据消息所包容的信息,将其转发给特定的窗体对象,此窗体对象所对应的“窗体过程”函数被调用以处理这些消息。
MSG msg; // 代表一条消息
BOOL bRet;
// 从UI线程消息队列中取出一条消息
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// 错误处理代码,通常是直接退出程序
}
else
{
TranslateMessage(&msg); // 转换消息格式
DispatchMessage(&msg); // 分发消息给相应的窗体
}
}
GetMessage()等到消息才返回,peekmessage()则马上返回消息或者空值;
GetMessage()获得消息后从队列中删除(WM_PAINT除外);
peekMessage()根据参数PM_NOREMOVE或者PM_REMOVE来决定要不要删除;
TranslateMessage()函数主要用于将WM_KEYDOWN和WM_KEYUP消息转换WM_CHAR消息。如果想要截获WM_KEYDOWN和WM_KEYUP消息,需要重载窗体类的PreTranslateMessage()函数进行分析。
DispatchMessage()函数根据取出的消息中所包含的窗体句柄,将这一消息转发给引此句柄所对应的窗体对象。负责响应消息的函数称为窗体过程(Window Procedure)。如果需要自定义处理,则重载窗体类的DefWindowProc()函数。窗体过程是一个函数,每个窗体一个,形式如下:
LRESULT CALLBACK MainWndProc(……)
{
//……
switch (uMsg) // 依据消息标识符进行分类处理
{
case WM_CREATE:
// 初始化窗体.
return 0;
case WM_PAINT:
// 绘制窗体
return 0;
//
// 处理其他消息
//
default:
// 转去调用系统默认的消息处理函数
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//……
}