Initializing a CProgressCtrl Object Inside CDialog :: MFC
-
Okay. Thanks. You were right. I did not have to create the progressbar. I did, however, override PreCreateWindow() and set the range and position of the progressbar. Now I need a way to update it from my view class. Kuphryn
-
Right now, I just want to get it working. To test it out, I want to update it ever 25 milliseconds. Here is the code: ----- CMyDialog mDlg; for (int i = 0; i < 100; ++i) { mDlg.SetNewProgressPos(i); ::Sleep(25); } if (mDlg.DoModal == IDOK) {} ----- // void SetNewProgressPos(int newPos) // { // m_MyProgressBar.SetPos(newPos); // } The code above does not work though. The program crashes. The code that causes it to crash is this: // m_MyProgressBar.SetPos(newPos); I tried calling that function from inside the dialog box as well as outside. That line crashes the program both times. Kuphryn
-
Right now, I just want to get it working. To test it out, I want to update it ever 25 milliseconds. Here is the code: ----- CMyDialog mDlg; for (int i = 0; i < 100; ++i) { mDlg.SetNewProgressPos(i); ::Sleep(25); } if (mDlg.DoModal == IDOK) {} ----- // void SetNewProgressPos(int newPos) // { // m_MyProgressBar.SetPos(newPos); // } The code above does not work though. The program crashes. The code that causes it to crash is this: // m_MyProgressBar.SetPos(newPos); I tried calling that function from inside the dialog box as well as outside. That line crashes the program both times. Kuphryn
Ok. I see what you are trying to do. You need to create a class for your dialog (by deriving from CDialog. Use Class Wizard), and do all of this in there. None of the controls for your dialog have been created when you are doing your loop. They don't get created until you call DoModal, and they get destroyed by the time DoModal returns. When I say created and destroyed, I don't mean the object gets destroyed. Rather, the Handle to the control that the progress control object wraps is destroyed. And you the functions that you are calling are thin wrappers to API calls using the Handle. Thus the crash. So, as I said, create a class for your dialog. Add the control to the class using class wizard. Also add a button to the dialog, and add a button clicked handler. Then, when the button gets pushed, add your for loop in the button handler. Hope that helps.
-
Ok. I see what you are trying to do. You need to create a class for your dialog (by deriving from CDialog. Use Class Wizard), and do all of this in there. None of the controls for your dialog have been created when you are doing your loop. They don't get created until you call DoModal, and they get destroyed by the time DoModal returns. When I say created and destroyed, I don't mean the object gets destroyed. Rather, the Handle to the control that the progress control object wraps is destroyed. And you the functions that you are calling are thin wrappers to API calls using the Handle. Thus the crash. So, as I said, create a class for your dialog. Add the control to the class using class wizard. Also add a button to the dialog, and add a button clicked handler. Then, when the button gets pushed, add your for loop in the button handler. Hope that helps.
Yes! Thanks. Your pointer was key to the fix. Is there a way to *interrupt* the progress? For example, let say the user wants to cancel out, but the program is still processing something and the progressbar is not at 100. Is there a way to implement a cancel button to exit completely? Kuphryn
-
Yes! Thanks. Your pointer was key to the fix. Is there a way to *interrupt* the progress? For example, let say the user wants to cancel out, but the program is still processing something and the progressbar is not at 100. Is there a way to implement a cancel button to exit completely? Kuphryn
Yes. There are a number of ways to do this, and most depend on the nature of the work you are computing. The best choice would be to create a worker thread to accomplish the task you want to process, and if they cancel key gets pressed, just kill the thread. This will allow your UI to still be responsive while the task is being completed. But threading is tricky, and it sounds like you are newer to MFC and possibly C++. Another possibility is avoiding creating your own dialog and just use one like Chris Maunder's found here: http://www.codeproject.com/miscctrl/progresswnd.asp This is the simplest approach, but it isn't multi-threaded, and thus, your program will seem unresponsive until the point in your loop where you check to see if the cancel button was pressed. Then all you have to do is just break out of whatever loop you are using to do your work. D
-
Yes. There are a number of ways to do this, and most depend on the nature of the work you are computing. The best choice would be to create a worker thread to accomplish the task you want to process, and if they cancel key gets pressed, just kill the thread. This will allow your UI to still be responsive while the task is being completed. But threading is tricky, and it sounds like you are newer to MFC and possibly C++. Another possibility is avoiding creating your own dialog and just use one like Chris Maunder's found here: http://www.codeproject.com/miscctrl/progresswnd.asp This is the simplest approach, but it isn't multi-threaded, and thus, your program will seem unresponsive until the point in your loop where you check to see if the cancel button was pressed. Then all you have to do is just break out of whatever loop you are using to do your work. D
Thanks. I have Prosise's book in front of me. I can implement a multi-threaded program, but it will take me some time and certain not in one night (maybe two weeks). Having a progressbar inside a dialogbox is more complicated than I originally expected. If the progressbar does not get created until *after* a call to DoModal(), but then it gets unvalidated after DoModal() returns IDOK, there is no way to really update the progressbar from outside of the dialogbar. For example, what if I were to instantiate a dialogbor inside view. I want to update the progressbar from view, not the dialogbar itself. One last question, is there a way to enable/disable a button that is inside a dialogbox? I cannot get ClassWizard to map commandupdateUI for the dialogbox. That seems to only be valid for menu items in a toolbar. Thanks, Kuphryn
-
Thanks. I have Prosise's book in front of me. I can implement a multi-threaded program, but it will take me some time and certain not in one night (maybe two weeks). Having a progressbar inside a dialogbox is more complicated than I originally expected. If the progressbar does not get created until *after* a call to DoModal(), but then it gets unvalidated after DoModal() returns IDOK, there is no way to really update the progressbar from outside of the dialogbar. For example, what if I were to instantiate a dialogbor inside view. I want to update the progressbar from view, not the dialogbar itself. One last question, is there a way to enable/disable a button that is inside a dialogbox? I cannot get ClassWizard to map commandupdateUI for the dialogbox. That seems to only be valid for menu items in a toolbar. Thanks, Kuphryn
Okay. Prosise described a good way to enable/disable a control 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 Kuphryn
-
Thanks. I have Prosise's book in front of me. I can implement a multi-threaded program, but it will take me some time and certain not in one night (maybe two weeks). Having a progressbar inside a dialogbox is more complicated than I originally expected. If the progressbar does not get created until *after* a call to DoModal(), but then it gets unvalidated after DoModal() returns IDOK, there is no way to really update the progressbar from outside of the dialogbar. For example, what if I were to instantiate a dialogbor inside view. I want to update the progressbar from view, not the dialogbar itself. One last question, is there a way to enable/disable a button that is inside a dialogbox? I cannot get ClassWizard to map commandupdateUI for the dialogbox. That seems to only be valid for menu items in a toolbar. Thanks, Kuphryn
Well, that is what I was gonna ask you. You might want to the dialog to be modeless. You can still do that with a class derived from CDialog. Just call Create on the dialog instead of DoModal. After you call create, you can access all the controls in the dialog from outside the dialog itself (i.e. from the View). Be sure to create the dialog on the heap using new rather than creating it on the stack. You also have to destroy the dialog yourself when you are done with it. Also be sure to override OnOK and OnCancel in the modeless version of the dialog and comment out the calls to the base class version. Dialogbars are also cool, but they don't sound like what you need. A modeless dialog should be just fine. Dialogbars also require a bit more overhead in your code. Good luck
-
Okay. Prosise described a good way to enable/disable a control 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 Kuphryn
-
Well, that is what I was gonna ask you. You might want to the dialog to be modeless. You can still do that with a class derived from CDialog. Just call Create on the dialog instead of DoModal. After you call create, you can access all the controls in the dialog from outside the dialog itself (i.e. from the View). Be sure to create the dialog on the heap using new rather than creating it on the stack. You also have to destroy the dialog yourself when you are done with it. Also be sure to override OnOK and OnCancel in the modeless version of the dialog and comment out the calls to the base class version. Dialogbars are also cool, but they don't sound like what you need. A modeless dialog should be just fine. Dialogbars also require a bit more overhead in your code. Good luck
-
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
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