【发布时间】:2017-09-28 07:46:52
【问题描述】:
我知道如何使用 PBS_MARQUEE 样式创建一个有效的 ProgressBar,但是在我想要选取框动画的情况下,我无法实现它,只要一些 long_operation() 运行,而不必从 @ 连续调用 SendMessage(hPB, PBM_STEPIT, 0, 0); 987654323@推进动画。
这是我失败的尝试之一:
INT_PTR CALLBACK ProgressDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_INITDIALOG:
{
HWND hProgressBar = GetDlgItem(hWnd, IDC_PROGRESS1);
LONG_PTR style_flags = GetWindowLongPtr(hProgressBar, GWL_STYLE);
SetWindowLongPtr(hProgressBar, GWL_STYLE, style_flags | PBS_MARQUEE);
SendMessage(hProgressBar, (UINT)PBM_SETMARQUEE, (WPARAM)1, (LPARAM)NULL);
break;
}
}
return FALSE;
}
void long_operation() {
for(int i = 0; i < 9; ++i) {
for(int j = 0; j < 99999999; ++j)
;
Beep(5000, 100);
}
}
void do_operation() {
HWND hDlg = CreateDialog(Dll_globals::g_hInst,
MAKEINTRESOURCE(IDD_DIALOG4), // assume this contains a ProgressBar ctl
Dll_globals::g_hWndMain, ProgressDlgProc);
if(hDlg) {
ShowWindow(hDlg, SW_SHOW);
UpdateWindow(hDlg);
}
long_operation();
}
我用上面的代码得到的是一个选取框进度条,在哔声继续时没有任何动画,然后在它停止时是一个正常的动画选取框。
据我了解,由于long_operation() 阻塞了线程,消息队列也被阻塞了,默认的30ms 更新消息不会被ProgressBar 控件发送/接收。
我觉得一定有一种直观的方法可以做到这一点,但我想不通。
这是怎么回事?
【问题讨论】:
-
不太确定 std::thread 是否曾被指责为直观。但这就是让你的 UI 线程能够更新栏所需要的。沙漏光标而不是进度条非常直观。
-
将
long_operation卸载到工作线程上。这可以通过多种方式完成,例如通过使用std::thread、std::async或 Windows 的本机线程实现 (CreateThread/_beginthreadex)。请特别注意,从long_operation调用SendMessage仅实现部分解决方案。例如,当用户尝试与之交互时,它仍会阻止发送其他消息,从而导致对话框显示为挂起。 -
发生的情况是您正在 UI 线程中工作,这导致 UI 无响应。通过在后台线程中完成工作来解决该问题。
-
您可以直接触发并忘记线程,然后立即将控制权交还给对话管理器以发送消息。线程完成后,它可以将自定义消息 (
WM_APP + x) 发布到对话窗口,或发送它,以防它需要传回数据。 -
@Asesh:这仅适用于更改某些样式(如边框)。此处不适用。
标签: c++ winapi controls progress-bar