CWnd-derived class, VC6SP6, Invalid m_hWnd

I'm trying to create a class that will derive from CWnd so that it can
have a message map, however it does not need to display anything.  This
class will be a member of a CWnd-derived object (CChildView) (not using
Document/View), and will simply be a target for posting messages to from
various code in the application.  The class declaration is as follows:

#define WM_ALERT (WM_USER+1)
class MyWnd : public CWnd {
public:
	afx_msg LRESULT OnAlert(WPARAM w, LPARAM l);
	DECLARE_MESSAGE_MAP()
};

The implementation for this class is as follows:

BEGIN_MESSAGE_MAP(MyWnd, CWnd)
	ON_MESSAGE(WM_ALERT, OnAlert)
END_MESSAGE_MAP()

LRESULT MyWnd::OnAlert(WPARAM w, LPARAM, l) {
	::MessageBox(NULL,
		_T("Message was successfully posted and dispatched."),
		_T("Test Event"),
		MB_OK | MB_ICONINFORMATION);
	return 0;
}

The view declaration is as follows:

class CChildView : public CWnd
{
// Construction
public:
	CChildView();

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CChildView)
	protected:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CChildView();

	// Generated message map functions
protected:

	MyWnd m_MyObj;

	virtual void OnInitialUpdate(); // called first time after construct

	//{{AFX_MSG(CChildView)
	afx_msg void OnPaint();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

I am using the OnInitialUpdate() member to create the window as follow:

void CChildView::OnInitialUpdate() {
	// IDC_OBJ_MINE is a resource ID in resource.h
	// and is unique.
	BOOL bResult = m_MyObj.Create(NULL, NULL, WS_CHILD,
		CRect(0, 0, 100, 100),
		this, IDC_OBJ_MINE);
	if (!bResult) {
		::MessageBox(NULL,
			_T("Unable to create child window instance."),
			_T("Stupid Thing(tm) anyway..."),
			MB_OK | MB_ICONSTOP);
	}
	if (m_MyObj.GetSafeHwnd() == NULL) {
		CString ErrMsg;
		ErrMsg.Format(
			_T("No HWND is present in child (Error %d)"),
			GetLastError());

		::MessageBox(NULL,
			(LPCTSTR)ErrMsg,
			_T("Stupid Thing(tm) anyway..."),
			MB_OK | MB_ICONSTOP);
	}
}

When the application runs, the call to CWnd::Create() succeeds, however
the message appears indicating that the m_hWnd/GetSafeHwnd() value is
NULL, and GetLastError() returns 0.  Of course, since I get no HWND I am
not able to post messages to the object.  Is it possible to create
so-called "invisible" windows like this, and am I missing something
fundamental in the creation of a CWnd-based child class?

Thank you all for your efforts and suggestions!

Jason
0
5/31/2006 5:21:02 PM
vc.mfc 33608 articles. 0 followers. Follow

3 Replies
674 Views

Similar Articles

[PageSpeed] 17

Yes, it is possible to create an invisible window like this. As I understand 
it, Create is returning TRUE. I'm not sure exactly why it would then have no 
window handle. What I would do is step through the Create call and see when 
it creates the actual window. Shouldn't be that hard to figure out why 
m_hWnd would be NULL but it still returns TRUE.

-- 
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com

