Visual C++ How to override event handler of parant class? - c++

I need to override event wm_lbuttonup of CMFCRibbonSlider class
class CMyRibbonSlider : public CMFCRibbonSlider
{
public:
virtual void OnLButtonUp(CPoint point); // need this event handler!
};
void CMyRibbonSlider::OnLButtonUp(CPoint point)
{
AfxMessageBox(_T("Works!"))
return;
}
Use CMyRibbonSlider object in MainFrame class
class CMainFrame : public CMDIFrameWndEx
{
....
CMyRibbonSlider* SliderLine;
}
When CMFCRibbonSlider control apears and I click left mousebutton, nothing happens. What do I do wrong?
EDIT:
initialization
CArray<CMFCRibbonBaseElement*, CMFCRibbonBaseElement*> ar;
m_wndRibbonBar.GetElementsByID(ID_SLIDER2, RibbonElementsArray);
m_wndRibbonBar.GetElementsByID(ID_START_BTN, ar);
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(ID_STOP_BTN, ar);
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(ID_SLIDER_LINE, ar); //HERE!
RibbonElementsArray.Append(ar);
m_wndRibbonBar.GetElementsByID(IDC_STATIC_TT, ar);
RibbonElementsArray.Append(ar);
Slider = DYNAMIC_DOWNCAST(CMFCRibbonSlider, RibbonElementsArray[0]);
btnStart = DYNAMIC_DOWNCAST(CMFCRibbonButton, RibbonElementsArray[1]);
btnStop = DYNAMIC_DOWNCAST(CMFCRibbonButton, RibbonElementsArray[2]);
SliderLine = (CMyRibbonSlider*)DYNAMIC_DOWNCAST(CMFCRibbonSlider, RibbonElementsArray[3]); //and HERE!
TmpLable = DYNAMIC_DOWNCAST(CMFCRibbonLabel, RibbonElementsArray[4]);
also I have these event handlers in Mainframe class and they work:
ON_UPDATE_COMMAND_UI(ID_SLIDER_LINE, &CMainFrame::OnUpdateSliderLine)
ON_COMMAND(ID_SLIDER_LINE, &CMainFrame::OnSliderLine)
SliderLine->GetPos() also returns right slider position, so I think initialization is right...

It is seem like the CMFCRibbonSlider control isn't added correctly to CMFCRibbonPanel and therefore CMainFrame class does not expose slider’s messages through message map.
Try to use a method described in the following article:
Walkthrough: Creating a New Ribbon Application By Using MFC
The code will be look like below.
MyRibbonSlider.h
#include "afxribbonslider.h"
#pragma once
class CMyRibbonSlider : public CMFCRibbonSlider
{
DECLARE_DYNCREATE(CMyRibbonSlider)
public:
CMyRibbonSlider();
CMyRibbonSlider(UINT nID, int nWidth = 100);
// Implementation
public:
virtual ~CMyRibbonSlider();
virtual void OnLButtonUp(CPoint point);
};
MyRibbonSlider.cpp
#include "stdafx.h"
#include "MyRibbonSlider.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CMyRibbonSlider, CMFCRibbonSlider)
CMyRibbonSlider::CMyRibbonSlider()
{
}
CMyRibbonSlider::CMyRibbonSlider(UINT nID, int nWidth)
: CMFCRibbonSlider(nID, nWidth)
{
}
CMyRibbonSlider::~CMyRibbonSlider()
{
}
void CMyRibbonSlider::OnLButtonUp(CPoint point)
{
TRACE("\nCMyRibbonSlider::OnLButtonUp()");
return;
}
Related declarations in the CMainFrame.h
afx_msg void OnSliderLine();
afx_msg void OnUpdateSliderLine(CCmdUI* pCmdUI);
CMainFrame.cpp
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
...
ON_COMMAND(ID_SLIDER, &CMainFrame::OnSliderLine)
ON_UPDATE_COMMAND_UI(ID_SLIDER, &CMainFrame::OnUpdateSliderLine)
END_MESSAGE_MAP()
void CMainFrame::InitializeRibbon()
{
...
bNameValid = strTemp.LoadString(*your title*);
ASSERT(bNameValid);
CMFCRibbonPanel* pPanelAdvanced = pCategoryHome->AddPanel(strTemp, m_PanelImages.ExtractIcon (*your icon*));
strTemp = _T("Slider");
CMyRibbonSlider* pRibbonSlider = new CMyRibbonSlider(ID_SLIDER);
pPanelAdvanced->Add(pRibbonSlider);
...
}
void CMainFrame::OnSliderLine()
{
// TODO
}
void CMainFrame::OnUpdateSliderLine(CCmdUI* pCmdUI)
{
// TODO
}

Related

Creating a new base CDialogEx derived class

