It is easy, just cast it.
DWORD WINAPI ThreadFunc(LPVOID pParam)
{
HWND pWnd = (HWND) pParam;
pWnd->DoThis();
pWnd->PostMessage(OK);
return 0;
}
Main Topics
Browse All TopicsI 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.
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.
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.
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.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
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.
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
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.
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.
>>>> 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.
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 ...
(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().
>>>> 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_messa
{
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::OnHandleMsgFromT
END_MESSAGE_MAP
The OnHandleMsgFromThread1 has was implemented like
LRESULT MyDialog::OnHandleMsgFromT
{
// Handle message here.
return 0;
}
>>>> 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.
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?
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.
>>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.
>> 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(hThrea
CloseHandle(hThr
//the
You need to be sure that these two tests works in your application. Then you can continue.
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.
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?
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
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.
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);
}
}
>>>> 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.
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(CDataExchan
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(CSplas
CSplash::CSplash(CWnd* pParent /*=NULL*/)
: CDialog(CSplash::IDD, pParent)
{
}
CSplash::~CSplash()
{
}
void CSplash::DoDataExchange(CD
{
CDialog::DoDataExchange(pD
DDX_Control(pDX, IDC_SPINNER, m_Spinner);
}
BEGIN_MESSAGE_MAP(CSplash,
END_MESSAGE_MAP()
// CSplash message handlers
BOOL CSplash::OnInitDialog()
{
CDialog::OnInitDialog();
if (m_Spinner.Load(_T("spinne
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.
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
It automatically creates and handles the additional thread used to animate the GIF.
I am recreating your scenario and will provide an answer soon.
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
>>>> 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.
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.
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.
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.
>>> 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?
>>>> 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.
>>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.
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.
If you decide to use multi-threading, you should check out this article:
Create a Dialog in its Own Thread
http://www.experts-exchang
Business Accounts
Answer for Membership
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.