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
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
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
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