如何使用PBS_MARQUEE样式制作ProgressBar
How to make ProgressBar with PBS_MARQUEE style work?
我知道如何使用pbs_marquee样式创建一个工作进度键,但是在我想要omquee动画的情况下,只要long_operation()
运行,我就在实现它时遇到了麻烦SendMessage(hPB, PBM_STEPIT, 0, 0);
从long_operation()
连续推进动画。
这是我失败的尝试之一:
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更新消息未发送到/接收到/接收到/接收。
我觉得必须有一种直观的方法来做到这一点,但我无法弄清楚。
该怎么办?
如果您想与一个线程保持一致,则需要定期泵送消息,因此如果发现窗口可以移动或刷新。
// Process all queued messages. Handle keyboard dialog nawigation
// for dialog_hwnd. For more then one modeless dialog modify code by
// calling IsDialogMessage for each dialog.
void PumpMesages( HWND dialog_hwnd ) {
MSG msg;
while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) != 0 ) {
// Handling modeless dialog nawigation.
if ( dialog_hwnd && IsDialogMessage( dialog_hwnd ) )
continue;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
void long_operation( HWND dialog_hwnd, HWND progress_hwnd ) {
for(int i = 0; i < 9; ++i) {
for(int j = 0; j < 99999999; ++j)
;
// I'm not shure if this is needed.
// I have always used propper progress bar (PBM_SETPOS).
SendMessage(progress_hwnd, PBM_STEPIT, 0, 0);
// Periodically process messages.
PumpMessages( dialog_hwnd );
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==0)
return;
ShowWindow(hDlg, SW_SHOW);
// Disable input processing in main window if there is possibility
// of recursion. For example, user select Open file, we begin
// loading and inside PumpMessages, user can again select Open
// file so we will end with two progress dialogs and nested
// message loops.
EnableWindow(Dll_globals::g_hWndMain,FALSE);
long_operation( hDlg, GetDlgItem( hDlg, progress_bar_id_here ) );
// Remember to enable input processing in main window.
EnableWindow(Dll_globals::g_hWndMain,TRUE);
}
可以通过添加中止按钮,处理progressdlgproc,设置一些标志(dll_globals :: g_abort?)并尽早离开long_operation来增强此功能。
进行多线程,您必须建立启动工作的协议(这取决于您选择的API)和信号完成(这可以通过使用自定义消息的后邮政以及具有足够的控制ID的WM_COMMAND来完成。即使在这种情况下