MFC SDI project want to call GetDocument() function in a view - mfc

Now I create a totally new SDI project
the view provides a function: GetDocument(), it helps me to get the current document's data
However, When I call the GetDocument() function,VC tells me some error occurs:Debug Assertion Failed
the following is my setting
class CHorse_programView : public CView
{
protected: // create from serialization only
CHorse_programView();
DECLARE_DYNCREATE(CHorse_programView)
// Attributes
public:
CHorse_programDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CHorse_programView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CHorse_programView();
CHorse_programDoc * GetDoc()
{
CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);
return (CHorse_programDoc *) pFrame->GetActiveDocument();
}
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CHorse_programView)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
and I want to call GetDocument() in this function
CHorse_programView::CHorse_programView()
{
GetDocument();
}
what's wrong

The CDocument and CView are not connected yet at CView construction time. You can move your code to OnInitialUpdate in the view to get full capability.

In the view's constructor, it hasn't been assigned to a document yet - that comes later.

Related

c++ Public member variable is inaccessible

There's an error message "member ... is inaccessible" in Visual Studio when I try to access the value of a member variable.
But, the member variable is declared public. It's a derived class, but it's not a member variable of the base class.
From the compiler, there's an error message "cannot access protected member".
The lines that cause the error:
CKaltestDlg dlg;
fprintf(debugout, "Reminders get input focus %s \n", dlg.m_ReminderInputFocus ? "true" : "false");
The header file. The member variable in question is near the end, under a public: heading.
// KaltestDlg.h : header file
//
#pragma once
// CKaltestDlg dialog
class CKaltestDlg : public CDialogEx
{
// Construction
public:
CKaltestDlg(CWnd* pParent = nullptr); // standard constructor
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_KALTEST_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnBnClickedRemindersinputfocus();
CButton m_EnableDisableInputFocus;
BOOL m_ReminderInputFocus;
CButton m_EnableDisableRemindersOntop;
BOOL m_RemindersOnTop;
afx_msg void OnBnClickedRemindersalwaysontop();
CButton m_EnableDisableFlash;
BOOL m_FlashTaskbarButton;
afx_msg void OnBnClickedReminderflash();
};
From the documentation of the DECLARE_MESSAGE_MAP() macro
Note
If you declare any member after DECLARE_MESSAGE_MAP, you must specify a new access type (public, private, or protected) for them.
So the macro expansion may result in the visibility being changed. Either move the macro to the end of the class or add public: right after it. I'd recommend leaving a comment about this in your code to remind you of this fact if you modify the class in the future.

MFC CView into CDockablePane

I need to place a CView derived class into a CDockablePane. Is there any code example somewhere, or can someone provide such code?
What I tried:
Apparently should be simple, online I found advice like "just create the view and set its parent to be the dialog or the dockable pane or what kind of window you want". But for some reason it doesn't work, maybe is because it needs a CFrameWnd, I don't know.
Anyway, I need to be able to do this without creating another document template class. Just to work with preexisting document and view classes.
Here's an example:
a class derived from CDockablePane:
//CRichEditPane .h
class CRichEditPane : public CDockablePane
{
DECLARE_DYNAMIC(CRichEditPane)
public:
CRichEditPane();
virtual ~CRichEditPane();
protected:
void AdjustLayout();
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
};
//CRichEditPane .cpp
IMPLEMENT_DYNAMIC(CRichEditPane, CDockablePane)
CRichEditPane::CRichEditPane()
{
}
CRichEditPane::~CRichEditPane()
{
}
BEGIN_MESSAGE_MAP(CRichEditPane, CDockablePane)
ON_WM_CREATE()
ON_WM_SIZE()
END_MESSAGE_MAP()
// CRichEditPane message handlers
int CRichEditPane::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
CRuntimeClass *pClass = RUNTIME_CLASS(CRichEditViewInPane);
// calling constructor using IMPLEMENT_DYNCREATE macro
CRichEditViewInPane *pView = (CRichEditViewInPane*)pClass->CreateObject();
if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0,0,0,0), this, AFX_IDW_PANE_FIRST, NULL))
{
return -1;
}
CRichEditCtrl ctrl;
ctrl.Create(WS_CHILD, CRect(0, 0, 0, 0), this, 10991);
return 0;
}
void CRichEditPane::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
AdjustLayout();
}
a view class derived from CView:
//CRichEditViewInPane .h
class CRichEditViewInPane : public CRichEditView
{
DECLARE_DYNCREATE(CRichEditViewInPane)
protected:
CRichEditViewInPane(); // protected constructor used by dynamic creation
virtual ~CRichEditViewInPane();
public:
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
DECLARE_MESSAGE_MAP()
};
//CRichEditViewInPane. cpp
IMPLEMENT_DYNCREATE(CRichEditViewInPane, CRichEditView)
CRichEditViewInPane::CRichEditViewInPane()
{
}
CRichEditViewInPane::~CRichEditViewInPane()
{
}
BEGIN_MESSAGE_MAP(CRichEditViewInPane, CRichEditView)
END_MESSAGE_MAP()

