2012-12-22 2 views
2

Windows 구현 중 진행률이 높은 진행 표시 줄을 큰 숫자의 바이트로 표시하지만 올바르게 수행 할 수는 없습니다.Progressbar 범위와 위치, C++에서 큰 숫자를 처리하는 방법은 무엇입니까?

다음과 같이하면 2.5GB의 다운로드가 가능하며 다운로드가 완료되면 전체 범위를 벗어납니다.

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

이 매우 noobish 구현하고, 나는 XY 상황에서 가을을 원하지 않는, 그래서 내 질문은 무엇인가 : 다음

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

및 각 다운로드 콜백에서 새로운 위치를 설정 바이트 수 2-5GB의 큰 숫자로 진행률 막대를 구현하는 올바른 방법은 무엇입니까?


나는 시도 모두 계정에서 ProgressBar의 폭을 고려하여 대신 실제 수의 비율을 사용하여, 심지어 모두 결합 @msandiford 및 @NikBougalis 아래 제안 된 접근 방법,하지만 모든 경우에 newIncrement 항상 0이 나온다. 아마도 dlSize가 항상 낮기 때문이다. (double 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; 
} 

편집 3 : 그것은 아직 초기 마무리처럼 보인다.

+0

'PBM_DELTAPOS'보다는'PBM_SETPOS'를 사용하는 것이 훨씬 쉽습니다. 나는 또한 내 대답에 버그가있어서 잘못된 방향으로 인도하고 있을지도 모른다. ( – msandiford

+0

@msandiford PBM_SETPOS는 진행 막대 위치를 WPARAM을 통해 제공된 위치로 재설정한다 :) – StudentX

+0

그래, 맞아. 정확한 델타를 계산하는 것보다 진행 막대의 절대 위치를 계산하는 것이 훨씬 쉽습니다. 다운로드 한 총 데이터 양을 추적하면됩니다. – msandiford

답변

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

진행 창이 어떻게 든 크기를 조정할 수 있었다면, 당신은 WM_SIZE에 대한 응답으로, pbRange를 다시 계산 진행률 표시 줄 범위를 재설정하고 unitsPerPixel를 다시 계산해야 메시지.

+0

당신의 접근 방식을 시도했지만 differnet 종류의 문제가있는, 위의 새 코드를 업데이트했습니다. – StudentX

+0

Ooops. 내 잘못. 이 기술을 위해'PBM_DELTAPOS'보다는'PBM_SETPOS'를 사용해야합니다. 변경 사항을 반영하도록 업데이트되었습니다. – msandiford

+0

옙, 근무, 완벽, 시간과 도움을 많이 주셔서 감사합니다. Vaughn Cato가 언급 한 접근법과 오류 확산 기술을 결합한 것입니다. http://stackoverflow.com/questions/14014261/how-to-effectively-convert-double-to-int-in-c – StudentX

3

큰 문제는 진행률 표시 줄 컨트롤 자체의 한계입니다. PBM_SETRANGE는 제한적이며 2GB보다 큰 값을 처리해야하는 경우 PBM_SETRANGE32을 사용할 수 있지만 문제가 여전히 발생합니다.

동시에 두 번 사용하면 어떨까요? UINT64를 사용하면 약 16,384 페타 바이트가됩니다 (오버플로 할 항목을 다운로드하는 경우 ... 진행률 막대를 건너 뛰면 고객과 고객을 우울하게 만듭니다). 정수는 바이트와 같은 것들을 세는 데 정말 잘 작동합니다.

다운로드하는 파일의 전체 크기를 알고 있다면 제한된 최대 범위를 갖는 진행률 표시 줄의 크기를 조정하는 한 가지 방법은 진행률 막대를 0에서 시작하여 100으로 끝내는 것입니다. 그런 다음 사용 비율로받은 바이트를 변환 할 수 simple rule of three :

percent = (bytes_received * 100)/max_bytes; 

당신이 더 많은 "단위"는 1000 진행률 표시 줄의 규모를 변경하고 그에 따라 계산을 조정할 수 있습니다을 얻고 싶은 경우에; 당신은 심지어 10000에 갈 수 있지만 그 시점에서 컨트롤의 너비 (또는 높이)에 따라 아마 당신은 모니터의 해상도에 부딪 힐 것이다.

+0

differnet 종류의 문제, 위의 새 코드를 업데이트했습니다. – StudentX

관련 문제