"Jason Tost" <no-spam-32-jason@aspenmt.com> wrote in message 
news:uL6fYaNhGHA.3956@TK2MSFTNGP02.phx.gbl...
> I'm trying to create a class that will derive from CWnd so that it can
> have a message map, however it does not need to display anything.  This
> class will be a member of a CWnd-derived object (CChildView) (not using
> Document/View), and will simply be a target for posting messages to from
> various code in the application.  The class declaration is as follows:
>
> #define WM_ALERT (WM_USER+1)
> class MyWnd : public CWnd {
> public:
> afx_msg LRESULT OnAlert(WPARAM w, LPARAM l);
> DECLARE_MESSAGE_MAP()
> };
>
> The implementation for this class is as follows:
>
> BEGIN_MESSAGE_MAP(MyWnd, CWnd)
> ON_MESSAGE(WM_ALERT, OnAlert)
> END_MESSAGE_MAP()
>
> LRESULT MyWnd::OnAlert(WPARAM w, LPARAM, l) {
> ::MessageBox(NULL,
> _T("Message was successfully posted and dispatched."),
> _T("Test Event"),
> MB_OK | MB_ICONINFORMATION);
> return 0;
> }
>
> The view declaration is as follows:
>
> class CChildView : public CWnd
> {
> // Construction
> public:
> CChildView();
>
> // Attributes
> public:
>
> // Operations
> public:
>
> // Overrides
> // ClassWizard generated virtual function overrides
> //{{AFX_VIRTUAL(CChildView)
> protected:
> virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
> //}}AFX_VIRTUAL
>
> // Implementation
> public:
> virtual ~CChildView();
>
> // Generated message map functions
> protected:
>
> MyWnd m_MyObj;
>
> virtual void OnInitialUpdate(); // called first time after construct
>
> //{{AFX_MSG(CChildView)
> afx_msg void OnPaint();
> //}}AFX_MSG
> DECLARE_MESSAGE_MAP()
> };
>
> I am using the OnInitialUpdate() member to create the window as follow:
>
> void CChildView::OnInitialUpdate() {
> // IDC_OBJ_MINE is a resource ID in resource.h
> // and is unique.
> BOOL bResult = m_MyObj.Create(NULL, NULL, WS_CHILD,
> CRect(0, 0, 100, 100),
> this, IDC_OBJ_MINE);
> if (!bResult) {
> ::MessageBox(NULL,
> _T("Unable to create child window instance."),
> _T("Stupid Thing(tm) anyway..."),
> MB_OK | MB_ICONSTOP);
> }
> if (m_MyObj.GetSafeHwnd() == NULL) {
> CString ErrMsg;
> ErrMsg.Format(
> _T("No HWND is present in child (Error %d)"),
> GetLastError());
>
> ::MessageBox(NULL,
> (LPCTSTR)ErrMsg,
> _T("Stupid Thing(tm) anyway..."),
> MB_OK | MB_ICONSTOP);
> }
> }
>
> When the application runs, the call to CWnd::Create() succeeds, however
> the message appears indicating that the m_hWnd/GetSafeHwnd() value is
> NULL, and GetLastError() returns 0.  Of course, since I get no HWND I am
> not able to post messages to the object.  Is it possible to create
> so-called "invisible" windows like this, and am I missing something
> fundamental in the creation of a CWnd-based child class?
>
> Thank you all for your efforts and suggestions!
>
> Jason 


0
jwood (1292)
5/31/2006 5:57:32 PM
Beware of using WM_USER messages; they are often preempted by Microsoft.  Use WM_APP
messages, or better still, Registered Window Messages.  See my essay on Message Management
on my MVP Tips site.

See below....

On Wed, 31 May 2006 11:21:02 -0600, Jason Tost <no-spam-32-jason@aspenmt.com> wrote:

