Question

passing the HWND of a mfc dialog to the CreateThread function

Asked by: dhenderson12

I have a dialog class that hosts a child dialog (mfc CDialog classes).  I have added the following api function to the top of the parent dialog class file, right below the #include statements:

DWORD WINAPI ThreadFunc(LPVOID pParam)
{
                pWnd->DoThis();
      pWnd->PostMessage(OK);
                return 0;
}

In a method of a class file I have the following:
m_childDialog.DoThis();

I need to run this method in a thread,  so I tried getting the windows handle to the child dialog:
HWND pWnd = m_childDialog.m_hWnd;

I think I can pass the pWnd variable to the thread function, but I don't know how to translate it in the thread function from the pParam argument to a pWnd type, so that I can call the child dialog method in the thread function like this:
pWnd->DoThis();

Can someone give me an example of doing this?

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2009-10-19 at 16:13:14ID24825393
Topics

Microsoft Visual C++

,

Windows MFC Programming

Participating Experts
6
Points
500
Comments
43

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. HWND of a CDialog...
    Hey, Continuing with my problem for having a CDialog automatically closed after a while, I need to pass the handle window parameter of the CDialog I want to send the message WM_CLOSE. I have spend plenty of hours searching for a way to have the HWND of that Dialog unsucessfu...
  2. hWnd
    I would like my programm to change the url of my browser. I know I have to use: ::ShellExecute(hWnd, NULL, _T("http://www.experts-exchange.com"), NULL, NULL, SW_SHOWNORMAL); but I don't know how to get hWnd for the browser window. What I want is my programm to g...
  3. hWnd not attatched to CWnd??
    I'm new to MFC but for the last 3 months or so I've been creating a windows application that is a script interpretter. Basically it looks like a normal window but functions kind of like a command line interface that takes in scripts to be executed as well as general commands...
  4. hWnd for my Single Document MFC App
    I need to get the hWnd of my Single Document MFC App in the InitInstance( ) of my application. I don't know how to do it, is there a one liner, or something someone can give me? Please help me out. Or tell me how to change an m_pMainWnd to an hwnd, if possible. I nee...
  5. "Loose" the HWND of Cwnd in MFC ???
    Hi EXPERTS in MFC! I don't know for what reason (after m_cList1 handle it)the HWND of CWnd is 0? Please help me. Here is the code : void CSeeResultDlg::OnDblclkList1() { int LIndex; char FisName; char *Name; LPCTSTR myRez; //HWND hWnd; ...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: dhenderson12Posted on 2009-10-19 at 16:15:45ID: 25609786

I forgot to add that I plan to call the CreateThread() function, passing the following values:
CreateThread(NULL, 0, ThreadFunc, pWnd, NULL, 0).  I think that the windows message I'm passing in the thread should close the child window.

 

by: IbanUlovPosted on 2009-10-19 at 17:33:17ID: 25610109

It is easy, just cast it.

DWORD WINAPI ThreadFunc(LPVOID pParam)
{
      HWND  pWnd = (HWND) pParam;
      pWnd->DoThis();
      pWnd->PostMessage(OK);
      return 0;
}

 

by: dhenderson12Posted on 2009-10-19 at 18:49:22ID: 25610477

thanks.  I cast it like you suggested, but I get and error that DoThis() is not a member of HWND.

 

by: jaime_olivaresPosted on 2009-10-19 at 19:52:39ID: 25610746

I would use the following:

DWORD WINAPI ThreadFunc(LPVOID pParam)
{
      CWnd *pWnd = CWnd::FromHandle(pParam);
      pWnd->DoThis();
      pWnd->PostMessage(OK);
      return 0;
}

 

by: jaime_olivaresPosted on 2009-10-19 at 20:03:01ID: 25610788

sorry, maybe you will need a cast like:


      CWnd *pWnd = CWnd::FromHandle( (HWND ) pParam);

 

by: pgnatyukPosted on 2009-10-19 at 21:35:26ID: 25611084

Create thread as CreateThread(NULL, 0, ThreadFunc, this, NULL, 0)

and then in the thread you can write:

CMyDlg* pDlg = (CMyDlg*)pParam;

