Class` member changes unwillingly somehow
I got the two following CDialog-class created for creating dialog windows from templates and a class CMainDialog that is dereived from CDialog and has some methods do manipulate controls on the dialogs.
class CDialog
{
public:
CDialog(DWORD dwTemplate) : m_dwTemplateID(dwTemplate), m_hWnd(NULL) {};
virtual ~CDialog() {};
static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual BOOL Create(HINSTANCE hInstance, HWND hParent = NULL);
BOOL Show(BOOL bShow);
private:
DWORD m_dwTemplateID;
protected:
HWND m_hWnd;
virtual INT_PTR HandleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
//Base Dialog Implementation
#include "BaseDialog.h"
//statics
INT_PTR CALLBACK Inc::CDialog::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Inc::CDialog* pDialog = nullptr;
if(uMsg == WM_INITDIALOG)
{
//save address of the CDialog-object into the dialog´s userdata
pDialog = (Inc::CDialog*)lParam;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pDialog);
}
else
{
//get the pointer
pDialog = (Inc::CDialog*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
}
if(pDialog)
{
//handle messages
return pDialog->HandleMessages(hWnd, uMsg, wParam, lParam);
}
return FALSE; //!pDialog
}
INT_PTR Inc::CDialog::HandleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
DestroyWindow(m_hWnd);
return TRUE;
case WM_DESTROY:
PostQuitMessage(0);
return TRUE;
};
return FALSE; //Message not handled => system will take action
}
BOOL Inc::CDialog::Create(HINSTANCE hInstance, HWND hParent)
{
m_hWnd = CreateDialogParam(hInstance, MAKEINTRESOURCE(m_dwTemplateID), hParent, DialogProc, (LPARAM)this);
if(m_hWnd == NULL)
return FALSE;
return TRUE;
}
//return values: TRUE => window was previously visible, FALSE otherwise
BOOL Inc::CDialog::Show(BOOL bShow)
{
if(bShow)
return ShowWindow(m_hWnd, SW_SHOWNORMAL);
return ShowWindow(m_hWnd, SW_HIDE);
}
//CMainDialog
class CMainDialog :
开发者_JAVA百科 public Inc::CDialog
{
public:
CMainDialog(DWORD dwTemplateID);
virtual ~CMainDialog(void);
virtual INT_PTR HandleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
static const char m_szDates[8][14];
//Dialog control item
HWND m_hDateComboBox;
HWND m_hItemListBox;
HWND m_hDescriptionEditBox;
HWND m_hButtonClose;
HWND m_hButtonSave;
HWND m_hButtonDelete;
//get save the control item handles
public:
void GetControlHandles();
public:
void PopulateDateComboBox();
};
//CMain Dialog Implementation
#include "MainDialog.h"
#include <WindowsX.h>
#include "resource.h"
#include <stdexcept>
//statics
const char Inc::CMainDialog::m_szDates[8][14] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Single Event"};
Inc::CMainDialog::CMainDialog(DWORD dwTemplateID) : CDialog(dwTemplateID)
{
}
Inc::CMainDialog::~CMainDialog(void)
{
}
//adds the entries in m_szDates to the Combo Box for choosing the date
void Inc::CMainDialog::PopulateDateComboBox()
{
for(unsigned short s = 0; s < 8; s++)
{
if(ComboBox_AddString(m_hDateComboBox, m_szDates[s]) <= CB_ERR)
throw(std::runtime_error("ComboBox_AddString() failed"));
}
}
INT_PTR Inc::CMainDialog::HandleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
this->GetControlHandles(); // It happens here !!!!!!! <====
this->PopulateDateComboBox();
return TRUE;
}
return Inc::CDialog::HandleMessages(hWnd, uMsg, wParam, lParam); //if message isnt handled here, default handling
}
void Inc::CMainDialog::GetControlHandles()
{
//Get Control window handles
m_hDateComboBox = GetDlgItem(m_hWnd, IDC_COMBO_DAY);
m_hItemListBox = GetDlgItem(m_hWnd, IDC_LIST);
m_hDescriptionEditBox = GetDlgItem(m_hWnd, IDC_EDIT_DESCRIPTION);
m_hButtonClose = GetDlgItem(m_hWnd, IDC_BUTTON_CLOSE);
m_hButtonSave = GetDlgItem(m_hWnd, IDC_BUTTON_SAVE_CHANGE);
m_hButtonDelete = GetDlgItem(m_hWnd, IDC_BUTTON_DELETE_ITEM);
}
The problem that I do encounter is, that in the CMainDialog::HandleMessages() member function when the WM_INITDIALOG should be handled the m_hWnd member is NULL even tho the CDialog::Create() function did succeed and return the window handle to m_hWnd.
The CDialog::DialogProc-procedure seems to work in the way, that it gets the right address from the WM_INITDIALOG´s LPARAM and let the pDialog-pointer point to the right object and call it´s member functions.
Maybe You see what I did miss or where I did wrong.
Thank You in advance
your WM_INITDIALOG message is processed during the call to CreateDialog ,while the assignment to m_hWnd (the result of CreateDialog) is done after CreateDialog ends.
Solution : pass hWnd to GetControlHandle( HWND hWnd ) or set m_hWnd in WM_INITDIALOG of the Base class.
The fix for this is to add pDialog->m_hWnd = hWnd;
in the handling of WM_INITDIALOG
:
if(uMsg == WM_INITDIALOG)
{
//save address of the CDialog-object into the dialog´s userdata
pDialog = (Inc::CDialog*)lParam;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pDialog);
pDialog->m_hWnd = hWnd;
}
This ensures m_hWnd
is set before any call to HandleMessage
精彩评论