In a Win32 C ++ application, every time a PBM_STEPIT message is received, the progress bar changes from 0 to the maximum value, but does not increment

  • Thread starter Thread starter Purple_Apple
  • Start date Start date
P

Purple_Apple

Guest
Hello. I write Win32 C++ application using Visual Studio 2017 Community. My application has a progress bar and, thanks to it, the next problem. Every time a PBM_STEPIT message is received, the progress bar changes from 0 to the maximum value, but does not incrementally increment its value. Although, I can’t demonstrate such “dynamic” changes here, but I provide a snapshot of the screen nonetheless. Please see it below:

1580421
1580443.png

But, let me tell you everything in order. In the application, I define a progress bar as follows. In the main application file, which contains, in particular, the wWinMain function and the WndProc window procedure, I, relative to the progress bar, define the following constants and variables:

// Progress bar window handle.
HWND g_hWndProgressbar;


// A message to set the progress bar to its initial state.
const UINT WM_RESETPROGRESS = WM_USER + 100;
// Message to change the value of the progress bar.
const UINT WM_UPDATEPROGRESS = WM_USER + 200;
// The range of values for the progress bar (or its maximum value).
int range;
Then, in the same file, I define a function to create a progress bar:

HWND CreateProgressBar(HWND hwndParent)
{
RECT rcClient; // Client area of parent window.
RECT r1;
int cyVScroll; // Height of scroll bar arrow.
HWND hwndPB; // Handle of progress bar.

// Ensure that the common control DLL is loaded, and create a progress bar
// along the bottom of the client area of the parent window.
//
// Base the height of the progress bar on the height of a scroll bar arrow.

InitCommonControls();

GetClientRect(hwndParent, &rcClient);

SendMessage(g_hWndStatusbar, SB_GETRECT, 1, (LPARAM)&r1);

cyVScroll = GetSystemMetrics(SM_CYVSCROLL);

// Create the progressbar.
hwndPB = CreateWindowEx(
0, // without using of extended windowed styles
PROGRESS_CLASS, // it'll be a progresbar
(LPTSTR)NULL, // without any text inside it
WS_CHILD | WS_VISIBLE | PBS_SMOOTH, // create progressbar as follow:
// - it is a child window
// - it is visible immediately after its creation
// - indicator filling will be shown as a solid bar
r1.left + 3, // put progress bar into right part of the status bar
r1.top + 3,
r1.right - r1.left, cyVScroll,
g_hWndStatusbar, // its parent window is the status bar
(HMENU)0, // no menu
hInst, // actually the handle to the module associated with the main application window
NULL // no additional data required
);

return hwndPB;
}
In the WndProc window procedure, I do the following:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
. . . . . . .
case WM_RESETPROGRESS: // Set progress bar in its initial state
// Get the progressbar changing range (maximum value) as a result
// of receiving a message from a stream performing triangulation.
range = (int)(lParam);
// Set the range of the value for the progress bar.
SendMessage(g_hWndProgressbar, PBM_SETRANGE32, 0, MAKELPARAM(0, range));
// Set the step of changing the value for the progress bar to one (1).
SendMessage(g_hWndProgressbar, PBM_SETSTEP, (WPARAM)1, 0);
// Set the initial value for the progress bar to zero (0).
SendMessage(g_hWndProgressbar, PBM_SETPOS, 0, 0);
break;
case WM_UPDATEPROGRESS: // Set the current value to the progress bar.
// (A gradual incremental increment of the
// indicator value should be performed here.)
SendMessage(g_hWndProgressbar, PBM_STEPIT, 0, 0);
break;
. . . . . . .
case WM_CREATE:
. . . . . . . .
g_hWndProgressbar = CreateProgressBar(hWnd);
. . . . . . . .
break;
. . . . . . .
case WM_SIZE:
. . . . . . . .
SendMessage(g_hWndProgressbar, WM_SIZE, wParam, lParam);
. . . . . . . .
break;
}
}
Then, I decide to try how it all works, and from the stream in which the source data for triangulation is read, messages are sent to the progress bar so that it shows signs of life. I do it very simply, namely, in the file in which the source data is read, I write:

// Message to set the progressbar in initial state.
const UINT WM_RESETPROGRESS = WM_USER + 100;
// Message to update a value of the progressbar.
const UINT WM_UPDATEPROGRESS = WM_USER + 200;

Note! This is not the file where wWinMain and WndProc are defined. This is the file that contains the definitions of functions that are members of a class that provides loading of the source data for triangulation from input file on disk. After that I write there:

void DelaunayInitialization::ReadNodes(HWND hWnd, Mesh* m, Configuration* b, wstring nodefilename, cancellation_token token)
{
if (token.is_canceled())
cancel_current_task();
else
{
. . . . . . . . .
// Get the number of vertices (source points for triangulation).
m->InVertices = (int)wcstol(stringptr, &stringptr, 0);
. . . . . . . . .
// Send the number of input vertices to the main window
// to initialize the range of the progress bar and set
// the progress bar to its initial state.
int vertices = m->InVertices;
PostMessage(hWnd, WM_RESETPROGRESS, 0, (LPARAM)vertices);

// Read the vertices coordinates.
for (int i = 0; i < m->InVertices; i++)
{
if (token.is_canceled())
cancel_current_task();
else
{
. . . . . . . . .
// Send, to the main application window, a message stating
// that the value of the progress bar should be changed.
PostMessage(hWnd, WM_UPDATEPROGRESS, 0, 0);
. . . . . . . . .
}
}
}
}
In this manner, I’m trying to get the progress bar to show, in particular, the degree of completion of loading the source data for triangulation. But at the same time, the problem described at the beginning of this post arises. Why every time the progress bar receives a PBM_STEPIT message, it does not incrementally increment its value by one, gradually progressing from zero to maximum, but immediately fills over its entire length? Then, it is as if reset and, upon receipt of the next PBM_STEPIT - the same thing is repeated again. There is one more, in my opinion, strange thing. If I, in the processing of the WM_RESETPROGRESS message, write not like this:

SendMessage(g_hWndProgressbar, PBM_SETRANGE32, 0, MAKELPARAM(0, range));
but like this:

SendMessage(g_hWndProgressbar, PBM_SETRANGE, 0, MAKELPARAM(0, range));
note that instead of sending a message PBM_SETRANGE32 I send PBM_SETRANGE, then the progress bar changes normally - gradually passing all its distance during the execution of reading all the original vertices. But, in this case, by the time the reading of all the source vertices is complete, it has managed to pass only half its length and, accordingly, stops, since the reading of the source data, which it must track, has completed. The same thing will happen if I write:

SendMessage(g_hWndProgressbar, PBM_SETRANGE32, 0, range);
That is, if I leave PBM_SETRANGE32, but slightly change the appearance of the passing of the last parameter in the function, the result will be exactly the same as when using PBM_SETRANGE. Why? Please help me deal with all these things. I especially want to solve the problem of why the progress indicator does not increase its value by one, gradually progressing from zero to maximum, but it immediately fills its entire length if I write in WM_RESETPROGRESS handler:

// Set the range of the value for the progress bar.
SendMessage(g_hWndProgressbar, PBM_SETRANGE32, 0, MAKELPARAM(0, range));
Please help me solve this problem. I will be very grateful.

Continue reading...
 
Back
Top