Progressbar 范围和位置,如何在 C++ 中处理大数字? [英] Progressbar Range and position, how to handle big numbers in C++?

查看:22
本文介绍了Progressbar 范围和位置,如何在 C++ 中处理大数字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图实现 windows Progressbar 以大数字字节显示下载进度,但我无法正确执行.

Trying to implement windows Progressbar showing progress of download in bytes with big numbers, but am unable to do it correctly.

对于 2.5gb 的下载,如果我执行以下操作,下载完成后它会低于完整范围.

For a download of 2.5gb if I do following, it ends short of the full range when download is complete.

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

然后在每个下载回调处设置新位置:

and then set new position at each download callback as :

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

这是一个非常笨拙的实现,我不想陷入 xy 情况,所以我的问题是实现具有 2-5GB 字节大小的大数字的进度条的正确方法是什么?

This is a very noobish implementation, and I don't want fall in the xy situation, So my question is what is the correct way to implement a progressbar with big numbers in tune of 2-5GBs in bytes ?

我尝试了@msandiford 和@NikBougalis 在下面建议的两种方法,通过考虑进度条的宽度并使用百分比而不是实际数字,我什至将两者结合起来,但在所有情况下,newIncrement 始终为 0,也许那是因为 dlSize 总是较低(在 double newIncrement 中出现类似 1.15743e+007 的东西,输入它和它的 0 ).

I tried both approaches suggested below by @msandiford and @NikBougalis, by taking the width of the progressbar in account and by using percentage instead of actual number, I even combined both, but in all cases the newIncrement always comes out 0, maybe that's because dlSize is always lower( in double newIncrement comes out something like 1.15743e+007, type cast it and its 0 ).

我还能做什么?

结合两种方法的新代码:

New Code combining both approaches:

编辑 2:对代码添加了一些检查,因为我不断为 newIncrement 获取 0,看起来它现在工作正常,不确定如何:

EDIT 2: Added few checks to the code as I was constantly getting 0 for newIncrement, looks like its working now, not sure how well:

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;
}

编辑 3:看起来它仍然很早就完成了.

EDIT 3 : Looks like its still finishing early.

推荐答案

让进度条比进度条窗口本身的像素数更准确可能没有多大意义.基于此,您应该能够轻松地将目标缩放到像素数.

There probably isn't much point making the progress bar more accurate than the number of pixels in progress bar window itself. Based on this, you should be able to scale the target to the number of pixels pretty easily.

    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));

然后更新进度将类似于:

Then updating progress would be something like:

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

如果进度窗口可以调整大小,您需要重新计算 pbRange、重置进度条范围并重新计算 unitsPerPixel 以响应 WM_SIZE消息.

If the progress window was somehow resizeable, you would need to recalculate pbRange, reset the progress bar range and recalculate unitsPerPixel in response to a WM_SIZE message.

这篇关于Progressbar 范围和位置,如何在 C++ 中处理大数字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