背景:
有次在MFC消息里延迟实现一些功能,结果导致刷新失常。
下面的程序说明MFC编程的一些原则:
不能在消息和事件处理中进行sleep,那样别指望paint操作能做什么,程序也会陷入假死状态,直到事件处理结束,也许事件处理必须是无阻塞处理。
尽量通过postmessage而不要随便使用sendmessage,除非确认算法不耗时,并且无阻塞。
代码:
struct wParam_st
{
CVc6Dlg* pThis;
HANDLE hRead;
CString strInfo;
};
HANDLE hRead,hWrite;
wParam_st wParamThrd;// = {this,hRead};
void CVc6Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CPaintDC dc(this); // device context for painting
m_Edit1 = wParamThrd.strInfo;
UpdateData(FALSE);//窗口只有无效的时候才会重绘,不能调用WM_PAINT消息,因为WM_LBUTTONDOWN事件没有完成。
CDialog::OnPaint();
}
}
DWORD WINAPI ShowInfoProc(WPARAM wParam)
{
wParam_st* pwParam = (wParam_st*)wParam;
CVc6Dlg* pThis = pwParam->pThis;
HANDLE hRead = pwParam->hRead;
//char buffer[4096] = {0};
char buffer[32] = {0};
DWORD bytesRead;
while (true)
{
if (ReadFile(hRead,buffer,sizeof(buffer)-1,&bytesRead,NULL) == NULL)
break;
pwParam->strInfo += buffer;
PostMessage(pThis->m_hWnd,WM_PAINT,0,0);
Sleep(100);
}
return S_OK;
}
void CVc6Dlg::OnBnClickedButton1()
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead,&hWrite,&sa,0))
{
AfxMessageBox("Error On CreatePipe()");
return;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite;
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (!CreateProcess(NULL,"c:\\windows\\system32\\cmd.exe /c dir /?",NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) {
AfxMessageBox("Error on CreateProcess()");
return;
}
CloseHandle(hWrite);
m_Edit1 = "NULL";
wParamThrd.pThis = this;
wParamThrd.hRead = hRead;
wParamThrd.strInfo ="";
HANDLE hGetCmdThrd = ::CreateThread(0,0,(LPTHREAD_START_ROUTINE)ShowInfoProc,&wParamThrd,0,0);
//int i=0;
//while (i++ < 50)
//{
// if(m_Edit1.Compare(wParamThrd.strInfo)==0) break;
// //UpdateData();//异常,数据交换错误
// m_Edit1 = wParamThrd.strInfo;
// UpdateData(FALSE);//窗口只有无效的时候才会重绘,不能调用WM_PAINT消息,因为WM_LBUTTONDOWN事件没有完成。
//
// CPaintDC dc(this); // device context for painting
// CDC *pDC = &dc;
// CRect cClientRect;
// GetClientRect( cClientRect );
// //DrawText(pDC->m_hDC,m_Edit1, m_Edit1.GetLength(), &cClientRect,DT_CENTER);
// //CDialog::OnPaint();
// //InvalidateRect(NULL);
// //PostMessage(WM_PAINT,0,0);
// Sleep(200);
//}
//WaitForSingleObject(hGetCmdThrd,50000);
//CloseHandle(hRead);
//CDialog::OnPaint();
}