>I'm trying to create a class that will derive from CWnd so that it can
>have a message map, however it does not need to display anything.  This
>class will be a member of a CWnd-derived object (CChildView) (not using
>Document/View), and will simply be a target for posting messages to from
>various code in the application.  The class declaration is as follows:
>
>#define WM_ALERT (WM_USER+1)
>class MyWnd : public CWnd {
>public:
>	afx_msg LRESULT OnAlert(WPARAM w, LPARAM l);
>	DECLARE_MESSAGE_MAP()
>};
>
>The implementation for this class is as follows:
>
>BEGIN_MESSAGE_MAP(MyWnd, CWnd)
>	ON_MESSAGE(WM_ALERT, OnAlert)
>END_MESSAGE_MAP()
>
>LRESULT MyWnd::OnAlert(WPARAM w, LPARAM, l) {
>	::MessageBox(NULL,
>		_T("Message was successfully posted and dispatched."),
>		_T("Test Event"),
>		MB_OK | MB_ICONINFORMATION);
>	return 0;
>}
>
>The view declaration is as follows:
>
*****
If this is really a view, in the doc/view sense, it must be derived from CView, not CWnd.
*****
>class CChildView : public CWnd
>{
>// Construction
>public:
>	CChildView();
>
>// Attributes
>public:
>
>// Operations
>public:
>
>// Overrides
>	// ClassWizard generated virtual function overrides
>	//{{AFX_VIRTUAL(CChildView)
>	protected:
>	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
>	//}}AFX_VIRTUAL
>
>// Implementation
>public:
>	virtual ~CChildView();
>
>	// Generated message map functions
>protected:
>
>	MyWnd m_MyObj;
>
>	virtual void OnInitialUpdate(); // called first time after construct
>
>	//{{AFX_MSG(CChildView)
>	afx_msg void OnPaint();
>	//}}AFX_MSG
>	DECLARE_MESSAGE_MAP()
>};
>
>I am using the OnInitialUpdate() member to create the window as follow:
>
>void CChildView::OnInitialUpdate() {
>	// IDC_OBJ_MINE is a resource ID in resource.h
>	// and is unique.
>	BOOL bResult = m_MyObj.Create(NULL, NULL, WS_CHILD,
>		CRect(0, 0, 100, 100),
>		this, IDC_OBJ_MINE);
>	if (!bResult) {
>		::MessageBox(NULL,
>			_T("Unable to create child window instance."),
>			_T("Stupid Thing(tm) anyway..."),
>			MB_OK | MB_ICONSTOP);
>	}
>	if (m_MyObj.GetSafeHwnd() == NULL) {
>		CString ErrMsg;
>		ErrMsg.Format(
>			_T("No HWND is present in child (Error %d)"),
>			GetLastError());
>
>		::MessageBox(NULL,
>			(LPCTSTR)ErrMsg,
>			_T("Stupid Thing(tm) anyway..."),
>			MB_OK | MB_ICONSTOP);
>	}
>}
>
>When the application runs, the call to CWnd::Create() succeeds, however
>the message appears indicating that the m_hWnd/GetSafeHwnd() value is
>NULL, and GetLastError() returns 0.  Of course, since I get no HWND I am
>not able to post messages to the object.  Is it possible to create
>so-called "invisible" windows like this, and am I missing something
>fundamental in the creation of a CWnd-based child class?
*****
I've done this many times in the way you show, or at least I'm not seeing any significant
difference between what you are doing and what I do.  You aren't setting WS_VISIBLE, you
are setting WS_CHILD, you are giving 'this' as the parent, and you have a control ID
(although IDC_STATIC might suffice; I don't know where you are using the IDC_OBJ_MINE
other than here).

The fact that the GetSafeHwnd() returns NULL is inconsistent with bResult being TRUE, so I
think there is a fairly serious problem here, but I have no idea short of doing a lot of
single-stepping through MFC exactly what went wrong.  What I'd first do is set a
breakpoint immediately after the Create and examine the m_hWnd using the debugger.  If it
is NULL at that point, I'd set a breakpoint at the AfxHookProc (or some similar function,
it has been a while since I've looked inside MFC at this level) to make sure the hook
function is being called.  Set a breakpoint at the Create call; when that breakpoint is
taken, set a breakpoint in the hook function.  The hook function is nominally what does
the binding of the HWND to the CWnd-derived object.  If the hook isn't called, I'd start
doing some serious single-stepping through Create looking for something strange.  Alas, I
can't point you any better than that.
				joe
****
>
>Thank you all for your efforts and suggestions!
>
>Jason
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15973)
5/31/2006 7:04:13 PM
Thank you very much for your feedback and suggestions.  The information
you gave is appreciated very much.  I will continue stepping through the
MFC source and checking values before and after the call to Create().

Again, I appreciate your assistance.

Best regards,
Jason