pDlg0>DoSomethign();

DoSomething is a method in CMyDialog (or whatever is the name of your dialog).

 

 

by: AndyAinscowPosted on 2009-10-19 at 23:04:32ID: 25611341

MFC is NOT thread safe.  Trying to access MFC window pointers betweeen threads can lead to crashes, you need to pass the HWND into the thread.

eg. (pseudo code)

//We start thread now
CreateThread(... (LPVOID)GetSafeHwnd());


in the thread
HWND hWndOwner = (HWND)pParam;
::PostMessage(hWndOwner, MY_MESSAGE, 0, 1);

 

by: IbanUlovPosted on 2009-10-20 at 12:29:33ID: 25617561

You can pass to the thread whatever you want. You pass a pointer to the data you want. You have to take care with you pass, if you pass a pointer, this pointer must be valid while the thread is running, you have to take care how you access to the variables if any other thread is accessing to this pointers... normal issues when you work with multi-thread.

 

by: DanRollinsPosted on 2009-10-20 at 15:07:30ID: 25619159

You can also create a global variable.  I usually don't recommand that, but it's the first, simplest way to get something running.  

Of course, as I've stated before, your DoSomething() function must completely avoid interacting with the U/I or this entire house of cards will collapse.  You'll wonder why it asserts and crashes and locks up.

 

by: jaime_olivaresPosted on 2009-10-20 at 15:46:27ID: 25619414

Also you can use the plain HWND value and use ::PostMessage(), but all actions will be asynchronous. PostMessage will return inmediately after posting the message and will not wait for a response.

 

by: itsmeandnobodyelsePosted on 2009-10-21 at 10:30:16ID: 25626223

>>>> You can also create a global variable.  I usually don't recommand that ...
Why here? As far as I see it is not a problem to pass the HWND of the dialog when creating the thread.

Global variables are not so simple as you need to know where to declare extern and where to define it. Static class members which are global as well, mostly is the fastest and easiest, but if using complex classes you might get problems with the order static class members were initialized. What really works, even beyond dll boundaries, is to have a static member function which provides a static object.

  class Global
  {
      public:
         static SharedObjectClass & getSharedObject()
         {
              static SharedObjectClass soc;
              return soc;
         }
  };

With that everyone from any thread could call

   Global::getSharedObject()

to retrieve a reference to the one soc instance defined in the static class member function.

But, I wouldn't recommend it in that case here where HWND easily could be passed as argument to the thread function.


 

by: dhenderson12Posted on 2009-10-24 at 18:22:08ID: 25655128

if I use:
 CreateThread(... (LPVOID)GetSafeHwnd());
isn't this getting  the safe handle to the current window?  I need to get the handle to the child window whose function I'm trying to call in the thread.

I tried the suggestions but so far none of them have worked for me.  do I need to use CWinThread?  I am definitely NOT understanding ...

 

by: pgnatyukPosted on 2009-10-24 at 22:25:02ID: 25655623

(LPVOID)GetSafeHwnd());

You said you need a child window. So pass the handle of the child window. Do you need this window handle for what? To send a message, to notify about something?

Now it differs from the original question - there was a dialog and you wanted to call its method from the thread and post a message.

Use this pointer as a parameter for CreateThread:
CreateThread(... (LPVOID)this);

Or pointer to the child window.
CreateThread(... (LPVOID)&childDlg);

Then in the thread:
CMyDialog* pDlg = (CMyDialog*)pParam;

Then if you need the window handle:
pDlg->GetSafeHwnd();

if you need a method:
pDlg->DoIt();

When you will have a sharing violation problem - you will think about it. Till that moment, do not complicate anything, do not confuse yourself. Probably, it will be very easy to add a simple synchronization mechanism. For example instead of pDlg->DoIt, post a message to the window and window will call DoIt().







 

by: itsmeandnobodyelsePosted on 2009-10-25 at 00:42:53ID: 25655856

>>>> isn't this getting  the safe handle to the current window?  I need to get the handle to the child window whose function I'm trying to call in the thread.

As pgnatyuk told, it normally is better to NOT calling functions for windows objects that were manged in the main thread. Instead send a message


// thread.cpp