Unable to get touches in COCOS 2dx?

Below is my HelloWorld.h class:
class HelloWorld : public cocos2d::CCLayer
{
public:
HelloWorld();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
b2World* world;
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
virtual void draw();
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
virtual void ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void update(float dt);
};
And in my HelloWorld.cpp class i have initialized My init method
bool HelloWorld::init(){
setTouchEnabled( true );
setAccelerometerEnabled( true );
scheduleUpdate();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
return true;
}
This code is working for me now! :)
The Targeted Delegate is for single touch events. Change your events to something like this:
virtual bool ccTouchBegan (CCTouch *pTouch, CCEvent *pEvent)
You can read up more about targeted and standard touch delegates on the iPhone side of the Cocos2D documentation at this Link
Writing the delegate in my initialisation method as per below solved the problem
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this, 1);
If you want to disable multiTouch capability you can use :
virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
virtual void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){}
virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){}
And so you need to:
bool init()
{
...
setTouchEnabled(true);
this->setTouchMode(ccTouchesMode::kCCTouchesOneByOne); // Important
}
If you omit last line you will need to override these (multiTouch mode):
void ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);

CMFCButton.SetToolTip() crash

I'm trying to display a tooltip on a CMfcButton.
When my code run the SetToolTip(), the application crash.
BOOL CGenerationDlg::OnInitDialog()
{
BOOL bret = CPropertyPage::OnInitDialog();
m_pButtonExport = (CMFCButton *)GetDlgItem(IDC_BTN_EXPORTE_BILAN);
m_pButtonExport->EnableFullTextTooltip();
m_pButtonExport->SetTooltip(L"my tooltip");
return bret;
}
void CKenoDlg::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
}
Here is my Header file :
// KenoDlg.h : fichier d'en-tête
//
#pragma once
#include "keno.h"
#include "AboutDlg.h"
// boîte de dialogue CKenoDlg
class CKenoDlg : public CPropertyPage
{
// Construction
public:
CKenoDlg(CWnd* pParent = NULL); // constructeur standard
CAboutDlg* myDialog;
// Données de boîte de dialogue
enum { IDD = IDD_KENO_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // Prise en charge de DDX/DDV
CMFCButton * m_pButtonExport;
// Implémentation
protected:
HICON m_hIcon;
// Fonctions générées de la table des messages
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedBtnGenerate();
afx_msg void OnBnClickedBtnExport();
afx_msg void OnStnClickedStaticAbout();
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
Here is my error :
Any idea please ?
Thanks a lot :)
Best regards,
Try this:
Change your header to define a CMFCButton instance rather than a pointer:
class CKenoDlg : public CPropertyPage
{
// ... existing code ...
protected:
virtual void DoDataExchange(CDataExchange* pDX); // Prise en charge de DDX/DDV
CMFCButton m_pButtonExport;
// ... existing code ...
};
Then change your DoDataExchange function as follows:
void CKenoDlg::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BTN_EXPORTE_BILAN, m_pButtonExport);
}
Finally, in OnInitDialog, do something like this:
BOOL CGenerationDlg::OnInitDialog()
{
BOOL bret = CPropertyPage::OnInitDialog();
m_pButtonExport.EnableFullTextTooltip();
m_pButtonExport.SetTooltip(L"my tooltip");
return bret;
}
The reason why you need to do it like this rather than with a pointer is because MFC has to subclass the control to a CMFCButton rather than the default CButton. When you use the DDX macro in DoDataExchange, this is done behind the scenes when the default implementation of OnInitDialog calls UpdateData, which in turn calls DoDataExchange and - if I recall correctly - on the first time through, the dialog controls are sub-classed to the correct types.
As you used a pointer, and had no link between the button control and the type you were using it as, there was a mismatch between the actual and expected types and that was the reason for the crash.
If you use the VS2012 wizard to add a variable from the dialog designer (right-click on a dialog control and choose Add Variable), it will create the member variable declaration in the header file and will add the DDX macro to the DoDataExchange function for you. You can then choose to change the type of the member variable, e.g. from CButton to one of your own CButton derived classes.
You use the term pointer to button and name the variable 'm_pButtonExport'. That is incorrect. The code creates an instance of a CMFCButton object, not a pointer to an instance of a button object. The variable should be named 'm_ButtonExport' and referred to as an instance of a CMFCButton object NOT a pointer to one.

