Share via


How to add ProgressBar in VC++ MFC ?

Question

Tuesday, May 26, 2015 5:36 AM

How to add ProgressBar at the stage of Processing some methods in Thread.

i want to show loading image while processing that's why i need to add progress bar while running the thread.

when i click the start button the Thread will start (at this time i want to show progress bar at center of the screen. just like Visual Studio opening it'll show rectangular box with progress bar and some text).

How to achieve it..?

All replies (25)

Wednesday, May 27, 2015 7:51 AM | 1 vote

Hi,

You can create a dialog to host a progress bar. You could use some global variables to make the progress control associated with your worker thread. I make a sample to create that progress bar.

void CMyDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
    CDialogEx::OnShowWindow(bShow, nStatus);
    m_progress.SetRange(0, 100);

    m_progress.SetPos(0);

    m_progress.SetStep(1);
    this->KillTimer(1);
    this->SetTimer(1, 20, NULL);
    
    // TODO: Add your message handler code here
}

Handle the timer:

void CMyDlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: Add your message handler code here and/or call default
    CDialogEx::OnTimer(nIDEvent);
    

    for (int i = 1; i <= 100; i++)
    {
    Sleep(50);
    m_progress.SetPos(i);

    }

    this->EndDialog(true);
}

In above code, you could change the value of "i"(m_progress.SetPos(i) ) to a global variable which used in your worker thread.

this->KillTimer(1);//kill the timer

Check the screenshot:

Hope this helps some.

Shu

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Wednesday, May 27, 2015 8:41 AM

thanks for reply.

what code i put under the onbuttonClick(). ?

and any funtion to mention unde MESSAGE_MAP ?


Wednesday, May 27, 2015 8:43 AM

To make the progress control associated with your worker thread. check below code snippets:

static int Varglobal;
...
int CMyDlg::Varglobal = 0;
...
AfxBeginThread(function, this);
...

UINT CMyDlg::function(LPVOID pParam)
{
    for (int i = 0; i < 100; i++){
        CMyDlg::Varglobal++;
        Sleep(50);
    }

    CMyDlg::Varglobal = -1;
    return 0;

}
...
void CMyDlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: Add your message handler code here and/or call default
    CDialogEx::OnTimer(nIDEvent);
    

    //for (int i = 1; i <= 100; i++)
    //{
    //Sleep(50);
    m_progress.SetPos(Varglobal);

    //}
    if (CMyDlg::Varglobal==-1)
        this->EndDialog(true);
}

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Wednesday, May 27, 2015 8:55 AM

Does not show that progress Dialog window.

how to solve it? Is there is any extra code to display that progress dialog


Wednesday, May 27, 2015 8:55 AM

thanks for reply.

what code i put under the onbuttonClick(). ?

and any funtion to mention unde MESSAGE_MAP ?

Do mean the button to show the dialog? if yes, check this:

void CMFC_WorkerThread_ProcessBarDlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here
    
    CMyDlg* pdlg = new CMyDlg;
    INT_PTR nResponse = pdlg->DoModal();

    if (nResponse == IDOK)
    {
        // TODO: Place code here to handle when the dialog is
        //  dismissed with OK
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: Place code here to handle when the dialog is
        //  dismissed with Cancel
    }
    else if (nResponse == -1)
    {
        TRACE(traceAppMsg, 0, "fail.\n");     
    }
}

And you need to add WM_TIMER(OnTimer) and WM_SHOWWINDOW(OnShowWindow) message handler in the class wizard.

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Wednesday, May 27, 2015 9:00 AM

my problem is,

i have one thread named as "WorkerThread". under the workerThread i call 5 functions.

now i need to show progress window .

i start the Thread when i press the run button. now i want to show progressBar.

when all the functions are completed then the progress will finish the loading option(that green loading point)and close the progress window.

how can i achieve this?


Wednesday, May 27, 2015 9:07 AM

I still do not see the problem, therefore please post some of your code where you create cour progress bar, where you call your thread and what functions you want to call in your thread...

I assume we will not come further if we do not see code...

Best regards

Bordon

Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.


Wednesday, May 27, 2015 9:08 AM

the

WM_TIMER(OnTimer)
WM_SHOWWINDOW(OnShowWindow)

gives error as follow as,


Wednesday, May 27, 2015 9:17 AM

under the button click

void CSDlg::OnBnClickedTestButton()
{
    // TODO: Add your control notification handler code here
        AfxBeginThread(WorkerThread,this);
    
}

Thread code,