void threadFunc(void * param)
{

     ...
     if (condition_to_send_a_message_back == true)
     {
             LPARAM   lp = (LPARAM)any32bitinfo1;
             WPARAM wp = (WPARAM)any32bitinfo2;
             PostMessage((HWND)param, WM_USER + MY_MSG_FROM_THREAD_1, lp, wp);
                                       
     }
}

The MY_MSG_FROM_THREAD_1 should be globally defined. It is supposed to make the message id unique. The PostMessage has two additional 32bit arguments, which you could use e. g. for pointing to an index in a container or even pass a pointer to a structure with additional information.

You handle (receive) the message in the main thread (GUI thread) in that class where the windows handle passed to the worker thread is from. That normally would be the dialog where the control you want to fill is into and not the control itself (even if you have derived from).

Always try to not wagging the dog with the tail but otherway round ;-)


// mydialog.cpp


....

BEGIN_MESSAGE_MAP (MyDialog, CDialog)
      ....
      ON_MESSAGE(WM_USER + MY_MSG_FROM_THREAD_1, MyDialog::OnHandleMsgFromThread1)
END_MESSAGE_MAP
 
The OnHandleMsgFromThread1 has was implemented like

LRESULT MyDialog::OnHandleMsgFromThread1(WPARAM wParam, LPARAM lParam)
{
   // Handle message here.

   return 0;
}


 

by: AndyAinscowPosted on 2009-10-25 at 00:44:15ID: 25655864

MFC is NOT thread safe.  Trying to access MFC window pointers betweeenthreads can lead to crashes, you need to pass the HWND into the thread.

eg. (pseudo code)

//We start thread now
CreateThread(... (LPVOID)GetSafeHwnd());


in the thread function

//Perform the calculation  (eg. the DoIt you currently have coded in the dialog)

//Now in the thread you inform the dialog that the calcualtion is finished.
HWND hWndOwner = (HWND)pParam;
::PostMessage(hWndOwner, MY_MESSAGE, 0, 1);




If you need to share more data then make a struct or class and pass that as the parameter into the thread.  A member of the struct/class is the HWND of the dialog to receive the message.
<!-- richText -->
       
             

 

by: itsmeandnobodyelsePosted on 2009-10-25 at 01:02:11ID: 25655908

>>>> isn't this getting  the safe handle to the current window?  

FYI: a pointer to a CWnd (or to a CWnd derived class like CDialog) is only loosely coupled with its window handle. The HWND is the *real* windows handle the operation system uses as an identifier for a currently created window (visible or not). The pointer points to a temporary MFC class object which was *attached* to the physical window in two ways: first, the CWnd (base) class holds the windows handle in the member m_hWnd. Second, Windows stores a function pointer to a so-called WindowsProc with the windows handle (::SetWindowLong is the function how to store additional information to a HWND). The function later was used to handle (or better dispatch) messages directed to the window.

If you have a CWnd pointer and call GetSafeHWnd(), you will get the real windows handle for that CWnd (i. e. the m_hWnd) if the m_hWnd was valid. In an initial phase where the CWnd wasn't attached the m_hWnd might be NULL. In a later phase where the window already was detached or even destroyed, the m_hWnd is invalid. In both cases the CWnd::GetSafeHWnd would return a valid pseudo handle which is valid (safe) though not very useful. But the PostMessage call wouldn't assert when using that handle.

If using a handle that was passed to a thread as parameter when creating the thread, you always must make sure that the window associated with the handle lives at least so long as the thread. If for example you closed the dialog (or let close it by the user) that started the thread before it returns some results and didn't terminate the thread somehow before the windows were destroyed, the thread my use the above PostMessage call and that call will assert in debug mode because the HWND used no longer is valid.

 

by: dhenderson12Posted on 2009-10-25 at 08:29:03ID: 25656911

Here is my thread function
DWORD WINAPI ThreadFunc(LPVOID pParam)
{
      CChildDialog *pDlg = (CChildDialog*) pParam;
      pDlg->GetSafeHwnd();
      pDlg->DoThis();
      return 0;
}

The child dialog is defined as CChildDialog m_childDialog

