Initializing a CProgressCtrl Object Inside CDialog :: MFC

kuphryn

Senior member
Jan 7, 2001
400
0
0
Hi.

I have a CDialog (modal) object. It serves as a progress dialog similar to the one that you see while waiting for EI to finish downloading. Inside the actual dialogbox is a CProgressCtrl object. Right now, the progress bar does not do anything. I tried initializing it like this:

m_MyProgressBar.SetRange(0, 100);
m_MyProgressBar.SetPos(0);

The program crashed when I add the code above. I did *not* create the object. The reason is I did not know the size of the object.

For example, this code comes from Prosise's book:

m_MyProgressBar.Create(WS_CHILD | WS_VISIBLE, rect, this, -);

I added a progressbar via Dialogbox Editor. I need to create the progressbar, but I do not know the actual rectangle of the progressbar I made using Dialogbox Editor.

How you to initialize a progressbar made using Dialog Editor?

Thanks,
Kuphryn
 

Adrian Tung

Golden Member
Oct 10, 1999
1,370
1
0
Where did you try to initialize the CProgressCtrl object? It will definitely crash if the dialog, and the progress bar, have not been created yet. You should wait until the dialog is initialized (i.e. after calling DoModal()) before you can call the SetRange() and SetPos() functions.

This can be done in the dialog's OnInitDialog() function, but if you need to do it outside the CDialog, you can declare two public member variables in the CDialog object and set those instead. Then, in OnInitDialog(), initialize your CProgressCtrl object using the member variables.

A side note - you cannot initialize any control in a modal Dialog until it has been created. That's usually what OnInitDialog() is for.


Hope that helps,
:)atwl
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
To build upon what Adrian stated:

The OnInitDialog function actually creates memory and initializes the object.
If you are setting up before the OnInit is called and/or in the constructor, the object is not prepared.
Your are then attempting to perform an operation on a memory address equivalent to addressing a NULL pointer.
 

kuphryn

Senior member
Jan 7, 2001
400
0
0
Thanks.

Here is something I learned and have implemented. Prosise described a good way to enable/disable a control (i.e. button) inside a dialog box. Here is the technique.

CWnd *pWnd = GetDlgItem(IDOK); // item you want to control
pWnd->EnableWindow(FALSE); // this will disable the control
pWnd->EnableWindow(TRUE); // this will enable the control

As for updating the progress bar inside a dialog box, I thought about sending CMainFrm a message which then gets redirected to CChildView. CChildView will then pass a new position to a function in CDialog. I would have to declare the CDialogBox as private in CChildView instead of local in a function. What do you think?

Kuphryn
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
What is controlling the dialog box.

Based on what you just wrote, the dialog is to just to contain a progress bar.

You could setup a timer or interrupt (depending on how the data arrives) in the dialog, that will look at the data needed for the progress bar and the update the bar position within the dialog class that has the progress as a child.

This will prevent the need for the MainFrame to chase the dialog.
 

kuphryn

Senior member
Jan 7, 2001
400
0
0
Thanks.

You gave me an idea. I will post it once I get something cleared up.

Conventionally speaking, should the dialogbox (progressbar) comes first or the access data processing. In other words, when creating a progressbar inside a dialog box, should I begin data manipulation, which is what the dialog box will ultimately depend on to update the progressbar, *before* creating the dialog box or *after*? Either way, it looks like I will need to seen a message to the MainFrm or view after InitDialog() in the dialog box.

Kuphryn
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
It should not make a difference when you update the progress bara s long as the progress bar is "touched" after the OnInitDialog you should be OK. I prefer to start with the bar at 0% and then update it as data comes in.

I would expect that you would set up the progress bar initially with 0% completion.
As the data is handled, the progress bar can be updated.

I myself have not always followed the strict policies/guidelines and
1) If the data analysis/process/interrupts can be controlled within the dialog window (parent of the progress bar), I try to do this and update the progress bar within the diaglog handlers.

2) If the data is/can not/should not be processed within the dialog window, I either
a) post a WM_USER message containing data to the dialog for the progress bar or
b) hang a global pointer out for the main app to get to
c) drill down from the main app to the dialog to get the handle of the progress bar and then update the progress bar.
 

kuphryn

Senior member
Jan 7, 2001
400
0
0
Thanks.

I implemented the WM_USER dialog box handling style.

I am now up against another drawback. The drawback has to do with multithreading. The entire program stalls while it updated the progress bar inside a for loop. I need to implement a solution that would have at least two separate threads. One thread is the default or "main" thread. The second is the progress bar. The second thread would draw the progress bar.

Kuphryn
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
Do not update the progress bar in a loop.

Get the data and send the progress bar or related handler the data. The progress bar then should just set the new position and exit the message handler if used.