I have a lot of CDialogEx derived classes that do something like this in OnInitDialog:
CMeetingScheduleAssistantApp::InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
CMeetingScheduleAssistantApp::RestoreWindowPosition(_T("PublisherDB"), this, true);
Then, I have the following added to each derived dialog class:
int CPublishersDatabaseDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CPublishersDatabaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CPublishersDatabaseDlg::OnClose()
{
CMeetingScheduleAssistantApp::SaveWindowPosition(_T("PublisherDB"), this);
CDialogEx::OnClose();
}
The only thing that is different for each dialog is the phrase that is used for saving the window position.
I want to have a based CDialogEx class that I can inherit from that will perform the above actions. I have looked on SO and seem some questions and creating a CDialog class and inheriting from another CDialog class. But this class I want to create is more generic. Effectively to be used as a base instead of CDialogEx.
Can this be done? Am I over-complicating this?
Problems
Why I try to create a new class, derived from CDialogEx:
I don't know if it is because it requires a dialog ID as stated here.
Classes such as CDialog, CFormView, or CPropertyPage, which require a dialog ID.
So I can't work out the correct way to create a base CDialogEx class for use in all my other dialog classes.
Update
I created this code and it tells me that CResizingDialog is not a class or a namespace:
#include "ResizingDialog.h"
#include "resource.h"
#include "stdafx.h"
IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent = nullptr)
: m_strWindowID(strWindowID), CDialogEx(nIDTemplate, pParent)
{
}
CResizingDialog::~CResizingDialog()
{
}
void CResizingDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
ON_WM_CREATE()
ON_WM_GETMINMAXINFO()
ON_WM_CLOSE()
END_MESSAGE_MAP()
int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CResizingDialog::OnClose()
{
SaveWindowPosition(m_strWindowID, this);
CDialogEx::OnClose();
}
Based on the comments encouraging me to try to create the class manually, I have it working:
#include "stdafx.h"
#include "resource.h"
#include "ResizingDialog.h"
IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent /* nullptr */, bool bOnlyStorePosition /* false */)
: m_strWindowID(strWindowID),
m_bOnlyStorePosition(bOnlyStorePosition), CDialogEx(nIDTemplate, pParent)
{
}
CResizingDialog::~CResizingDialog()
{
}
void CResizingDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
ON_WM_CREATE()
ON_WM_GETMINMAXINFO()
ON_WM_CLOSE()
END_MESSAGE_MAP()
int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CResizingDialog::OnClose()
{
SaveWindowPosition(m_strWindowID, this);
CDialogEx::OnClose();
}
void CResizingDialog::OnOK()
{
SaveWindowPosition();
CDialogEx::OnOK();
}
BOOL CResizingDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
if(!m_bOnlyStorePosition)
InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
RestoreWindowPosition(m_strWindowID, this, true);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
I decided to duplicate the methods that were in the app class into this new dialog class instead. Eventually they can be removed from the app class. The only thing I also had to do was #include my resource file because the image needs to know the value of the resource ID.
This is the ResizingDialog.h header:
#pragma once
#include <afxwin.h>
class CResizingDialog : public CDialogEx
{
DECLARE_DYNAMIC(CResizingDialog)
public:
CResizingDialog(const CString& phrase, UINT nIDTemplate, CWnd* pParent = nullptr, bool bOnlyStorePosition = false); // Constructor
virtual ~CResizingDialog(); // Destructor
protected:
void OnOK() override;
virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support
void SaveWindowPosition(void) { SaveWindowPosition(m_strWindowID, this); }
public:
BOOL OnInitDialog() override;
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
afx_msg void OnClose();
DECLARE_MESSAGE_MAP()
private:
CBitmap m_bmpResize;
CStatic m_lblResize;
CRect m_rcInit;
CString m_strWindowID;
bool m_bOnlyStorePosition;
void RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState = false);
void SaveWindowPosition(CString strWindow, CWnd* pWindow);
void InitialiseResizeIcon(CBitmap& rBmpResize, CStatic& rLblResize, CWnd* pDialog);
};
The actual functions SaveWindowPosition, RestoreWindowPosition and InitialiseResizeIcon are not shown here as they don't directly relate to the issue.

Creating CWnd derived control at runtime