Here is my creating the thread:
CreateThread(NULL, 0, ThreadFunc, (LPVOID)&m_childDialog , NULL, 0);

This causes an assert error after which a general windows error.  The other suggestions give me a compile error that DoThis() is not a member of pDlg.  This is where I'm stuck.  

A dumb question:  if I send a windows message to the child dialog to run its own function, will that function still be running in the thread I created?

 

by: pgnatyukPosted on 2009-10-25 at 08:40:48ID: 25656940

So where is DoThis? This method exists in CChildDialog?
Method GetSafeHwnd() gives HWND. Now I don't see why you need it. If you need to send a message to this dialog you can say: pDlg->PostMessage(...)

Next issue:
It will be great if you will be sure that the data-members used DoThis method are not used somewhere else. At least while the thread works.

 

by: dhenderson12Posted on 2009-10-25 at 08:57:40ID: 25656987

1. DoThis() is a function in the CChildDialog().  
2. The data members of DoThis are not used anywhere else,  they are simply loading values into combo boxes on the CChildDialog.
3. The thread DOES NOT work.  It causes an application crash.  I haven't been able to get the thread to work at all yet.

 

by: AndyAinscowPosted on 2009-10-25 at 09:24:58ID: 25657092

>>A dumb question:  if I send a windows message to the child dialog torun its own function, will that function still be running in the threadI created?A dumb question:  if I send a windows message to the child dialog to run its own function, will that function still be running in the thread I created?

That is not a dumb question - yes, it defeats the threading.  You perform the work in the thread and inform the dialog (owner) of progress/results/status whatever.

 

by: pgnatyukPosted on 2009-10-25 at 10:57:32ID: 25657458

>> 1. DoThis() is a function in the CChildDialog().
But you said that the compiler says DoThis is not a member of CChildDialog.
So you forget #include "ChildDialog.h"?

>>2. The data members of DoThis are not used anywhere else, they are simply loading values into combo boxes on the CChildDialog.

It is exactly the worst case. The thread is loading a data into the visual controls that are drawn in the same time.
How many data do you load? Can you load it into an internal array or arrays? Make these controls disable for the loading time?

>> 3. The thread DOES NOT work. It causes an application crash. I haven't been able to get the thread to work at all yet.

if it does not work, so why the application crashes? Do not create the thread (cooment CreateThread call), and check it the application does not crash.
Second test, call CreateThread (uncomment the CreateThread call) but wait till the thread hadnle will becoma signaled - it means the thread has finished.

HANDLE hThread = CreateThread();
DWORD nWait = WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
//the thread stopped

You need to be sure that these two tests works in your application. Then you can continue.

 

by: AndyAinscowPosted on 2009-10-25 at 11:10:07ID: 25657503

Here is my thread function
DWORD WINAPI ThreadFunc(LPVOID pParam)
{
     CChildDialog *pDlg = (CChildDialog*) pParam;
     pDlg->GetSafeHwnd();
     pDlg->DoThis();
     return 0;
}


and
The data members of DoThis are not used anywhere else,  they are simply loading values into combo boxes on the CChildDialog.



To repeat myself.
MFC is NOT thread safe.  Trying to access MFC window pointers betweeenthreads can lead to crashes.

You say you experience a crash - the reason why?  It sounds like you are attempting to manipulate MFC window contents directly from a different thread.  MFC then attempts to get thread specific information which is garbage (because of two threads) and then promptly blows up.

As I mentioned earlier wrap data inside another object (struct or class), pass that to the thread, process that then inform the dialog the processing is finished.

 

by: itsmeandnobodyelsePosted on 2009-10-25 at 11:34:13ID: 25657590

>>>> pDlg->GetSafeHwnd();
That statement is totally unnecessary.

>>>> pDlg->DoThis();
That causes the crash. Replace that by

   pDlg->PostMessage(WM_USER+1234, 0, 0);

and call the DoThis in the handler for message WM_USER+1234 as showed above.

 

by: DanRollinsPosted on 2009-10-25 at 14:53:32ID: 25658557

With PostMessage, the message will be processed by the main (U/I) thread.  That will possibly prevent crashes, but it seems to be counter to the desires of the Asker.  Why start a thread to post a single message and then end?