UINT WorkerThread(LPVOID pParam)
{
    funtion1(); //assume funtion 1 contains addtion of two numbers
    funtion2(); //assume funtion 1 contains subtraction of two numbers
    funtion3(); //assume funtion 1 contains multiplication of two numbers
    funtion4(); //assume funtion 1 contains division of two numbers
    funtion5(); //assume funtion 1 contains % of two numbers
    
    //finally i want to print result here.
    //like
    SetDlgItemText(IDC_RESULT,final_result);    //assume final_result contains result text
    
return 0;

}

now i want to display the progress window when i click the button. then update 20% of loading to the progressBar each funtion is completed.

finally function5() is completed ,then show test completed messge then automatically close the progressBar window.

thanks


Wednesday, May 27, 2015 9:18 AM

I know you have problem, but I just show you a sample of how to achieve this. We don't know what you are doing, you need to debug your code and find out why it is not working. I have posted the sample code of how to handle your "workerthread" with the CprocegressCtrl control (using a static variable).

You may need to tell me what problem you get if you use the approach in above code.

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Wednesday, May 27, 2015 9:26 AM

But your sample code does not have clear solution. do you have any demo ?.

previously i tell my problem clearly.i post thread code and button_click code.

kindly give a better solution to me.


Wednesday, May 27, 2015 9:36 AM

the

WM_TIMER(OnTimer)
WM_SHOWWINDOW(OnShowWindow)

gives error as follow as,

I don't know why you get this error.

What you need to do is:

Right click the class and select class wizard. Then you should find the WM_TIMER , WM_SHOWWINDOW and click add handler.

You can download the demo here: http://1drv.ms/1GCUH02

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Wednesday, May 27, 2015 9:37 AM

the

WM_TIMER(OnTimer)
WM_SHOWWINDOW(OnShowWindow)

gives error as follow as,

This was not code you were supposed to write. Shu Hu just meant that the WM_TIMER handler in MFC is called OnTimer, and similarly for WM_SHOWWINDOW.

David Wilkinson | Visual C++ MVP


Wednesday, May 27, 2015 10:46 AM

i just copy the demo project then it gives error like

Error    1    error LNK2001: unresolved external symbol "public: static int CMyDlg::Varglobal" (?Varglobal@CMyDlg@@2HA)   

in MyDlg.obj 

what can i do now?


Wednesday, May 27, 2015 10:47 AM

Try this:

Cpp file:

UINT CStatBarDlgDlg::ThreadProc(LPVOID ptr)
{
  CProgressCtrl* progress=(CProgressCtrl*)ptr;

  progress->SetPos(20);

  return 0;
}

void CStatBarDlgDlg::OnBnClickedButton1()
{
  // TODO: Add your control notification handler code here
  CWinThread *pThread = AfxBeginThread(ThreadProc, &m_ProgressBar_ics);
}

H File:

#pragma once

...

// CStatBarDlgDlg dialog
class CStatBarDlgDlg : public CDialog
{
....
  CProgressCtrl m_ProgressBar_ics;
...
public:
  static UINT ThreadProc(LPVOID ptr);
...
};

This works perfectly so far for a quick and dirty test...

The Progrssbar is addred to the dialog, and the member variable of the progress bar was created using the IDE and "Add variable..."

Best regards

Bordon

Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.


Wednesday, May 27, 2015 10:58 AM

Try this:

Cpp file:

UINT CStatBarDlgDlg::ThreadProc(LPVOID ptr)
{
  CProgressCtrl* progress=(CProgressCtrl*)ptr;

  progress->SetPos(20);

  return 0;
}

void CStatBarDlgDlg::OnBnClickedButton1()
{
  // TODO: Add your control notification handler code here
  CWinThread *pThread = AfxBeginThread(ThreadProc, &m_ProgressBar_ics);
}

H File:

#pragma once

...

// CStatBarDlgDlg dialog
class CStatBarDlgDlg : public CDialog
{
....
  CProgressCtrl m_ProgressBar_ics;
...
public:
  static UINT ThreadProc(LPVOID ptr);
...
};

This works perfectly so far for a quick and dirty test...

The Progrssbar is addred to the dialog, and the member variable of the progress bar was created using the IDE and "Add variable..."

Best regards

Bordon

Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.

This may work, but you are manipulating a window (the progress control) from a thread different from the one in which it was created. This often causes problems in MFC. A better method is to use PostMessage() or SendMessage to relay a custom message back to the dialog, and have the dialog update the progress bar.

But the key idea that you have shown the OP is to use the LPVOID parameter of the thread function to access the context.

David Wilkinson | Visual C++ MVP


Wednesday, May 27, 2015 11:05 AM

i still not able to get correct output.

i cant understand your statement

The Progrssbar is addred to the dialog, and the member variable of the progress bar was created using the IDE and "Add variable..."


Wednesday, May 27, 2015 11:16 AM

david,