Joseph M. Newcomer wrote:
> Beware of using WM_USER messages; they are often preempted by Microsoft.  Use WM_APP
> messages, or better still, Registered Window Messages.  See my essay on Message Management
> on my MVP Tips site.
> 
> See below....
> 
> On Wed, 31 May 2006 11:21:02 -0600, Jason Tost <no-spam-32-jason@aspenmt.com> wrote:
> 
>> I'm trying to create a class that will derive from CWnd so that it can
>> have a message map, however it does not need to display anything.  This
>> class will be a member of a CWnd-derived object (CChildView) (not using
>> Document/View), and will simply be a target for posting messages to from
>> various code in the application.  The class declaration is as follows:
>>
>> #define WM_ALERT (WM_USER+1)
>> class MyWnd : public CWnd {
>> public:
>> 	afx_msg LRESULT OnAlert(WPARAM w, LPARAM l);
>> 	DECLARE_MESSAGE_MAP()
>> };
>>
>> The implementation for this class is as follows:
>>
>> BEGIN_MESSAGE_MAP(MyWnd, CWnd)
>> 	ON_MESSAGE(WM_ALERT, OnAlert)
>> END_MESSAGE_MAP()
>>
>> LRESULT MyWnd::OnAlert(WPARAM w, LPARAM, l) {
>> 	::MessageBox(NULL,
>> 		_T("Message was successfully posted and dispatched."),
>> 		_T("Test Event"),
>> 		MB_OK | MB_ICONINFORMATION);
>> 	return 0;
>> }
>>
>> The view declaration is as follows:
>>
> *****
> If this is really a view, in the doc/view sense, it must be derived from CView, not CWnd.
> *****
>> class CChildView : public CWnd
>> {
>> // Construction
>> public:
>> 	CChildView();
>>
>> // Attributes
>> public:
>>
>> // Operations
>> public:
>>
>> // Overrides
>> 	// ClassWizard generated virtual function overrides
>> 	//{{AFX_VIRTUAL(CChildView)
>> 	protected:
>> 	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
>> 	//}}AFX_VIRTUAL
>>
>> // Implementation
>> public:
>> 	virtual ~CChildView();
>>
>> 	// Generated message map functions
>> protected:
>>
>> 	MyWnd m_MyObj;
>>
>> 	virtual void OnInitialUpdate(); // called first time after construct
>>
>> 	//{{AFX_MSG(CChildView)
>> 	afx_msg void OnPaint();
>> 	//}}AFX_MSG
>> 	DECLARE_MESSAGE_MAP()
>> };
>>
>> I am using the OnInitialUpdate() member to create the window as follow:
>>
>> void CChildView::OnInitialUpdate() {
>> 	// IDC_OBJ_MINE is a resource ID in resource.h
>> 	// and is unique.
>> 	BOOL bResult = m_MyObj.Create(NULL, NULL, WS_CHILD,
>> 		CRect(0, 0, 100, 100),
>> 		this, IDC_OBJ_MINE);
>> 	if (!bResult) {
>> 		::MessageBox(NULL,
>> 			_T("Unable to create child window instance."),
>> 			_T("Stupid Thing(tm) anyway..."),
>> 			MB_OK | MB_ICONSTOP);
>> 	}
>> 	if (m_MyObj.GetSafeHwnd() == NULL) {
>> 		CString ErrMsg;
>> 		ErrMsg.Format(
>> 			_T("No HWND is present in child (Error %d)"),
>> 			GetLastError());
>>
>> 		::MessageBox(NULL,
>> 			(LPCTSTR)ErrMsg,
>> 			_T("Stupid Thing(tm) anyway..."),
>> 			MB_OK | MB_ICONSTOP);
>> 	}
>> }
>>
>> When the application runs, the call to CWnd::Create() succeeds, however
>> the message appears indicating that the m_hWnd/GetSafeHwnd() value is
>> NULL, and GetLastError() returns 0.  Of course, since I get no HWND I am
>> not able to post messages to the object.  Is it possible to create
>> so-called "invisible" windows like this, and am I missing something
>> fundamental in the creation of a CWnd-based child class?
> *****
> I've done this many times in the way you show, or at least I'm not seeing any significant
> difference between what you are doing and what I do.  You aren't setting WS_VISIBLE, you
> are setting WS_CHILD, you are giving 'this' as the parent, and you have a control ID
> (although IDC_STATIC might suffice; I don't know where you are using the IDC_OBJ_MINE
> other than here).
> 
> The fact that the GetSafeHwnd() returns NULL is inconsistent with bResult being TRUE, so I
> think there is a fairly serious problem here, but I have no idea short of doing a lot of
> single-stepping through MFC exactly what went wrong.  What I'd first do is set a
> breakpoint immediately after the Create and examine the m_hWnd using the debugger.  If it
> is NULL at that point, I'd set a breakpoint at the AfxHookProc (or some similar function,
> it has been a while since I've looked inside MFC at this level) to make sure the hook
> function is being called.  Set a breakpoint at the Create call; when that breakpoint is
> taken, set a breakpoint in the hook function.  The hook function is nominally what does
> the binding of the HWND to the CWnd-derived object.  If the hook isn't called, I'd start
> doing some serious single-stepping through Create looking for something strange.  Alas, I
> can't point you any better than that.
> 				joe
> ****
>> Thank you all for your efforts and suggestions!
>>
>> Jason
> Joseph M. Newcomer [MVP]
> email: newcomer@flounder.com
> Web: http://www.flounder.com
> MVP Tips: http://www.flounder.com/mvp_tips.htm
0
5/31/2006 8:53:28 PM
Reply:

Similar Artilces: