有一个单文档的程序,响应一个菜单消息,用afxbeginthread创建了一个用户界面线程(这个线程是基于cwinthread的,在initlinstance()里面创建了一个对话框并显示出来),在这个对话框中响应一个按钮消息,进入一个while死循环,这个时候按照常理,单文档是主线程,对话框是一个后来创建的子线程,子线程进入死循环被阻塞,主线程没有进入任何函数是不应该被阻塞的,可以响应鼠标消息,但是实际情况是单文档不能响应鼠标消息,比如移动窗口,最大化等,也就是主线程也被阻塞了。 谁来解释一下这是怎么回事啊?如果是这样,多线程的意义何在?
解决方案 »
- readfile读取串口数据的问题
- BHO中挂接了网页按钮的onClick以后,怎么让网页的JS再执行它原来的函数?
- 怎么屏蔽对话框工程中,按回车键就关闭对话框这个功能啊,就是按回车键 ,不要关闭对话框!谢谢
- 如何根据需要按行显示一个文本文件,并根据需要可以使某些行的颜色(字体或背景)改变?
- 如此简单,为什么就是不对呢?
- 多个EDIT控件,怎么将它们的背景设为不同颜色?
- 请教:用LoadImage()载入的光标资源,当光标尺寸大于32*32时,显示不正常?
- 关于ListCtrl的图标显示问题?
- select函数是干什么的?详细一些,最好有代码!!!
- 求解关于局域网上传输语音的两个难题!
- 关于netdb.h头文件问题?
- 调查,用VC做管理系统多不多,俺正准备这样做.又有点担心工程周期
在消息循环中有个:DispatchMessage函数,将消息发送给系统,并由系统去调用窗口过程中的消息处理函数。那么它的程序流是:DispatchMessage函数将控制权交给系统,系统调用消息处理函数(即系统又将控制权交给消息处理函数,等消息处理函数处理完成后,它又将控制权交还给系统,系统又交还给DispatchMessage函数,并进入下一次消息循环。
对话框的按钮消息处理函数一直死循环,那么控制权一直都在消息处理函数中,系统处于等待控制权返回状态。而当主线程的消息循环的DispatchMessage函数将控制权交给系统时,因系统处于等到上次控制权返回的状态,它是无法再次获取新的控制权的,所以主线程的消息也得不到处理。
#include <process.h>
UINT WINAPI ThreadProc(LPVOID lpParam);
void CSDISampleApp::OnTest()
{
// TODO: Add your command handler code here
::CloseHandle((HANDLE)::_beginthreadex(NULL, 0, ThreadProc, this, 0, NULL));
}// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);UINT WINAPI ThreadProc(LPVOID lpParam)
{
// TODO: Place code here.
MSG msg; // Initialize global strings
HINSTANCE hInstance = ::GetModuleHandle(NULL);
MyRegisterClass(hInstance);
InitInstance(hInstance, SW_SHOW); // Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} return (int) msg.wParam;
}//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME);
wcex.lpszClassName = _T("Test Class");
wcex.hIconSm = NULL; return RegisterClassEx(&wcex);
}//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd; hWnd = CreateWindow(_T("Test Class"), _T("TEST"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd)
{
return FALSE;
} ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd); return TRUE;
}//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc; switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case ID_FILE_NEW:
while (TRUE);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE; case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}