2

ダウンロードの進行状況を大きな数字でバイト単位で表示する Windows プログレスバーを実装しようとしていますが、正しく実行できません。

2.5GB のダウンロードの場合、次のようにすると、ダウンロードが完了すると全範囲を下回って終了します。

double dlSize = getDlSize();
unsigned int pbRange = (unsigned int)( dlSize / 3000 );
SendMessage( hProgressbar, PBM_SETRANGE, 0, MAKELPARAM( 0, pbRange ) );

次に、各ダウンロード コールバックで新しい位置を次のように設定します。

double dlBytes = bytesDownloaded();
unsigned int newIncrement = (unsigned int)( dlBytes / 3000 );
SendMessage( hProgressbar, PBM_DELTAPOS, (WPARAM)newIncrement, 0 );

これは非常に初心者の実装であり、xy の状況に陥りたくないので、私の質問は、バイト単位で 2 ~ 5 GB の大きな数字を持つプログレスバーを実装する正しい方法は何ですか?


プログレスバーの幅を考慮し、実際の数値の代わりにパーセンテージを使用して、@msandiford と @NikBougalis によって以下に提案された両方のアプローチを試しました。両方を組み合わせましたが、すべての場合で newIncrement は常に 0 になります。 dlSize は常に低くなります (2 倍の newIncrement では 1.15743e+007 のように出力され、型キャストとその 0 が返されます)。

他に何ができますか?

両方のアプローチを組み合わせた新しいコード:

編集 2: newIncrement に対して常に 0 を取得していたため、コードにいくつかのチェックを追加しました。現在は機能しているように見えます。

GetClientRect(hProgressbar, &pbRCClient);
pbWidth = pbRCClient.right - pbRCClient.left; // (pbWidth  its a global variable)
unsigned int pbRange = pbRCClient.right - pbRCClient.left;
SendMessage( hProgressbar, PBM_SETRANGE, 0, MAKELPARAM( 0, pbRange ) );

そして更新中:

double dlSize = getDlSize();
double doubleIncrement = ( ( dlSize * pbWidth ) / totalSize );

unsigned int newIncrement;

if ( (unsigned int)doubleIncrement < 1 )
{
    blockFill += doubleIncrement;

    if ( (unsigned int)blockFill > 1 )
    {
        newIncrement = ( unsigned int )blockFill;
        SendMessage( hProgressbar, PBM_DELTAPOS, (WPARAM)newIncrement, 0 );
        blockFill = 0;
    }
}
else
{
    newIncrement = ( unsigned int )( doubleIncrement );
    SendMessage( hProgressbar, PBM_DELTAPOS, (WPARAM)newIncrement, 0 );
    //blockFill = 0;
}

EDIT 3:まだ早く終わっているようです。

4

2 に答える 2

3

あなたが抱えている大きな問題は、進行状況バー コントロール自体の制限です。PBM_SETRANGE には制限があり、2GB を超える値を処理する必要がある場合はPBM_SETRANGE32を使用できますが、それでも問題が発生します。

偶然にも、なぜ double を使用するのでしょうか? 最大で約 16,384 ペタバイトに達する UINT64 を使用します (オーバーフローするものをダウンロードしている場合は... プログレス バーを飛ばしても、あなたとあなたの顧客を落胆させるだけです)。整数は、バイトなどのカウントに非常に適しています。

ダウンロードするファイルのフル サイズがわかっている場合、プログレス バーの最大範囲が制限されているサイズを回避する 1 つの方法は、プログレス バーを 0 から開始し、100 で終了することです。その後、変換できます。単純なルール 3を使用して、受信したバイト数をパーセンテージで表します。

percent = (bytes_received * 100) / max_bytes;

さらに「粒度」を上げたい場合は、進行状況バーのスケールを 1000 に変更し、それに応じて計算を調整できます。10000 にすることもできますが、その時点で、コントロールの幅 (または高さ) によっては、モニターの解像度にぶつかる可能性があります。

于 2012-12-22T07:19:36.187 に答える
2

プログレス バー ウィンドウ自体のピクセル数よりも正確なプログレス バーを作成しても、おそらくあまり意味がありません。これに基づいて、ターゲットをピクセル数に簡単にスケーリングできるはずです。

    RECT rcClient;
    GetClientRect(hProgressBar, &rcClient);
    unsigned int pbRange = rcClient.right - rcClient.left;

    // Need to either keep unitsPerPixel, or recalculate later
    double pixelsPerUnit = pbRange / dlSize;
    SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, pbRange));

次に、進行状況の更新は次のようになります。

    double dlBytes = totalBytesDownloaded();
    unsigned int newProgress = (unsigned int)(dlBytes * pixelsPerUnit);
    SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)newProgress, 0);

プログレス ウィンドウのサイズを何らかの方法で変更できる場合は、再計算しpbRange、プログレス バーの範囲をリセットしunitsPerPixelて、メッセージに応答して再計算する必要がありWM_SIZEます。

于 2012-12-22T07:15:58.730 に答える