W
William Payne
Hello, consider these following two classes. A base class, class
MDIChildWindow, and a class inherting from that base class, class Document.
In the static base member function callback() I obtain a pointer to the
child class and call the function on_mdiactivate() using this pointer. For
some reason, the program executes MDIChildClass:n_mdiactivate() and not
Document:n_mdiactivate(). Why? on_mdiactivate() is a virtual function in
MDIChildClass and I have redefined that function in the child class
Document. The code contains some non-standard code (Win32-API), but, I hope
and think, it's not an API problem I have but a problem with my classes. I
hope you can disregard from the non-standard code, and help me solve this
problem. If you can't I apologise and will try to create an example using
only standard c++ that behaves exactly the same.
The code:
/* mdi_child_window.hpp */
#ifndef MDI_CHILD_WINDOW_HPP
#define MDI_CHILD_WINDOW_HPP
#include <windows.h>
#include <cassert>
#include <cstring>
#include <stdexcept>
class MDIChildWindow
{
public:
MDIChildWindow(HWND mdi_client_window,
const char* const title,
long lparam);
virtual ~MDIChildWindow()
{
delete [] m_title;
}
static long CALLBACK dummy_callback(HWND mdi_child_window,
unsigned int message,
unsigned int wparam,
long lparam);
protected:
virtual long on_mdiactivate(unsigned int /*wparam*/, long /*lparam*/)
{
return 0;
}
static const char* const m_mdi_child_class_name;
HWND m_frame_window; /* Maybe make static? */
HWND m_mdi_client_window; /* Maybe make static? */
HWND m_mdi_child_window;
char* m_title;
};
#endif /* #ifndef MDI_CHILD_WINDOW_HPP */
/* mdi_child_window.cpp */
#include "mdi_child_window.hpp"
#include "document.hpp"
using std::runtime_error;
using std::strcpy;
using std::strlen;
const char* const MDIChildWindow::m_mdi_child_class_name =
"MDIChildWindowClass";
MDIChildWindow::MDIChildWindow(HWND mdi_client_window,
const char* const title,
long lparam)
:
m_mdi_client_window(mdi_client_window)
{
m_title = new char[strlen(title) + 1];
strcpy(m_title, title);
m_frame_window = GetParent(m_mdi_client_window);
m_mdi_child_window = CreateMDIWindow(
m_mdi_child_class_name,
m_title,
WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU |
WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
mdi_client_window,
GetModuleHandle(NULL),
lparam /* Contains a pointer-to-class-Document */
);
assert(m_mdi_child_window);
if(!m_mdi_child_window)
{
unsigned long error = GetLastError();
char format_msg_str[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
0,
format_msg_str,
sizeof(format_msg_str),
NULL);
MessageBox(m_frame_window, format_msg_str, "Error", MB_OK |
MB_ICONERROR);
delete [] m_title;
}
}
long CALLBACK
MDIChildWindow::dummy_callback(HWND mdi_child_window,
unsigned int message,
unsigned int wparam,
long lparam)
{
switch(message)
{
case WM_NCCREATE:
{
CREATESTRUCT* cs = (CREATESTRUCT*)lparam;
MDICREATESTRUCT* mdics = (MDICREATESTRUCT*)cs->lpCreateParams;
Document* p = (Document*)mdics->lParam;
assert(p);
SetWindowLongPtr(mdi_child_window, GWLP_USERDATA, (long)p);
return 1;
}
case WM_MDIACTIVATE:
{
Document* p = (Document*)GetWindowLongPtr(mdi_child_window,
GWLP_USERDATA);
assert(p);
return p->on_mdiactivate(wparam, lparam);
}
default:
{
return DefMDIChildProc(mdi_child_window,
message,
wparam,
lparam);
}
}
}
/* document.hpp */
#ifndef DOCUMENT_HPP
#define DOCUMENT_HPP
#include "globals.hpp"
#include "mdi_child_window.hpp"
class Document : public MDIChildWindow
{
public:
Document(HWND mdi_client_window,
const char* const title);
const HWND get_handle() const
{
return m_mdi_child_window;
}
virtual long on_mdiactivate(unsigned int wparam, long lparam);
private:
HWND m_frame_window;
};
#endif
/* document.cpp */
#include "document.hpp"
Document:ocument(HWND mdi_client_window,
const char* const title)
:
MDIChildWindow(mdi_client_window, title, (long)this)
{
;
}
/* This function is not called! Why?? */
long Document:n_mdiactivate(unsigned int /*wparam*/, long lparam)
{
// do something more than just return 0
return 0;
}
/ WP
MDIChildWindow, and a class inherting from that base class, class Document.
In the static base member function callback() I obtain a pointer to the
child class and call the function on_mdiactivate() using this pointer. For
some reason, the program executes MDIChildClass:n_mdiactivate() and not
Document:n_mdiactivate(). Why? on_mdiactivate() is a virtual function in
MDIChildClass and I have redefined that function in the child class
Document. The code contains some non-standard code (Win32-API), but, I hope
and think, it's not an API problem I have but a problem with my classes. I
hope you can disregard from the non-standard code, and help me solve this
problem. If you can't I apologise and will try to create an example using
only standard c++ that behaves exactly the same.
The code:
/* mdi_child_window.hpp */
#ifndef MDI_CHILD_WINDOW_HPP
#define MDI_CHILD_WINDOW_HPP
#include <windows.h>
#include <cassert>
#include <cstring>
#include <stdexcept>
class MDIChildWindow
{
public:
MDIChildWindow(HWND mdi_client_window,
const char* const title,
long lparam);
virtual ~MDIChildWindow()
{
delete [] m_title;
}
static long CALLBACK dummy_callback(HWND mdi_child_window,
unsigned int message,
unsigned int wparam,
long lparam);
protected:
virtual long on_mdiactivate(unsigned int /*wparam*/, long /*lparam*/)
{
return 0;
}
static const char* const m_mdi_child_class_name;
HWND m_frame_window; /* Maybe make static? */
HWND m_mdi_client_window; /* Maybe make static? */
HWND m_mdi_child_window;
char* m_title;
};
#endif /* #ifndef MDI_CHILD_WINDOW_HPP */
/* mdi_child_window.cpp */
#include "mdi_child_window.hpp"
#include "document.hpp"
using std::runtime_error;
using std::strcpy;
using std::strlen;
const char* const MDIChildWindow::m_mdi_child_class_name =
"MDIChildWindowClass";
MDIChildWindow::MDIChildWindow(HWND mdi_client_window,
const char* const title,
long lparam)
:
m_mdi_client_window(mdi_client_window)
{
m_title = new char[strlen(title) + 1];
strcpy(m_title, title);
m_frame_window = GetParent(m_mdi_client_window);
m_mdi_child_window = CreateMDIWindow(
m_mdi_child_class_name,
m_title,
WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU |
WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
mdi_client_window,
GetModuleHandle(NULL),
lparam /* Contains a pointer-to-class-Document */
);
assert(m_mdi_child_window);
if(!m_mdi_child_window)
{
unsigned long error = GetLastError();
char format_msg_str[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
0,
format_msg_str,
sizeof(format_msg_str),
NULL);
MessageBox(m_frame_window, format_msg_str, "Error", MB_OK |
MB_ICONERROR);
delete [] m_title;
}
}
long CALLBACK
MDIChildWindow::dummy_callback(HWND mdi_child_window,
unsigned int message,
unsigned int wparam,
long lparam)
{
switch(message)
{
case WM_NCCREATE:
{
CREATESTRUCT* cs = (CREATESTRUCT*)lparam;
MDICREATESTRUCT* mdics = (MDICREATESTRUCT*)cs->lpCreateParams;
Document* p = (Document*)mdics->lParam;
assert(p);
SetWindowLongPtr(mdi_child_window, GWLP_USERDATA, (long)p);
return 1;
}
case WM_MDIACTIVATE:
{
Document* p = (Document*)GetWindowLongPtr(mdi_child_window,
GWLP_USERDATA);
assert(p);
return p->on_mdiactivate(wparam, lparam);
}
default:
{
return DefMDIChildProc(mdi_child_window,
message,
wparam,
lparam);
}
}
}
/* document.hpp */
#ifndef DOCUMENT_HPP
#define DOCUMENT_HPP
#include "globals.hpp"
#include "mdi_child_window.hpp"
class Document : public MDIChildWindow
{
public:
Document(HWND mdi_client_window,
const char* const title);
const HWND get_handle() const
{
return m_mdi_child_window;
}
virtual long on_mdiactivate(unsigned int wparam, long lparam);
private:
HWND m_frame_window;
};
#endif
/* document.cpp */
#include "document.hpp"
Document:ocument(HWND mdi_client_window,
const char* const title)
:
MDIChildWindow(mdi_client_window, title, (long)this)
{
;
}
/* This function is not called! Why?? */
long Document:n_mdiactivate(unsigned int /*wparam*/, long lparam)
{
// do something more than just return 0
return 0;
}
/ WP