我有三個類... Base,Derived 1和Derived 2.基類包含一個靜態LONG(this *),它使用靜態函數來處理窗口消息。說我遇到的問題是,當我宣佈多個派生類,靜態LONG基類內於第二派生類的聲明改變了...這裏是實現:實例化基類 - Win32對話框類
BaseDialog.h:
class CBaseDialog;
typedef void(CBaseDialog::*fpMessageHandler)(HWND hDlg,WPARAM wParam,LPARAM lParam);
struct t_MessageEntry
{
fpMessageHandler MsgHandler;
};
/////////////////////////////// MACROS
#define IMPLEMENT_MESSAGE_HANDLER(base,derived) void derived::AddHandler(UINT MessageId, void(derived::*Handler)(HWND hDlg,WPARAM wParam,LPARAM lParam))\
{\
AddMessageHandler(MessageId, (void(base::*)(HWND hDlg,WPARAM wParam,LPARAM lParam))Handler);\
}\
#define DECLARE_MESSAGE_HANDLER(derived) void AddHandler(UINT MessageId, void(derived::*Handler)(HWND hDlg,WPARAM wParam,LPARAM lParam));\
void HandleManager(void);\
#define BEGIN_MESSAGE_MAP(derived) void derived::HandleManager(void) {
#define ADD_MESSAGE_HANDLER(message,handler) AddHandler(message, handler);
#define END_MESSAGE_MAP() }
#define ENABLE_MESSAGE_MAP() HandleManager();
class CBaseDialog
{
public:
std::map<UINT,t_MessageEntry> m_MessageMap;
std::map<UINT,t_MessageEntry>::iterator m_MessageMapIterator;
CBaseDialog(int nResId, HWND hParent=NULL);
virtual ~CBaseDialog();
int DoModal(void);
static BOOL CALLBACK DialogProcStatic(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void OnOK(void);
void OnCancel(void);
void AddMessageHandler(UINT MessageId, void(CBaseDialog::*Handler)(HWND hDlg,WPARAM wParam,LPARAM lParam));
protected:
int m_nResId;
HWND m_hParent;
static HWND m_hWindow;
static long m_lSaveThis;
};
BaseDialog.cpp:
HWND CBaseDialog::m_hWindow = NULL;
long CBaseDialog::m_lSaveThis = 0; // Changes on second declaration of derived class
CBaseDialog::CBaseDialog(int nResId, HWND hParent)
{
m_lSaveThis = (long)this; /// store this pointer
m_nResId = nResId;
m_hParent = hParent;
}
CBaseDialog::~CBaseDialog()
{
m_hWindow = NULL;
m_lSaveThis = 0;
}
int CBaseDialog::DoModal(void)
{
HWND hWnd = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(m_nResId), m_hParent, (DLGPROC)DialogProcStatic);
return 0;
}
void CBaseDialog::AddMessageHandler(UINT MessageId, void(CBaseDialog::*MsgHandler)(HWND hDlg,WPARAM wParam,LPARAM lParam))
{
t_MessageEntry MessageEntry;
MessageEntry.MsgHandler = MsgHandler;
m_MessageMap.insert(std::map<UINT,t_MessageEntry>::value_type(MessageId, MessageEntry)); /// insert key & data to map
}
BOOL CALLBACK CBaseDialog::DialogProcStatic(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if(m_hWindow == NULL)
{
m_hWindow = hDlg;
}
CBaseDialog *pThis = (CBaseDialog*)m_lSaveThis; /// typecast stored this-pointer to CBaseDialog pointer
return pThis->DialogProc(hDlg, uMsg, wParam, lParam);
}
BOOL CALLBACK CBaseDialog::DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
m_MessageMapIterator = m_MessageMap.find(message); /// find message entry by key
if(m_MessageMapIterator == m_MessageMap.end()) /// check if message entry available
{
return 0;
}
else
{
t_MessageEntry MessageEntry = (*m_MessageMapIterator).second; /// dereference iterator and get message entry
void (CBaseDialog::*MessageHandler)(HWND hDlg,WPARAM wParam,LPARAM lParam);
MessageHandler = MessageEntry.MsgHandler;
(this->*MessageHandler)(hDlg, wParam, lParam); /// execute function
return 0;
}
}
void CBaseDialog::OnOK(void)
{
EndDialog(m_hWindow, IDOK);
}
void CBaseDialog::OnCancel(void)
{
EndDialog(m_hWindow, IDCANCEL);
}
Outliner.h:
#include "BaseDialog.h"
class COutlinerDlg : public CBaseDialog
{
public:
COutlinerDlg(int nResId, HWND hParent=NULL);
virtual ~COutlinerDlg();
void Initialize(LPCWSTR strRootName)
{
m_strRootName = strRootName;
}
public:
VOID Resize(RECT rc);
HWND GetHWND(){ return m_hWindow; }
HWND GetTREEDLG(){ return m_hTreeDlg; }
BOOL GetVisible(){ return m_bVisible; }
VOID SetVisible(BOOL b){ m_bVisible = b; }
BOOL GetDragging(){ return m_bDragging; }
VOID SetDragging(BOOL b){ m_bDragging = b; }
VOID SetParentHWND(HWND hWnd){ m_hParent = hWnd; }
HWND GetParentHWND(){ return m_hParent; }
BOOL Show(DWORD dwFlags){ return ShowWindow(m_hWindow, dwFlags); }
HRESULT BuildOutlinerFromDirectory(LPCWSTR rootName, LPCWSTR directory);
HRESULT BuildChildDirectory(LPCWSTR child);
protected:
void On_WM_INITDIALOG(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_COMMAND(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_NOTIFY(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_LBUTTONDOWN(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_LBUTTONUP(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_MOUSEMOVE(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_PAINT(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_SIZE(HWND hDlg, WPARAM wParam, LPARAM lParam);
void On_WM_CLOSE(HWND hDlg, WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_HANDLER(COutlinerDlg);
private:
// Tree Root name
LPCWSTR m_strRootName;
// Directory
LPCWSTR m_strDirectory;
// Dialog Dimensions
RECT m_rcDlg;
TV_ITEM m_tvi;
TV_INSERTSTRUCT m_tvinsert; // struct to config out tree control
HTREEITEM m_hTISelected;
HTREEITEM m_hTIParent; // Tree item handle
HTREEITEM m_hTIBefore; // .......
HTREEITEM m_hTIRoot; // .......
HIMAGELIST m_hImageList; // Image list array hadle
bool m_bSelected;
// for drag and drop
HWND m_hTreeDlg;
HTREEITEM m_hTIHitTarget;
TVHITTESTINFO m_tvht;
POINTS m_ptsPos;
bool m_bDragging;
bool m_bVisible;
// for lable editing
HWND m_hEdit;
};
Outliner.cpp:
#include "Outliner.h"
IMPLEMENT_MESSAGE_HANDLER(CBaseDialog, COutlinerDlg)
BEGIN_MESSAGE_MAP(COutlinerDlg)
ADD_MESSAGE_HANDLER(WM_INITDIALOG, &COutlinerDlg::On_WM_INITDIALOG)
ADD_MESSAGE_HANDLER(WM_COMMAND, &COutlinerDlg::On_WM_COMMAND)
ADD_MESSAGE_HANDLER(WM_NOTIFY, &COutlinerDlg::On_WM_NOTIFY)
ADD_MESSAGE_HANDLER(WM_LBUTTONDOWN, &COutlinerDlg::On_WM_LBUTTONDOWN)
ADD_MESSAGE_HANDLER(WM_LBUTTONUP, &COutlinerDlg::On_WM_LBUTTONUP)
ADD_MESSAGE_HANDLER(WM_MOUSEMOVE, &COutlinerDlg::On_WM_MOUSEMOVE)
ADD_MESSAGE_HANDLER(WM_PAINT, &COutlinerDlg::On_WM_PAINT)
ADD_MESSAGE_HANDLER(WM_CLOSE, &COutlinerDlg::On_WM_CLOSE)
END_MESSAGE_MAP()
COutlinerDlg::COutlinerDlg(int nResId, HWND hParent) : CBaseDialog(nResId, hParent)
{
ENABLE_MESSAGE_MAP();
m_hTISelected = m_hTIParent = m_hTIBefore = m_hTIRoot = m_hTIHitTarget = NULL;
m_hImageList = NULL;
m_bSelected = m_bDragging = false;
m_bVisible = true;
m_hTreeDlg = NULL;
ZeroMemory(&m_tvi, sizeof(TV_ITEM));
ZeroMemory(&m_tvinsert, sizeof(TV_INSERTSTRUCT));
ZeroMemory(&m_tvht, sizeof(TVHITTESTINFO));
ZeroMemory(&m_ptsPos, sizeof(POINTS));
}
COutlinerDlg::~COutlinerDlg()
{
m_hWindow = NULL;
m_lSaveThis = 0;
}
void COutlinerDlg::On_WM_INITDIALOG(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
...
}
此代碼是從演示中,我在網上找到的代碼的項目,我想......
我可以實例的基類,這樣我就不會宣佈大綱的新實例時覆蓋靜態多久?
您不應該將'this'強制轉換爲64位版本。使用DWORD_PTR或類似的(或者只是使用CBaseDialog *並避免完全投射)。 – 2013-02-22 02:44:41
這個想法是有一個類來處理win32應用程序中的許多不同的對話框窗口消息 – 2013-02-22 03:36:40
是的我明白,它不會改變你應該存儲指針大小適當的變量的事實:) – 2013-02-22 03:43:35