如何使用PBS_MARQUEE样式制作ProgressBar

How to make ProgressBar with PBS_MARQUEE style work?

本文关键字:ProgressBar 样式 MARQUEE 何使用 PBS      更新时间:2023-10-16

我知道如何使用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来完成。即使在这种情况下