The whole idea of running a thread to handle a dialog is doomed to failure.  We have provided many good ideas in other of  dhenderson12's questions, yet he persists.  I think it is time to simply say:  

Your multi-threaded approach will not work.  Would you like some help in solving the actual problem in a way that does not use multiple threads?

 

by: dhenderson12Posted on 2009-10-27 at 18:40:07ID: 25679329

I would absolutely love a a way to do this without threads.

 

by: DanRollinsPosted on 2009-10-27 at 20:17:42ID: 25679728

From your previous question, the problem is this:

1.  I have a main dialog, a child dialog, and a "splash" dialog for the child dialog.
2.  The child form is created on the OnInitDialog method of the main dialog and it's set to be hidden ( ShowWindow(0) ).
3.  When it's time to show the child dialog, from a button event, I set m_childDialog.ShowWindow(1) which shows the chld dialog and the child dialog "splash" dialog which is set to be a child of the child dialog and is visible, so in the OnInitDialog of the child dialog I have m_Splash.ShowWindow(1) .
4.  The main dialog calls a method of the child dialog to load its data which, in turn, is loaded into a group of controls on the child dialog.
5.  THE PROBLEM:  The  "splash" dialog has an animated gif image, but the animation doesn't work until the method that is retrieving the data and loading the child dialog is complete, after which I will close, or hide, the splash dialog.

------------
So the problem is that the animated gif is not displaying animation.  Is that correct?

When I asked you how you displayed the animated gif, you said :

>>The animated gif is loaded into a static picture control, same as a bitmap.  

But I know of no direct way to load an animated gif into a static control.  So there must be more to the story.  I need to know the "more."

I also asked you about what was causing the load-time delay in the other dialog.  (step 4) but you did not respond.  I need to know more about that delay -- what is taking so long in the other dialog?

I can solve this problem for you.  We will discard the entire idea of a secondary thread.  But you will need to tell me everything that I need to know.

-- Dan

P.S.  are you able ZIP up the entire project and attach it here?  Doing so would probably be the fastest route to a solution.

 

by: AndyAinscowPosted on 2009-10-27 at 23:28:46ID: 25680388

OK, poor mans multithreading (because it isn't multithreading, just looks a bit like it).

CMyDlg::LongOperation()
{
for(int i = 10000; i; i--)
 {
   DoSomething();
   DoEvents();  //give interface a chance to update
 }
}

void CMyDlg::DoEvents()
{  
   MSG msg;  
   while ( ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE ) )
   {  
       ::TranslateMessage(&msg);
       ::DispatchMessage(&msg);
   }
}

 

by: itsmeandnobodyelsePosted on 2009-10-27 at 23:55:19ID: 25680512

>>>> but the animation doesn't work until the method that is retrieving the data and loading the child dialog is complete, after which I will close, or hide, the splash dialog

Dan, probably 'retrieving the data and loading the child dialog' is good enough an answer to your q. "what is taking so long in the other dialog?"

>>>> I would absolutely love a a way to do this without threads.
How long will the retrieving of data last on average? Milliseconds? Seconds? Minutes?

DHenderson12, do you see a way to do the retrieval in steps where each step won't last more than - say - half a second? If not, there is no suitable way to perform that step within the modal message loop of the main thread without freezing the screen (or not displaying the animation) cause no messages were processed while you you do the lengthy operation.

>>>> Why start a thread to post a single message and then end?
The thread was supposed to do the lengthy operation, i. e. retrieve the data, what then would be done asynchronously. The PostMessage only is to send the progress notification to the dialog.

 

by: AndyAinscowPosted on 2009-10-28 at 00:03:32ID: 25680539

IF the problem is your animation then the best solution (as I recommended in the other question and which you said you had an example for) is a UI thread to have the dialog with the animation.

 

by: dhenderson12Posted on 2009-10-28 at 16:01:34ID: 25689178


Here is the the splash screen with the animated .gif file.  It is loaded into a static picture control via a helper class called PictureEx, which I downloaded from codeguru.com.

===========header file==============================
#pragma once
#include "afxwin.h"
#include "PictureEx.h"

// CSplash dialog