I agree with you, but in this case I do not see any problem, the SetPos code only calls SendMessagE:

_AFXCMN_INLINE int CProgressCtrl::SetPos(int nPos)
    { ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, PBM_SETPOS, nPos, 0L); }

Since I know this I brought my solution. But is it also as easy passing the HWND to the thread and using SendMessage directly... But at least you need to know what message you need to use and how you must do it, and I doubt the OP has the WinAPI knowledge. The OP is a beginner I assume...

Best regards

Bordon

Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.


Wednesday, May 27, 2015 11:38 AM

i just copy the demo project then it gives error like

Error    1    error LNK2001: unresolved external symbol "public: static int CMyDlg::Varglobal" (?Varglobal@CMyDlg@@2HA)   

in MyDlg.obj 

what can i do now?

MyDlg.h

class CMyDlg
{
..
 static int Varglobal;
..
};

MyDly.cpp

int CMyDlg::Varglobal=0;

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Wednesday, May 27, 2015 11:53 AM

Hi Shu Hu,

i done based on your demo . thanks a lot.

but still i need i help.

i already told my thread have 5 functions. but that progress dialog shows only my 2'nd function is completed. i want to show that progressBar till my last function is completed.

As per the given demo the progressBar SetRange(0, 100). now i need to pass the high value(100) from another cpp file.


Wednesday, May 27, 2015 12:11 PM

and it has another problem.

the problem is under the your demo , the progressBar dialog have Sleep(50). it'll be not good. because i have have already one thread . i start that Thread when i click the Button.

now i add new Thread which is in your Demo so my time consuming is to huge .

so how to run these two thread at a same time simultaneously?

i put the following code behind of my 5 functions

CMyDlg* pdlg = new CMyDlg;
INT_PTR nResponse = pdlg->DoModal();
funtion1();
funtion2();
funtion3();
funtion4();
funtion5();

this code behaves when the progress dialog is close then only my functions will start.

now i want to run progress dialog and as well as my 5 functions at a time.

Is there any possible to achieve this?


Wednesday, May 27, 2015 12:46 PM

As hint, DoModal returns if the dialog window will be closed. As long as the dialog ist not closed (that means visible function1-5 will not be called!

Best regards

Bordon

Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.


Wednesday, May 27, 2015 2:04 PM

david,

I agree with you, but in this case I do not see any problem, the SetPos code only calls SendMessagE:

_AFXCMN_INLINE int CProgressCtrl::SetPos(int nPos)
    { ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, PBM_SETPOS, nPos, 0L); }

Yes, because CProgresCtrl::SetPos() just uses SendMessage() your code will work. But if you do not know this, then the safer method is to use SendMessage() or PostMessage() with a custom message. One thing I do know (and use) is the fact that CWnd::SendMessage() and CWnd::PostMessage() just simply wrap the Win32 calls, so they are safe to use from another thread.

David Wilkinson | Visual C++ MVP


Thursday, May 28, 2015 4:34 AM

i call 1-5 functions after the following code

CMyDlg* pdlg = new CMyDlg;
INT_PTR nResponse = pdlg->DoModal();

that's why the Progress Dialog runs first. when it's completes the process then only  1-5 functions. it works nice.

Progress Dialog has Thread . and i call the thread within the thread like,

void CSDlg::OnBnClickedTestButton()
{
AfxBeginThread(WorkerThread,this);  
}

under button click i call 1 thread (mainThread- works my 1-5 functions) like

UINT CSelfTestDlg::WorkerThread(LPVOID pParam)
{
    CMyDlg* pdlg = new CMyDlg; //this have 1 thread used to display progressBar dialog
    INT_PTR nResponse = pdlg->DoModal();

   function1();
   function2();
   function3();
   function4();
   function5();

return 0;

}

but i want to run CMyDlg in background. (that is CMyDlg is not affect my WorkerThread Process but it should show that dialog)

for example,

windows copy option. when we copy some files from somewhere it shows the coping dialog. and in background the copy function going well . i want like this.

help me..


Thursday, May 28, 2015 6:33 AM

At least now I begin to understand your problem. Your question is more design pattern related than Progress Bar, Thread or MFC related.

I would create a new class thant handles this specific action, like copying a file from location a to b. This class is not derived from CDialog, but this class also contains a dialog. When the copy operation begins a dialog will be opened. This can be done using doModal, but before DoModal is called also a thread that is indended to process the action (in my example copy operation) is started. The thread communicates with the dialog to update i.e. a progress bar or displays the name of the current filename that is copied if more than one file is copied, ...

The communication may be done in the way I tried to expaon in several of my posts or using windows messages or the prefered IPC mechanism you like.

Best regards

Bordon

Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.