以下内容有大部分转载自CSDN,经过自己整理完成。
该文主要的方法为在非模态对话框中自定义一组消息函数,然后在主窗口中开辟一个线程通过线程把消息传递给子窗口进行更新。
在子窗口类中定义消息如下:
/*************************************************子窗口*******************************************************************************/
消息函数定义
afx_msg LRESULT Customize(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
消息函数映射
BEGIN_MESSAGE_MAP(CDiaglogATest, CDialogEx) ON_MESSAGE(WM_CUSTOMIZE, Customize) //自定义消息映射 ON_BN_CLICKED(IDOK, &CDiaglogATest::OnBnClickedOk) END_MESSAGE_MAP()
消息函数实现
LRESULT CDiaglogATest::Customize(WPARAM wParam, LPARAM lParam) { CString strTittle; if (wParam < 0) wParam = 0; else if (wParam >= 100) { wParam = 100; m_Progress1.ShowWindow(FALSE); UpdateWindow(); } strTittle.Format(_T("自定义消息参数:x=%d,y=%d"), wParam, lParam); m_Progress1.SetPos(wParam); SetWindowText(strTittle); UpdateData(TRUE); return 0; }
在初始化窗口函数中初始进度条
BOOL CDiaglogATest::OnInitDialog() { CDialogEx::OnInitDialog(); m_Progress1.SetRange(0, 100); m_Progress1.SetStep(1); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE }
/*******************************************************父窗口主要是开线程,传消息**********************************************/
//以下线程代码主要实现传递按钮位置参数和,完成后的子窗口销毁消息
struct myThreadParamExanple { bool bRunningFlag; // 线程运行标志变量 HWND hwnd; // 线程关联的对话框窗口的句柄 char sFn[_MAX_PATH]; // 文件名 }; // // 线程处理函数 UINT MyThreadExample(LPVOID *pParam) { FILE *fp = fopen(((struct myThreadParamExanple*)pParam)->sFn, "wt"); unsigned long iMaxCOunt = 1000, g_nCount; int iPercent; CString msg; for (g_nCount = 0; ((struct myThreadParamExanple*)pParam)->bRunningFlag && g_nCount <= iMaxCOunt; ::InterlockedIncrement((long*)&g_nCount)) { fprintf(fp, "g_nCount=%d\n", g_nCount); Sleep(10); iPercent = g_nCount * 100 / iMaxCOunt; ::PostMessage((HWND)((struct myThreadParamExanple*)pParam)->hwnd, WM_CUSTOMIZE, iPercent, 100);//iPercent传递位置参数 } if (!((struct myThreadParamExanple*)pParam)->bRunningFlag) fprintf(fp, "\n线程被人为终止\n"); else fprintf(fp, "\n线程自然结束\n"); fclose(fp); ((struct myThreadParamExanple*)pParam)->bRunningFlag = false; ::PostMessage((HWND)((struct myThreadParamExanple*)pParam)->hwnd, WM_DESTROY, 0, 0);//销毁子窗口 return 0; }
//以下代码主要实现了子窗口的显示和线程的创建
CString CMFCApplication2Dlg::GetCurrentPath() { TCHAR szFullPath[MAX_PATH]; GetModuleFileName(NULL, szFullPath, MAX_PATH); CString sFn = szFullPath; int ret = sFn.ReverseFind(_T('\\')); sFn = sFn.Left(ret) + _T("\\"); return sFn; } void CMFCApplication2Dlg::OnBnClickedMfcbutton1() { /* // TODO: 在此添加控件通知处理程序代码 CDiaglogATest* pDlgATest = new CDiaglogATest; pDlgATest->Create(IDD_DLOG_ATEST, NULL); pDlgATest->ShowWindow(SW_SHOW); //pDlgATest->UpdateWindow(); // 线程运行参数 // TODO: Add your command handler code here */ CString sFn = GetCurrentPath() + _T("1.txt"); // 线程参数定义和初始化 static struct myThreadParamExanple myParam = { false, NULL, ""}; memcpy(myParam.sFn, sFn, sFn.GetLength()); //strcpy(myParam.sFn, sFn); struct myThreadParamExanple *pParam = &myParam; if (myParam.bRunningFlag) { MessageBox(_T("本操作上次运行尚未结束,您不能再次运行!"), _T("提示"), MB_ICONINFORMATION); return; } else { // 无模式对话框创建 CDiaglogATest* pDlgATest = new CDiaglogATest(pParam->bRunningFlag, _T("进度111")); pDlgATest->Create(IDD_DLOG_ATEST, NULL); pDlgATest->ShowWindow(SW_SHOW); // 线程运行参数 pParam->bRunningFlag = true; // 设置进程运行标志 pParam->hwnd = pDlgATest->GetSafeHwnd(); // 获取无模式对话框的句柄 // 开线程 pMyThread = AfxBeginThread((AFX_THREADPROC)MyThreadExample, pParam, THREAD_PRIORITY_NORMAL); } }
该方法也能完美的实现非模态对话框更新进程控件的方法。!!!!
经过一天的折磨才总结了这些方法,欸,道路还好长啊。