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