class CSplash : public CDialog
{
      DECLARE_DYNCREATE(CSplash)

public:
      CSplash(CWnd* pParent = NULL);   // standard constructor
      virtual ~CSplash();

// Dialog Data
      enum { IDD = IDD_SPLASH_LOADING };

protected:
      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
      virtual BOOL OnInitDialog();

      DECLARE_MESSAGE_MAP()
public:
      CPictureEx m_Spinner;

};

=================class file ================================
// Splash.cpp : implementation file
//

#include "stdafx.h"
#include "VSSAAdmin.h"
#include "Splash.h"
#include "ReportOptions.h"

// CSplash dialog

IMPLEMENT_DYNCREATE(CSplash, CDialog)

CSplash::CSplash(CWnd* pParent /*=NULL*/)
      : CDialog(CSplash::IDD, pParent)
{

}

CSplash::~CSplash()
{
}

void CSplash::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      DDX_Control(pDX, IDC_SPINNER, m_Spinner);
}


BEGIN_MESSAGE_MAP(CSplash, CDialog)
END_MESSAGE_MAP()


// CSplash message handlers

BOOL CSplash::OnInitDialog()
{
      CDialog::OnInitDialog();

      if (m_Spinner.Load(_T("spinner_arrows.gif")))
    m_Spinner.Draw();
      
      return TRUE;
}
=========================================================

The child dialog is created on the OnInitDialog() method of the main dialog, the splash screen is created on the OnInitDialog() method of the child dialog.  I then
turn the child dialog form visible or invisible when I need it.

There is a public method in the child dialog called DoThis().  It reads and parses an xml file, loading a group of combo boxes on the child dialog as it's parsing the file.  

The DoThis() method is called from the main form, when I decide to load the xml.  This is something that is initiated from a OnButtonClicked event on the parent form.

The whole idea here is to display the splash screen with the animated .gif while the xml is being parsed and loaded into the combo box  controls.

The load time delay, at the  moment, is only 3-4 seconds, but this will get longer as the data in the xml grows.  I also have this same scenario with a couple other data-loading methods that could take up to a minute or longer.

 

by: DanRollinsPosted on 2009-10-28 at 19:16:30ID: 25690114

Thank you for providing the information that is needed to solve this problem.

CPictureEx is a non-standard control. I presume that you obtained it here:
http://www.codeproject.com/KB/graphics/pictureex.aspx

It automatically creates and handles the additional thread used to animate the GIF.

I am recreating your scenario and will provide an answer soon.

 

by: DanRollinsPosted on 2009-10-28 at 20:00:24ID: 25690330

I was able to reproduce the problem.

I created a DoThis() function that simply calls Sleep(10000) and sure enough the animation stops. Although the PictureEx is faithfully updating the image (in its internal thread), the Splash dialog is not able to process the WM_PAINT messages that are being sent to it.

This is a variation of a very common problem. And there is a simple solution:

Add the attached function to your CChildDlg dialog, just above your DoThis function.

Turn your attention to the DoThis function. You will need to periodically call
    PumpMsgs(10);
while DoThis() is running.

I don't have your source code, so I cant tell you exactly where to put it. You will need to try to find the inner loop of your XML parsing logic. If you can't find that, then you must insert that function where needed throughout the parsing code.

If you can't figure out how to do that, then please provide the source code you use in your XML parsing and I'll figure it out for you.

-- Dan

void PumpMsgs( int nMs )
{
    DWORD nMaxTick= GetTickCount()+ nMs;
 
    while ( GetTickCount() < nMaxTick ) {
        MSG msg;
        while ( ( GetTickCount() < nMaxTick ) 
           && (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) 
        ) {
            AfxGetApp()->PumpMessage();  // does a ::GetMessage()
        }
    } 
}
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:

Select allOpen in new window

 

by: itsmeandnobodyelsePosted on 2009-10-28 at 23:44:42ID: 25691132

>>>> You will need to try to find the inner loop of your XML parsing logic.

Why not moving *all* the XML parsing to the thread we already have?

The proposed *method* to process messages in an inner loop while doing some lengthy operation often has some negative side effects. E. g. that some menus are open which may allow the user to quit from the current dialog or switch to somewhere else or invoke the current action again, with unknown consequences.

I have very bad experiences using functions like the PumpMsgs, including crashes when the User closed (and destroyed) the current dialog while the running loop still tried to use the deleted dialog pointer.

 

by: AndyAinscowPosted on 2009-10-29 at 00:27:41ID: 25691243

I agree with itsmeandnobodyelse - you have a bad design.

As I said earlier you should do the lengthy processing in the thread function (parse the XML file) and let the main app handle the interface.
Make a class or struct that contains as member variables the following:
HWND of the main dialog
CStringArray - one per combo box with the information you extract from the XML file

In the main dialog you have a member variable which is this new class/struct and you pass that as the param into the thread function.
The thread parses the XML file, fills in the arrays with the information you require
When it is done it posts a message back to the dialog to inform it the task is done.
The dialog, on receipt of the message, fills the combo boxs with the information in the arrays inside this class/struct.

 

by: DanRollinsPosted on 2009-10-29 at 03:25:38ID: 25692068

Do you guys realize that you are confusing this poor guy beyond belief?  You've been trying to talk him through a multi-threaded approach for nearly two weeks.  And he still can't get how to pass a CWnd* from one function to another.

The best way for this particular user to solve this particular problem is to take the simple (single-threaded) route.

 

by: itsmeandnobodyelsePosted on 2009-10-29 at 03:26:12ID: 25692072

dhenderson12,

I am sorry that you have to decide between two different approaches where we experts don't have a common view on.

But both Dan for his one-thread-design and Andy and me for our worker-thread-design, would need the code where you load the xml. If you would post it here, you probably will get two working solutions where you later can decide which one suits better to your needs.

 

by: itsmeandnobodyelsePosted on 2009-10-29 at 03:36:33ID: 25692152

>>> Do you guys realize that you are confusing this poor guy beyond belief?  
Dan, I don't know your reasons why you think a single-threaded is simpler. IMO it is not, and the multi-threading itself is *NOT* the problem here as the CreateThread and thread function already exists.

Did you think about that your (new) approach and the hopes you may have arised by dhenderson12 by your recent posts could have added some part to the confusion?

 

by: DanRollinsPosted on 2009-10-29 at 15:08:14ID: 25698748

I decided to take that risk when it became clear that the other methods were not going to work for this member in this situation.  He does not need the best solution.  He first needs one that he can understand and implement with little code.

 

by: itsmeandnobodyelsePosted on 2009-10-29 at 17:16:14ID: 25699350

>>>> He first needs one that he can understand and implement with little code.

Don't think you can/should force your way in a question titled "passing the HWND of a mfc dialog to the CreateThread function".

@dhenderson12, as told you can decide how to go on.

If you would post your loading function, you surely would get all help needed to put it into the thread and exchange results and progress info with the main dialog and finally stop the animation.

If you want to go the single-threaded way Dan was proposing, you better close that thread and ask a new follow-up question. You may accept any of the earlier comments then which was an answer to the q. asked.

 

by: DanRollinsPosted on 2009-10-30 at 00:07:33ID: 25700613

I guess it all depends on whether dhenderson12 wants an answer to his question or a solution to his problem...

 

by: AndyAinscowPosted on 2009-10-30 at 00:30:20ID: 25700722

>>I guess it all depends on whether dhenderson12 wants an answer to his question or a solution to his problem...


For me the solution to his problem would actually answer the question and involve getting the thread to work correctly.  A single threaded 'solution' IMHO is more of a hack to make it work rather than a solution, especially as this should be trivial - he already has the code, just in the wrong place and not quite complete enough.


 

by: dhenderson12Posted on 2009-11-02 at 18:37:35ID: 25725667

Gentlemen, thank you all for your help.  You have given me multiple approaches to this problem which I am attempting to implement to see which works best, although I'm leaning to threading, which is really where I wanted to go in the first place.

I am splitting the points among you all for all the effort.  Thanks again.

 

by: DanRollinsPosted on 2009-11-02 at 19:56:00ID: 25725937

If you decide to use multi-threading, you should check out this article:

   Create a Dialog in its Own Thread
   http://www.experts-exchange.com/A_1886.html

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...