簡體   English   中英

在Windows C ++中更新進度欄

[英]Updating progress bar in windows C++

我用C ++創建了一個簡單的Windows控制台程序,該程序進行一些處理,並創建一個帶有進度條的窗口,該進度條會隨着處理的進行而更新。 問題在於進度條不會更新。

下面是我的示例應用程序的代碼。

#include <iostream>
#include <stdlib.h>
#include "atlstr.h"
#include "pch.h"
#include <string.h>
#include "tchar.h"
#include <vector>
#define ISOLATION_AWARE_ENABLED 1
#include <windows.h>
#include <commctrl.h>

using namespace std;

#define WM_UPDATEPROGRESS WM_USER + 1

typedef struct {
    HWND    window;
    HWND    hwndPB;
} OPERATION_INFO;

void DoOperation(LPVOID lpThreadParams) {
    //reading ThreadParams
    OPERATION_INFO *pOperationInfo = (OPERATION_INFO *)lpThreadParams;
    //run a test loop that updates bar
    for (int i = 1; i <= 10; i += 1) {
        // do something
        Sleep(500); // dummily waiting some time
        // send message to update progress bar
        PostMessage(
            pOperationInfo->window, WM_UPDATEPROGRESS, 0, NULL);
    }
}

LONG_PTR CALLBACK WindowProcedure(
    HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
    RECT rcClient;
    HWND hwndPB = NULL;
    OPERATION_INFO operationInfo;
    static bool flag_activate = FALSE;

    switch (msg)
    {
    case WM_CREATE:

        // create progress bar
        GetClientRect(window, &rcClient);
        hwndPB = CreateWindowEx(0, PROGRESS_CLASS,
            (LPCWSTR)NULL, (WS_CHILD | WS_VISIBLE),
            20,
            20,
            rcClient.right - rcClient.left - 40,
            20,
            window, (HMENU)0, GetModuleHandle(0), NULL);

        // progress bar settings
        SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
        SendMessage(hwndPB, PBM_SETPOS, (WPARAM)0, 0);
        SendMessage(hwndPB, PBM_SETSTEP, (WPARAM)10, 0);

    case WM_ACTIVATEAPP:
        // if message already fired then do nothing:
        // because in this message we have code to initialize thread 
        // that updates progress bar and the thread initialization, 
        // obviously, must be done once.
        if (flag_activate)
            break;
        else
        {
            // store message MW_ACTIVEAPP fired
            flag_activate = TRUE;

            // initialize thread
            OPERATION_INFO operationInfo = { window, hwndPB };
            HANDLE threadHandle;
            // make thread call DoOperation routine
            threadHandle = CreateThread(
                NULL, 0, 
                (LPTHREAD_START_ROUTINE)DoOperation, 
                (LPVOID)&operationInfo, 0, 0);
        }
        break;

    case WM_UPDATEPROGRESS:
        //get info with HWND of the progress bar to update
        //update the progress bar
        SendMessage(hwndPB, PBM_STEPIT, NULL, 0);
        //release memory
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0L;

    case WM_LBUTTONDOWN:
        break;

    default:
        return DefWindowProc(window, msg, wp, lp);
    }
}

int main()
{
    // Window creation

    // structure initialization
    LPCWSTR myclass = L"myclass";
    WNDCLASSEX wndclass = { 
        sizeof(WNDCLASSEX), CS_DBLCLKS, 
        WindowProcedure, 0, 0, GetModuleHandle(0), 
        LoadIcon(0,IDI_APPLICATION), LoadCursor(0,IDC_ARROW), 
        HBRUSH(COLOR_WINDOW + 1), 0, myclass, 
        LoadIcon(0,IDI_APPLICATION) };
    // preliminar action
    if (RegisterClassEx(&wndclass))
    {
        // create window
        HWND window = CreateWindowEx(0, myclass, L"Processing",
            WS_OVERLAPPED | WS_SYSMENU,
            CW_USEDEFAULT, CW_USEDEFAULT,
            300, 150,
            0, 0, GetModuleHandle(0), 0);
        // if OK
        if (window)
        {
            // show window
            ShowWindow(window, SW_SHOWDEFAULT);
            MSG msg;
            while (GetMessage(&msg, 0, 0, 0)) 
                DispatchMessage(&msg);
        }
    }
}

我希望進度條每秒更新一次,但這不會發生:進度條什么也不做。

怎么了?

您的代碼有兩個類似的問題:

  1. 在WM_ACTIVATEAPP處理程序中,您正在將CreateThread(...)的lpParameter參數(要傳遞給線程的變量)分配給指向堆棧上定義的本地結構的指針。 一旦調用的else子句結束,則struct超出范圍,並且指針無效。

  2. 在WM_UPDATEPROGRESS處理程序中,您將SendMessage-inging到一個未定義的變量的窗口句柄。 該變量僅在WM_CREATE處理程序中定義。

在真實的代碼中,您希望以更健壯的方式處理這些問題,但是為了使該代碼達到您期望的目的,請將兩個狀態變量設為靜態:

static HWND hwndPB = NULL;
static OPERATION_INFO operationInfo;

並修改WM_ACTIVATEAPP處理程序,以使其將指針傳遞給此靜態變量,而不是其自身的本地OPERATION_INFO。

基本上,您需要記住WNDPROC是適用於普通范圍規則的普通C函數。 它們不是任何種類的類定義。 如果要保持與某個窗口相關聯的狀態,這種狀態在調用其窗口過程時是很好的,則必須顯式維護這種狀態。

我遇到了同樣的問題,但是當我在Delphi工作時。 最可能的原因是處理需要花費大量時間,並且由於處理和鋼筋更新是在同一線程上進行的,因此在完成處理之后,鋼筋填滿了100%。

解決方案:嘗試在單獨的線程中更新進度條。 從主線程每秒調用一次update函數(或根據需要多次調用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM