Link to home
Start Free TrialLog in
Avatar of xenia27
xenia27Flag for Taiwan, Province of China

asked on

Progress Bar with DialogBox....detecting COM Ports...>"<..help~~

Hi,

I got this problem and I'm stucking with those codes seems forever~~  So help me~~

Here is my problem...

I got three main functions in order to detecting COM Ports and show the progress.
1. MainFunc:
In this function, first I call CreateThread like the following
  DlgThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE )ProgressDlg, NULL, 0, &ThreadID);

  if (DlgThread != NULL)
      CloseHandle(DlgThread);
Then, I continue doing the detecting part with some for-loops...
While doig these loops, I use "SendMessage(hwndPB, PBM_STEPIT, 0, 0);"...according to their percentage..of course...to update the progress...

2. ProgressDlg...
In this function, I use "DialogBox(hInst, (LPCSTR)IDD_DetectProgress, gHwnd, ProgressDlgProc);"

3.  ProgressDlgProc
    switch(message)
    {
          case WM_INITDIALOG:
                        hwndDlg = hDlg;
                        hwndPB = GetDlgItem(hDlg, IDC_DetectProgress);
                        SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
                        SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);
                  return 0;
    }


********************************************************************

These functions work fine for the first detecting...but the second time I call these function again...it seems like it will stuck in "ProgressDlg" (the part of DialogBox)...So in the MainFunc, SendMessage and EndDialog cannot have the right value for the handle part...so what's wrong with my codes?  What should I do to make my codes works fine??  Help~~~  Help~~~  >"<

Xenia

Avatar of Roshan Davis
Roshan Davis
Flag of United States of America image

Are you calling any dialog specific functions from thread (instead of posting messages..)...?

If you, change that to PostMessage

Rosh L)
Avatar of xenia27

ASKER

I don't understand what you mean...>"<  Sorry~
The thread...basically only execute the function "ProgressDlg"...and which will call "DialogBox" and "ProgressDlgProc"....and I didn't do anything else at all...>"<


Xenia
Avatar of AlexFM
AlexFM

I don't see handling of PBM_STEPIT message. I don't see here where dialog is created, where worker thread is created. A lot of important information is missing in your post, and it is very difficult to find the problem. Even description of the problem itself:
>>...it seems like it will stuck in "ProgressDlg" (the part of DialogBox)...So in the MainFunc, SendMessage and EndDialog cannot have the right value for the handle part...
is not clear.

When you ask the question, provide more details and relevant code fragments. Please post here:

1) Full thread creation code
2) Full dialog creation code
3) Thread function
4) Dialog message handler
5) Exact description of the problem - program is freezing (where), or progress bar is not moving, or handle is invalid (what handle, where?) etc.
Avatar of xenia27

ASKER

1. int MainFun()
{
  DlgThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE )ProgressDlg, NULL, 0, &ThreadID);

  if (DlgThread != NULL)
      CloseHandle(DlgThread);

  // here I tried to detect COM Port with CreateFile with for-loops with
  // the combination of baudrate, databits...etc
  // Then I send Message to update progress
  SendMessage(hwndPB, PBM_SETPOS, 100, 0); <-  here the hwndPB, a handle, is incorrect
  EndDialog(hwndDlg, NULL); <- hwndDlg is invalid, too
  // hwndPB and hwndDlg are global vairlabes
  // and they suppose to be sat in "ProgressDlgProc"
 // PBM_SETPOS is defined in "commctrl.h" which is in a library.
}

////////////////////////////////////////////////////////////////////////////////
2. void WINAPI ProgressDlg()
{
      DialogBox(hInst, (LPCSTR)IDD_DetectProgress, gHwnd, ProgressDlgProc); <-- where the program freezed
}

//////////////////////////////////////////////////////////////////////////////

3. BOOL CALLBACK ProgressDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
          case WM_INITDIALOG:
                        hwndDlg = hDlg;
                        hwndPB = GetDlgItem(hDlg, IDC_DetectProgress);
                        SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
                        SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);
                  return 0;
      }
      return FALSE;
}

***************************************************************************

Is these better?  Or can I have your email so I can send the codes?  Sorry for your inconvenience.  >"<
Avatar of xenia27

ASKER

Or if there is any better way to create a progress bar or an easier way???  I'm using VC++ of course...Any suggestions??? ^^"
All this code is completely wrong. Dialog box should be created in the main thread. In the WM_INITDIALOG message handler create worker thread which should scan COM ports and post user-defined message to the dialog. Dialog handles these messages in the main thread and update progress bar.

#define WM_PROGRESSMESSAGE WM_APP + 100

int MainFun()
{
    // create dialog here
    // ProgressDlgProc is dialog function
}


BOOL CALLBACK ProgressDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
         case WM_INITDIALOG:
                    hwndDlg = hDlg;
                    hwndPB = GetDlgItem(hDlg, IDC_DetectProgress);
                    SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
                    SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);

                    // create worker thread here passing dialog handler to it as parameter

                    break;
         case WM_PROGRESSMESSAGE:

                    // update progress bar here

                    break;                  

               return 0;
     }
     return FALSE;
}



// in the thread function:
get dlg handler from thread parameter

while ( some loop )
{
    // do something (detect COM port etc.)

    PostMessage(hDlg, WM_PROGRESSMESSAGE, n, 0);  // n is progress step
}
Avatar of xenia27

ASKER

So your suggestion is that I should do this??

int MainFunc
{
  DialogBox(hInst, (LPCSTR)IDD_DetectProgress, gHwnd, ProgressDlgProc);

  while (loop)
  {
    PostMessage(hDlg, WM_PROGRESSMESSAGE, n, 0);
  }
}

BOOL CALLBACK ProgressDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
         case WM_INITDIALOG:
                    hwndDlg = hDlg;
                    hwndPB = GetDlgItem(hDlg, IDC_DetectProgress);
                    SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
                    SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);

                    // create worker thread here passing dialog handler to it as parameter
>>               Question here:
>>               I'm confused about the dialog handler...I thought hwndDlg and hwndPB are the dialog
>>               handlers and they are global variables...
                    break;
         case WM_PROGRESSMESSAGE:

                    // update progress bar here
>>               Question again:
>>               How can you update the progress bar??  Isn't that I can update my progress bar with
>>               "SendMessage"???
                    break;                  

               return 0;
     }
     return FALSE;
}


Thanks for your advise! ^^


Xenia
Avatar of xenia27

ASKER

Hi,

Is there any example that I can study???  Please help me~~  >"<

Xenia
#define WM_PROGRESSMESSAGE WM_APP + 100   // wParam - progress bar position

int MainFunc
{
  DialogBox(hInst, (LPCSTR)IDD_DetectProgress, gHwnd, ProgressDlgProc);
}

BOOL CALLBACK ProgressDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
         case WM_INITDIALOG:
                    hwndDlg = hDlg;
                    hwndPB = GetDlgItem(hDlg, IDC_DetectProgress);
                    SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
                    SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);

                    // start worker thread
                    unsigned threadID;
                   _beginthreadex(NULL,  0, ThreadProc, hDlg, 0, &threadID);

                    break;
         case WM_PROGRESSMESSAGE:

                    // update progress bar here
                    SendMessage(hwndPB, PBM_SETSTEP, wParam, 0);
                    break;                  

     }
     return FALSE;
}

unsigned ThreadProc(LPVOID param)
{
    HWND hDlg = (HWND)param;

    while ( ... )
    {
          // do something

          PostMessage(hDlg, WM_PROGRESSMESSAGE, n, 0);  // n - required progress bar position
    }
}
ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of xenia27

ASKER

Hi, AlexFM,

Thanks for yor information...I'll try to work with it today...^^"...If I got more question, I'll definitely ask again~  Thank you~~  ^^



Xenia
Avatar of xenia27

ASKER

Hi,

I got this problem...error C2065: '_beginthreadex' : undeclared identifier
I did what you said in the previous message...including <process.h> and made some adjustments in the setting part....but it still didn't complie..
Avatar of xenia27

ASKER

Hi,

I have this question...can I use CreateThread instead of using _beginthreadex???
What's the difference bwteen these two functions?? ^^  Thanks for your help.


Xenia
Jeffrey Richter's "Programming Applications for Microsoft Windows 2000" contains explanation why _beginthreadex is better than CreateThread, I don't remember details. _beginthreadex is deined in PROCESS.H:

#ifdef  _MT
_CRTIMP unsigned long __cdecl _beginthreadex(void *, unsigned,
        unsigned (__stdcall *) (void *), void *, unsigned, unsigned *);
#endif

_MT is defined in project settings when we select DEbug Multithreaded (for Debug configuration) or Multithreaded (for Release configuration) run-time library. See MSDN topic:
/MD, /ML, /MT, /LD   (Use Run-Time Library)
_beginthreadex calls CreateThread, but first it makes some other important things (I don't remember what exactly).
Avatar of xenia27

ASKER

Hi,

I got this question...about my project of course...

I noticed that the handle was wrong because the ProgressDlgProc was called seconds later after SendMessage...so the handle was wrong...So what can I do to adjust it?  I tried to Sleep for a while but it seems it won't work...>"<  And I found some discussion before but I cannot find it now...Please help me...


Xenia
Please describe with more detailes - code, where and what happened.
Avatar of xenia27

ASKER

Here is what happened in my codes..

int MainFunc
{
  DlgThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE )ProgressDlg, NULL, 0, &ThreadID);

  if (DlgThread != NULL)
      CloseHandle(DlgThread);
  Sleep(2000);
  for(conditions...)
  {
    // here I use CreateFile for detecting COM port
    // and then, I use GetPage function to know whether the port is connected or not.
    Sleep(5000);
>>>   SendMessage(hwndPB, PBM_STEPIT, 0, 0); <-- when this function called, ProgressDlgProc is not called yet...so hwndPB has the wrong value...
  }
  EndDialog(hwndDlg, NULL);
>>>  // in the end of this function...ProgressDlgProc called...
}

void WINAPI ProgressDlg()
{
    DialogBox(hInst, (LPCSTR)IDD_DetectProgress, gHwnd, ProgressDlgProc);
}


BOOL CALLBACK ProgressDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
          case WM_INITDIALOG:
            hwndDlg = hDlg;
            hwndPB = GetDlgItem(hDlg, IDC_DetectProgress);
                      SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
            SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);
            return TRUE;
      }

      return FALSE;
}

/////////////////////////////////////////////////
Ok...this is my old codes...but I think I have to work it out with the old codes...>"<
I tried Sleep in order to delay for SendMessage in the MainFunc after CreateThread...but there is always two seconds difference...and ProgressDlgProc is always late for two seconds..so SendMessage in MainFunc has the wrong handle.
So what can I do for this project?  Thanks for your helps~~~  ^^
Please change your code according to my recommendations. Your code is completely wrong and cannot work in any case. It's impossible to say how to correct it.
COM ports scanning which is made in the main thread prevents main thread message loop to handle window messages. This is only one problem of this code - I don't see a reason to find and describe all problems in it.
Rewrite your code according to my post from 12/12/2003 04:17AM PST, I don't think this is a hard work. After this ask specific questions if there are problems.

Avatar of xenia27

ASKER

Hi,

I finally get this problem done...but I have another problem....>"<
After detecting the device, I would like to restart the windows...so I use "ExitWindowsEx(EWX_REBOOT, 0);"  BUT...I got this error message right after I execute the command...it's error code: 1314...which means "A required privilege is not held by the client."  So what can I do with this problem??  Help~  Please~~  ^^

Thanks for the helps~~~~



Xenia
PS...is this description clear enough????
Avatar of xenia27

ASKER

Hi, Hi,

I got my problem solved already~  Finally~  ^^  Thanks for all the helps~~~  




Xenia
Yes, the description is clear :-)
Avatar of xenia27

ASKER

Hi, ^^

I'm so happy now that my project is done...at least one of the difficult part is done...^^
Now...I'm studying how to create windows service...^^...

Anyway, thanks for your helps.

Xenia