OnSelectionChanged not getting called

Header:
#pragma once
class AlarmsList : public CVSListBox
{
DECLARE_DYNAMIC(AlarmsList)
public:
AlarmsList();
virtual ~AlarmsList();
void OnAfterAddItem(int index);
void OnSelectionChanged(NMHDR *pNMHDR, LRESULT *pResult);
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnDtnDatetimechangeDatetimepicker1(NMHDR *pNMHDR, LRESULT *pResult);
};
void AlarmsList::OnAfterAddItem(int index)
{
GetParent()->GetDlgItem(IDC_TIMEPICK)->EnableWindow(true);
LOGIC->addAlarm();
LOGIC->changeSelection(index);
}
void AlarmsList::OnSelectionChanged(NMHDR *pNMHDR, LRESULT *pResult)
{
}
OnAfterAddItem gets called when i add a new item but OnSelectionChanged NEVER gets called how much i even try.
Linking it trough a message map neither dosnt work:
IMPLEMENT_DYNAMIC(AlarmsList, CVSListBox)
BEGIN_MESSAGE_MAP(AlarmsList, CVSListBox)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, OnSelectionChanged)
END_MESSAGE_MAP()
I create the AlarmsList object using the create function.
Source code and project: http://www.filedropper.com/clockmaster
Generally, I think the LVN_ITEMCHANGED notification is sent to the parent window. Put the handler and the message map entry int your dialog/window that is the parent of the list box.
Didnt help :/.
Tried both parent property page and that property pages dialog.
Overloading dosnt work either :/, it does for OnAfterAddItem tough.
And yes I'm then using the same parameters as the virtual function.
You can try overriding the functions in the CVSListBoxBase class.In this class, the signature of OnSelectionChanged function requires no arguments.
You can find the declaration of the CVSListBoxBase class in afxvslistbox.h.
Just had a look at some of my own MFC code that uses list boxes, and the following works;
CMyListBox : public CListBox
{
}
class CMyDialog : public CDialog
{
// Construction
public:
CMyDialog(CFeatureDoc* pFeatureDoc,BOOL SheetLayout = FALSE,CWnd* pParent = NULL); // standard constructor
//{{AFX_DATA(CMyDialog)
enum { IDD = IDD_MY_DIALOG };
CMyListBox m_MyListBox;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMyDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CMyDialog)
afx_msg void OnSelChangeListBox();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDialog)
DDX_Control(pDX, IDC_MY_LIST_BOX, m_MyListBox);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
//{{AFX_MSG_MAP(CMyDialog)
ON_LBN_SELCHANGE(IDC_MY_LIST_BOX, OnSelChangeListBox)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyDialog message handlers
void CMyDialog::OnSelChangeListBox()
{
}
If you want to have your own control process messages from a dialog, you may want to subclass it. See this related question What's the correct way to create a subclass of a MFC control?