I am trying to create CWnd derived class at runtime but CWnd::Create fails. I have no idea why. Here is minimal code that show the problem:
MFCTestApplicationDlg.h
#pragma once
class c_CustomButton : public CButton
{
protected:
DECLARE_MESSAGE_MAP()
virtual void PreSubclassWindow();
public:
c_CustomButton();
virtual ~c_CustomButton();
};
class TestWindow : public CWnd
{
public:
TestWindow();
virtual ~TestWindow();
protected:
DECLARE_MESSAGE_MAP()
DECLARE_DYNCREATE(TestWindow)
};
// CMFCTestApplicationDlg dialog
class CMFCTestApplicationDlg : public CDialogEx
{
...
}
MFCTestApplicationDlg.cpp
//
#include "stdafx.h"
#include "MFCTestApplication.h"
#include "MFCTestApplicationDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
/*==========================================================================*/
c_CustomButton::c_CustomButton()
{
}
/*==========================================================================*/
c_CustomButton::~c_CustomButton()
{
}
BEGIN_MESSAGE_MAP(c_CustomButton, CButton)
END_MESSAGE_MAP()
/*==========================================================================*/
void c_CustomButton::PreSubclassWindow()
{
CButton::PreSubclassWindow();
ModifyStyle(0, BS_OWNERDRAW);
}
IMPLEMENT_DYNAMIC(TestWindow, CWnd)
TestWindow::TestWindow()
{
}
TestWindow::~TestWindow()
{
}
BEGIN_MESSAGE_MAP(TestWindow, CWnd)
END_MESSAGE_MAP()
void CMFCTestApplicationDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
c_CustomButton* pColoredButton = new c_CustomButton;
pColoredButton->Create((LPCTSTR)"", 0, CRect(), this, 0);// successeded
pColoredButton->SetWindowTextW((LPCTSTR)"test");
TestWindow* pTestWindow = new TestWindow;
pTestWindow->Create((LPCTSTR)"TestWindow", (LPCTSTR)"TestWindowName", 0, CRect(), this, 0);// failed
pTestWindow->SetWindowText((LPCTSTR)"test");
}
In void CMFCTestApplicationDlg::DoDataExchange(CDataExchange* pDX) I tried to create a CButton derived class object and CWnd derived class object. The first one created successfully but CWnd derived class object fails to create. Whats wrong with this code?

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()

How can I change the border?

I make a simple window with wxwidgets. How can I change the border?
Also how can I call the destroy function(OnClose) with the right arrow button press?
#include <wx/wx.h>
class _Frame: public wxFrame
{
public:
_Frame(wxFrame *frame, const wxString& title);
private:
void OnClose(wxCloseEvent& event);
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(_Frame, wxFrame)
END_EVENT_TABLE()
_Frame::_Frame(wxFrame *frame, const wxString& title)
: wxFrame(frame, -1, title)
{}
void _Frame::OnClose(wxCloseEvent &event)
{
Destroy();
}
class _App : public wxApp
{
public:
virtual bool OnInit();
};
IMPLEMENT_APP(_App);
bool _App::OnInit()
{
_Frame* frame = new _Frame(0L, _("wxWidgets Application Template"));
frame->Show();
return true;
}
To close the window on right-arrow you need to trap EVT_CHAR or EVT_KEY_DOWN like so:
header file:
void OnChar(wxKeyEvent& event);
source file:
void _Frame::OnChar(wxKeyEvent& event)
{
if (event.GetKeyCode() == WXK_RIGHT)
{
wxCommandEvent close(wxEVT_CLOSE_WINDOW);
AddPendingEvent(close);
}
event.Skip();
}
BEGIN_EVENT_TABLE(_Frame, wxFrame)
EVT_CHAR(_Frame::OnChar)
END_EVENT_TABLE()
Changing the border (by setting a different wxBORDER_XXX style) doesn't work for all windows/under all platforms after the initial window creation so you'd better recreate the window if you really, really need to do this.

Can't get OnContextMenu to work for custom CListCtl class

I am trying to get a context menu to work for a CListCtrl derived class. I just created a method OnContextMenu, but it isn't being called. What am I missing? I am using Visual Studio 2008, to create a CDialog based MFC application.
CustomList.h
class tcCustomListCtl : public CListCtl
{
DECLARE_DYNAMIC(tcCustomListCtl)
public:
tcCustomListCtl();
virtual ~tcCustomListCtl();
protected:
DECLARE_MESSAGE_MAP()
afx_msg void OnContextMenu(CWnd* pWnd,CPoint pos );
};
CustomList.cpp
// tcFaultListCtl
IMPLEMENT_DYNAMIC(tcCustomListCtl, CListCtrl)
tcCustomListCtl::tcCustomListCtl()
{
}
tcCustomListCtl::~tcCustomListCtl()
{
}
BEGIN_MESSAGE_MAP(tcCustomListCtl, CListCtrl)
END_MESSAGE_MAP()
// tcCustomListCtl message handlers
afx_msg void tcCustomListCtl::OnContextMenu(CWnd* pWnd,CPoint pos )
{
TRACE("tcCustomListCtl::OnContextMenu\n");
}
I found out I had to add ON_WM_CONTEXTMENU() to message map.