MFC 界面假死问题解决方法

13 篇文章 1 订阅

在界面处理函数中,可以会长时间处理数据,导致界面假死,这时可以在代码块中加入下面代码:

有两种方法:
1. 单线程解决:
OnBtn1()
{
        while(m_bLoop)
       {
                your code....

              // 派发消息
               MSG	msg;
               if (PeekMessage(&msg,(HWND)NULL, 0, 0, PM_REMOVE))
               {
                        ::SendMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);  
                }
       }
}

OnBtn2()
{
       m_bLoop = FALSE;
}
2. 多线程 (参考:http://www.vckbase.com/document/viewdoc/?id=1704)
a. 在xxxDlg.h中类的外面(即大括号外面)定义一个函数 void ThreadFunc();(外部函数)
b. 在xxxDlg类中定义在类CMultiThread1Dlg内部添加protected型变量:
HANDLE hThread;	 DWORD ThreadID;
     分别代表线程的句柄和ID。 
c. 在xxxDlg.cpp中定义全局变量volatileBOOL m_Flag;
d.在xxxDlg.cpp中写ThreadFunc函数
    void ThreadFunc()
    {
           while(m_Flag)
           {
                    //your code here
            }
           return; //线程自杀
    }
e. 按钮A代表开始循环
void CxxxDlg::OnStart()
{
         hThread=CreateThread(
               NULL,
0,	 (LPTHREAD_START_ROUTINE)ThreadFunc,	 NULL,	 0,
&ThreadID
);
}
f. 按钮B代表结束循环
void CxxxDlg::OnStop() {	m_bRun=FALSE;}

void CConsoleTestDlg::OnButtonClose() 
{
	// TODO: Add your control notification handler code here
	CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_CLOSE);

	if (g_isOpen)
	{
		//ConWin.Close();

		HANDLE hProcessHandle;
		ULONG nProcessID;
		HWND TheWindow;
		
		TheWindow = ::FindWindow(NULL,"console");
		::GetWindowThreadProcessId(TheWindow,&nProcessID);
		hProcessHandle = ::OpenProcess(THREAD_TERMINATE,FALSE,nProcessID);
		::TerminateProcess(hProcessHandle,4);
		
		if(pBtn != NULL)
		{
			pBtn->SetWindowText("close");
		}

		g_isOpen = FALSE;
	}
	else
	{
		ConWin.Open();
		int i;

		while(1)
		{
			g_isOpen = TRUE;

			ConWin.printf("========test======%d\n",i++);
			
			// 派发消息
			MSG	msg;
			if (PeekMessage(&msg,(HWND)NULL, 0, 0, PM_REMOVE))
			{
				::SendMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);  
            }

			Sleep(100);
		}

		if(pBtn != NULL)
		{
			pBtn->SetWindowText("close");
		}
	}
}

从别人博客中看到还可以用下方法:

/* -------------------------------------------------------------------------      
Ok, call this to pump messages... 
------------------------------------------------------------------------- */
void CDoeventsDlg::DoEvents()
{
    MSG msg;
    if (::PeekMessage(&msg,NULL,0,0,PM_REMOVE)) 
	{
	//从Windows消息队列中取出消息 
		if (msg.message== WM_QUIT)//如果消息为退出,发送退出消息
        {
			::PostQuitMessage(-1);
        }
		
		if(!AfxGetApp()->PreTranslateMessage(&msg))//如果无法预处理消息
        {
			::TranslateMessage(&msg);//转换消息
			::DispatchMessage(&msg);//发送消息
        }
	}
	
	AfxGetApp()->OnIdle(0);
	AfxGetApp()->OnIdle(1);//消息队列为空时闲置一段时间
}


  • 15
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值