I am not sure what code to show you here. I have a CDialogEx derived resource in my MFC application:
It supports the dynamic resize layout controls so the user can resize the window. But I would like to add a vertical gripper (indicated in red) so the user can make the width of the names column larger.
I have done some research on this and all the articles are nearly 10 years old and don't factor in the newer dynamic resizing controls.
Having researched this more I see that the "resize gripper" term is not what I mean. That is the icon in the bottom right. I don't mean this.
I am sure you know what I mean though. Is it possible?
Adding a custom gripper control can be relatively easy. See CMySplitter class below.
But if all the controls are in one dialog, it will be very difficult reposition/resize individual controls one by one.
Ideally, use two child dialogs. Set the resize/reposition properties for individual controls in resource editor. Put the grip control in between the two dialogs and resize in response.
Class for gripper control:
#include <functional>
class CMySplitter : public CStatic
{
public:
class CPopup : public CWnd
{
public:
CMySplitter *parent;
int offset;
void OnMouseMove(UINT flag, CPoint pt);
void OnLButtonUp(UINT flag, CPoint pt);
DECLARE_MESSAGE_MAP()
};
std::function<void(int)> callback;
CRect boundary;
CPopup popup;
void OnLButtonDown(UINT flag, CPoint point);
void PreSubclassWindow();
void SetRange(int left, int right);
DECLARE_MESSAGE_MAP()
};
//create splitter control from a static control in dialog
void CMySplitter::PreSubclassWindow()
{
CStatic::PreSubclassWindow();
//modify static control's style (must have SS_NOTIFY)
SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_VISIBLE | SS_GRAYRECT | WS_CHILD | SS_NOTIFY);
//create a popup window with transparency
static CString classname =
AfxRegisterWndClass(0, 0, (HBRUSH)GetStockObject(BLACK_BRUSH));
popup.CreateEx(WS_EX_LAYERED | WS_EX_PALETTEWINDOW | WS_EX_NOACTIVATE,
classname, NULL, WS_POPUP, CRect(0, 0, 0, 0), this, 0);
popup.SetLayeredWindowAttributes(0, 128, LWA_ALPHA);
popup.parent = this;
}
//when user click the static control, show a popup window
void CMySplitter::OnLButtonDown(UINT flag, CPoint pt)
{
CStatic::OnLButtonDown(flag, pt);
GetCursorPos(&pt);
CRect rc;
GetWindowRect(&rc);
popup.offset = pt.x - rc.left;
popup.SetWindowPos(NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
popup.SetCapture();
}
//how far to the left and right the splitter can go
void CMySplitter::SetRange(int left_, int right_)
{
CRect rc;
GetParent()->GetWindowRect(&rc);
boundary.left = rc.left + left_;
boundary.right = rc.right - right_;
}
//move this popup window
void CMySplitter::CPopup::OnMouseMove(UINT flag, CPoint pt)
{
CWnd::OnMouseMove(flag, pt);
GetCursorPos(&pt);
CRect rc;
GetWindowRect(&rc);
int x = pt.x - offset;
if (x > parent->boundary.left && x < parent->boundary.right)
SetWindowPos(NULL, x, rc.top, 0, 0, SWP_NOSIZE);
}
//hide popup window, let the parent dialog know
void CMySplitter::CPopup::OnLButtonUp(UINT flag, CPoint pt)
{
CWnd::OnLButtonUp(flag, pt);
ReleaseCapture();
ShowWindow(SW_HIDE);
CRect rc;
GetWindowRect(&rc);
parent->callback(rc.left);
}
BEGIN_MESSAGE_MAP(CMySplitter::CPopup, CWnd)
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CMySplitter, CWnd)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
Usage:
Add a static control with IDC_STATIC1 to the dialog and use as follows.
The code below has a main dialog CMyDialog with IDD_DIALOG, normal dialog
It has two child dialogs, child1 and child2 with IDD_PAGE1 and IDD_PAGE2
IDD_PAGE1 and IDD_PAGE2 are dialog resources with "child" style (not popup)
class CMyDialog : public CDialogEx
{
public:
class CChild1 : public CDialogEx
{
};
class CChild2 : public CDialogEx
{
};
CChild1 child1;
CChild1 child2;
//respond to gripper resize
void respond(int position)
{
CRect rs;
m_splitter.GetWindowRect(&rs);
rs.MoveToX(position);
ScreenToClient(&rs);
CRect rc;
GetClientRect(&rc);
CRect r1(0, 0, rs.left, rc.bottom);
CRect r2(rs.right, 0, rc.right, rc.bottom);
child1.MoveWindow(r1, TRUE);
child2.MoveWindow(r2, TRUE);
m_splitter.MoveWindow(rs, TRUE);
m_splitter.Invalidate(TRUE);
}
CMySplitter m_splitter;
BOOL OnInitDialog()
{
CDialogEx::OnInitDialog();
child1.Create(IDD_PAGE1, this);
child2.Create(IDD_PAGE2, this);
m_splitter.SubclassDlgItem(IDC_STATIC1, this);
m_splitter.SetRange(50, 50);
m_splitter.callback = std::bind(&CMyDialog::respond, this, std::placeholders::_1);
//width for splitter
int dx = 10;
CRect rc;
GetClientRect(&rc);
CRect r1(0, 0, 200, rc.bottom);
CRect r2(r1.right + dx, 0, rc.right, rc.bottom);
CRect rs(r1.right, 10, r2.left, rc.bottom - 10);
child1.MoveWindow(r1);
child2.MoveWindow(r2);
m_splitter.MoveWindow(rs);
child1.ShowWindow(SW_SHOW);
child2.ShowWindow(SW_SHOW);
return TRUE;
}
...
};
Related
I was trying to make the CScrollView move
Although it moved successfully, but I found a problem...
The CScrollView flickered randomly while it is moving.
Below is the whole code of my project:
#include <afxwin.h>
#include <afxext.h>
#include "resource.h"
class MyView : public CScrollView
{
public:
void OnDraw(CDC *aDC){
CRect rc;
GetClientRect(&rc);
aDC->FillSolidRect(&rc, RGB(0,0,255));
}
BOOL PreCreateWindow(CREATESTRUCT& cs)
{
cs.style &= ~WS_BORDER;
return CScrollView::PreCreateWindow(cs);
}
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CScrollView::OnCreate(lpCreateStruct) == -1)
return -1;
CSize DCSize(200, 800);
SetScrollSizes(MM_TEXT, DCSize);
return 0;
}
DECLARE_DYNCREATE(MyView)
DECLARE_MESSAGE_MAP()
};
IMPLEMENT_DYNCREATE(MyView, CScrollView)
BEGIN_MESSAGE_MAP(MyView, CScrollView)
ON_WM_CREATE()
END_MESSAGE_MAP()
class CMainDlg : public CDialog
{
public:
CMainDlg(CWnd* pParent = NULL);
enum { IDD = IDD_MAIN_DIALOG };
CWnd* pFrameWnd;
CCreateContext context;
MyView* pView;
int time;
virtual BOOL OnInitDialog();
afx_msg void OnTimer(UINT_PTR timer);
void OnPaint(){
CPaintDC dc(this);
CRect rc;
GetClientRect(&rc);
dc.FillSolidRect(&rc,RGB(255,187,187));
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
ON_WM_TIMER()
ON_WM_PAINT()
END_MESSAGE_MAP()
CMainDlg::CMainDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMainDlg::IDD, pParent)
{
}
BOOL CMainDlg::OnInitDialog()
{
CDialog::OnInitDialog();
pFrameWnd = this;
context.m_pCurrentDoc = NULL;
context.m_pNewViewClass = RUNTIME_CLASS(MyView);
pView = (MyView*)((CFrameWnd*)pFrameWnd)->CreateView(&context);
pView->ShowWindow(SW_SHOW);
time = 0;
SetTimer(1, 1, 0);
return TRUE;
}
void CMainDlg::OnTimer(UINT_PTR timer)
{
if(timer == 1){
if(time > 300){
KillTimer(1);
return;
}
pView->MoveWindow(CRect(time,10,time+300,200),FALSE);
}
time+=1;
Invalidate(FALSE);
}
class MyApp : public CWinApp
{
public:
BOOL InitInstance()
{
CWinApp::InitInstance();
CMainDlg Frame;
Frame.DoModal();
return true;
}
} a_app;
I don't know why the CScrollView flickered while it is moving. Can anyone solve this problem?
It is flickering because you're invalidating the entire window. This causes a WM_ERASE, which blanks the window, then a WM_PAINT, which redraws the entire thing. You're passing FALSE as the bRepaint (last) parameter to MoveWindow, so that it won't repaint any necessary window area after the window has been moved.
Normally when a window moves the content moves with it, and the only parts that need to be redrawn are bits that were offscreen or under another window. Passing TRUE as the last parameter will cause only these areas of the window to be redrawn, which will avoid the flicker.
I've created a new dialog in my MFC dialog based application. the new dialog contains 5 control buttons.
the following happens and I don't understand why?
click on buttonX. (result ok, OnBnClicked message is sent)
click on on any place of the application, but not on the dialog.(removing focus from dialog)
click again on buttonX (FAILED, OnBnClicked message is NOT sent). but if instead I click on any other button in the dialog (result ok, OnBnClicked message is sent).
and when I do:
...
...
click on the dialog area just to set focus on the dialog again
click again on buttonX. (result ok, OnBnClicked message is sent)
**I need to do step 3 only if I want to click again on the buttonX! why??
I think it related to SetFocus() but I m not sure how.
the buttons IDC are:
IDC_BACK_MEDIA_PRESS_BUTTON 1180
IDC_TOOLS_LEFT_RIGHT 1024
IDC_MEDIA_FOREWARD_BUTTON 1103
IDC_MEDIA_BACKWARD_BUTTON 1104
IDC_TOOLS_HOOD_BUTTON 2346
the dialog properties is:
IDD_TOOLS_DIALOG DIALOGEX 0, 0, 51, 218
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Tools"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Media &Foreward",IDC_MEDIA_FOREWARD_BUTTON,7,79,37,36,BS_MULTILINE
PUSHBUTTON "&Media &BackWard",IDC_MEDIA_BACKWARD_BUTTON,7,43,37,36,BS_MULTILINE
PUSHBUTTON "Back Media Press",IDC_BACK_MEDIA_PRESS_BUTTON,7,127,37,36,BS_MULTILINE | NOT WS_VISIBLE
PUSHBUTTON "Hood",IDC_TOOLS_HOOD_BUTTON,7,7,37,36
PUSHBUTTON "Left Right",IDC_TOOLS_LEFT_RIGHT,7,175,37,36
END
I've tried different style like, tool windows, overlapped, popup. it happens in all the cases.
Thanks for the help.
.h
class CToolsDlg : public CBDialog
{
DECLARE_DYNAMIC(CToolsDlg)
public:
CToolsDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CToolsDlg();
CToolTipCtrl m_ToolsTips;
// Dialog Data
enum { IDD = IDD_TOOLS_DIALOG };
protected:
virtual void OnCancel();
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
CMFCButton m_HoodButton;
CMFCButton m_MediaForewardButton;
CMFCButton m_MediaBackwardButton;
CMFCButton m_LeftRightButton;
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnBnClickedCancel();
afx_msg void OnBnClickedToolsHoodButton();
afx_msg void OnBnClickedMediaForewardButton();
afx_msg void OnBnClickedMediaBackwardButton();
afx_msg void OnBnClickedLeftRightButton();
afx_msg void OnBnClickedBackMediaPressButton();
};
.cpp
IMPLEMENT_DYNAMIC(CToolsDlg, CBDialog)
CToolsDlg::CToolsDlg(CWnd* pParent /*=NULL*/)
: CBDialog(CToolsDlg::IDD, pParent)
{
}
CToolsDlg::~CToolsDlg()
{
}
void CToolsDlg::DoDataExchange(CDataExchange* pDX)
{
CBDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TOOLS_HOOD_BUTTON, m_HoodButton);
DDX_Control(pDX, IDC_MEDIA_FOREWARD_BUTTON, m_MediaForewardButton);
DDX_Control(pDX, IDC_MEDIA_BACKWARD_BUTTON, m_MediaBackwardButton);
DDX_Control(pDX, IDC_TOOLS_LEFT_RIGHT, m_LeftRightButton);
}
BEGIN_MESSAGE_MAP(CToolsDlg, CBDialog)
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_TIMER()
ON_BN_CLICKED(IDC_TOOLS_HOOD_BUTTON, &CToolsDlg::OnBnClickedToolsHoodButton)
ON_BN_CLICKED(IDC_MEDIA_FOREWARD_BUTTON, &CToolsDlg::OnBnClickedMediaForewardButton)
ON_BN_CLICKED(IDC_MEDIA_BACKWARD_BUTTON, &CToolsDlg::OnBnClickedMediaBackwardButton)
ON_BN_CLICKED(IDC_TOOLS_LEFT_RIGHT, &CToolsDlg::OnBnClickedLeftRightButton)
ON_BN_CLICKED(IDC_BACK_MEDIA_PRESS_BUTTON, &CToolsDlg::OnBnClickedBackMediaPressButton)
END_MESSAGE_MAP()
// CToolsDlg message handlers
BOOL CToolsDlg::OnInitDialog()
{
CBDialog::OnInitDialog();
// Window position
//////////////////////////////////////////////////////////////////////////
CMainFrame* mf = (CMainFrame*)AfxGetMainWnd();
RECT MFwinRect;
RECT ThiswinRect;
CWnd* fv = mf->m_wndSplitter.GetView( mf->m_wndSplitter.GetCurrentViewIndex(0,0) );
fv->GetWindowRect(&MFwinRect);
GetWindowRect(&ThiswinRect);
MoveWindow(
MFwinRect.right - (ThiswinRect.right - ThiswinRect.left) - 14, // X
MFwinRect.top + 14, // Y
(ThiswinRect.right - ThiswinRect.left), // nWidth
(ThiswinRect.bottom - ThiswinRect.top) ); // nHeight
// Set controls state
//////////////////////////////////////////////////////////////////////////
m_ToolsTips.Create(this);
m_ToolsTips.AddTool(&m_HoodButton, TOOLTIP_HOOD_BUTTON);
m_ToolsTips.AddTool(&m_MediaForewardButton, TOOLTIP_MEDIA_FOREWARD_BUTTON);
m_ToolsTips.AddTool(&m_MediaBackwardButton, TOOLTIP_MEDIA_BACKWARD_BUTTON);
m_ToolsTips.AddTool(&m_LeftRightButton, TOOLTIP_LEFT_RIGHT_BUTTON);
m_ToolsTips.SetDelayTime(1000);
m_ToolsTips.Activate(BARAK_PREFS->m_Params.m_bShowToolTips);
// Main timer loop (no need for now)
// SetTimer( 1, 1000, NULL );
return TRUE;
}
BOOL CToolsDlg::PreTranslateMessage(MSG* pMsg)
{
m_ToolsTips.RelayEvent(pMsg);
return CBDialog::PreTranslateMessage(pMsg);
}
void CToolsDlg::OnCancel()
{
// When closing the window, destroy it and not only hide (its a floating window).
DestroyWindow();
}
void CToolsDlg::OnTimer(UINT_PTR nIDEvent)
{
CBDialog::OnTimer(nIDEvent);
}
void CToolsDlg::OnBnClickedToolsHoodButton()
{
...
}
void CToolsDlg::OnBnClickedMediaForewardButton()
{
...
}
void CToolsDlg::OnBnClickedMediaBackwardButton()
{
...
}
void CToolsDlg::OnBnClickedLeftRightButton()
{
...
}
void CToolsDlg::OnBnClickedBackMediaPressButton()
{
...
}
I see that you are filling view with dialog content. Have you put focusing to your dialog? I think this mystic behavior happening only on first mouse click in your dialog (then dialog gets the focus). I'm just guessing :)
I'm trying to change the background color of a dialog box (win 7, vs2010,c++).
I tried to catch WM_CTLCOLOR ,WM_ERASEBKGND and change the color.
I manged to change in this way the backgroung color, but when the window is finish to upload itself, the color is back to default but I noticed that the frame is in the right color.
I think that I'm changing the window and not the dialog box or something like that.
I'm doing this with WTL (not AFX).
What should I do?
Try this:
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CAboutDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
CBrush myBrush(RGB(255, 255, 255)); // dialog background color
CBrush *pOld = pDC->SelectObject(&myBrush);
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOld); // restore old brush
return bRes; // CDialog::OnEraseBkgnd(pDC);
}
And have a look here
The better way will be to override WM_CTLCOLOR, background of controls such as STATIC will be fill with your color too.
BEGIN_MESSAGE_MAP(YourDlg, CDialogEx)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
...
HBRUSH YourDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
return (HBRUSH)GetStockObject(WHITE_BRUSH);
}
The above answer will work only if you don't have a tab inside dialog box it will color background of dialog box other the tab portion. For the tab portion you have to create a new derived class with base class CTabCtrl.
I am not able to access the private member variables from member function CAboutDlg::OnLButtonDown.
When I attempted to assign a new value to ellipseColor i get the undeclared identifier error. When I try to access it through its class CCSIT861a3VasilkovskiyDlg::ellipseColorthe compiler says that it is inaccessible.
What have I missed, and how can I access/modify these variable?
Header File:
#pragma once
// CCSIT861a3VasilkovskiyDlg dialog
class CCSIT861a3VasilkovskiyDlg : public CDialogEx
{
// Construction
public:
CCSIT861a3VasilkovskiyDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_CSIT861A3VASILKOVSKIY_DIALOG };
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();
DECLARE_MESSAGE_MAP()
private:
COLORREF ellipseColor;
COLORREF centerRectColor;
COLORREF rightRectColor;
CRect centerRect;
CRect rightRect;
CSize ellipse;
bool mouseCaptured;
};
Implementation File:
#include "stdafx.h"
#include "CSIT861a3 Vasilkovskiy.h"
#include "CSIT861a3 VasilkovskiyDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
// CCSIT861a3VasilkovskiyDlg dialog
CCSIT861a3VasilkovskiyDlg::CCSIT861a3VasilkovskiyDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CCSIT861a3VasilkovskiyDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
ellipseColor = RGB(255, 0, 0);
centerRectColor = RGB(0, 0, 0);
rightRectColor = RGB(255, 0, 0);
centerRect.left = 40;
centerRect.top = 20;
centerRect.right = 55;
centerRect.bottom = 80;
rightRect.left = 75;
rightRect.top = 35;
rightRect.right = 90;
rightRect.bottom = 50;
ellipse.cx = 10;
ellipse.cy = 10;
mouseCaptured = false;
}
void CCSIT861a3VasilkovskiyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CCSIT861a3VasilkovskiyDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
// CCSIT861a3VasilkovskiyDlg message handlers
BOOL CCSIT861a3VasilkovskiyDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CCSIT861a3VasilkovskiyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CCSIT861a3VasilkovskiyDlg::OnPaint()
{
//Create pen and pointer to the old pen
CPen blackPen;
blackPen.CreatePen(PS_SOLID, 1, RGB (0, 0, 0));
//Create a bursh
CBrush blackBrush(centerRectColor);
CBrush redBrush(rightRectColor);
CBrush hatchRedBrush(HS_CROSS, ellipseColor);
//Set up object for painting
CPaintDC dc (this);
CRect rect;
GetClientRect (&rect);
dc.SetMapMode (MM_ANISOTROPIC);
dc.SetWindowExt (100, 100);
dc.SetViewportExt (rect.Width (), rect.Height ());
//select pen
dc.SelectObject(&blackPen);
//Rectangle red interior color
dc.SelectObject(&redBrush);
dc.Rectangle(rightRect); //(75, 35, 90, 50);
//Rectangel black interior
dc.SelectObject(&blackBrush);//Select Brush
dc.Rectangle( centerRect);//(40, 20, 55, 80);
//Ellipse
dc.SelectObject(&hatchRedBrush);//Select Brush
dc.Ellipse(ellipse.cx, ellipse.cy, (ellipse.cx) + 10, (ellipse.cy) + 10);//10, 10, 20, 20);
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CCSIT861a3VasilkovskiyDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CAboutDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//SetCapture();
CClientDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetWindowExt(100, 100);
dc.SetViewportExt(rect.Width(), rect.Height());
CRect rectEllipse(10, 10, 20, 20);
CDialogEx::OnLButtonDown(nFlags, point);
}
void CAboutDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
ReleaseCapture ();
CDialogEx::OnLButtonUp(nFlags, point);
}
void CAboutDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDialogEx::OnMouseMove(nFlags, point);
}
Your OnLButtonDown() is a member function of CAboutDlg, but you are trying to access a private, non-static data member of CCSIT861a3VasilkovskiyDlg, which is a different class.
You probably meant to have functions OnLButtonDown(), OnLButtonUp(), and OnMouseMove() as member functions of CCSIT861a3VasilkovskiyDlg, and not as member functions of CAboutDlg.
I painted three objects onto a window using CPaintDC, and now I am trying to get one of them (the ellipse) to become draggable by using OnMouseMove event handler. I am just playing around with MFC and am lost as to how to get this to work.
This is what I have tried in OnMouseMove:
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetWindowExt(100, 100);
CRect rectEllipse(ellipse.cx, ellipse.cy,(ellipse.cx) + 10, (ellipse.cy) + 10);//(10, 10, 20, 20);dc.Ellipse(ellipse.cx, ellipse.cy, (ellipse.cx) + 10, (ellipse.cy) + 10);//10, 10, 20, 20);
//CPoint ellipseDest;
//dc.SetViewportExt(rect.Width(), rect.Height());
if (mouseCaptured)
{
ellipse.cx = point.x;
ellipse.cy = point.y;
InvalidateRect(rectEllipse, TRUE);
}
CDialogEx::OnMouseMove(nFlags, point);
Please find my code pasted below.
Thanks so much for the help.
#include "stdafx.h"
#include "CSIT861a3 Vasilkovskiy.h"
#include "CSIT861a3 VasilkovskiyDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
public:
// afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
// afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
// afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
// ON_WM_LBUTTONDOWN()
// ON_WM_LBUTTONUP()
// ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
// CCSIT861a3VasilkovskiyDlg dialog
CCSIT861a3VasilkovskiyDlg::CCSIT861a3VasilkovskiyDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CCSIT861a3VasilkovskiyDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
ellipseColor = RGB(255, 0, 0);
centerRectColor = RGB(0, 0, 0);
rightRectColor = RGB(255, 0, 0);
centerRect.left = 40;
centerRect.top = 20;
centerRect.right = 55;
centerRect.bottom = 80;
rightRect.left = 75;
rightRect.top = 35;
rightRect.right = 90;
rightRect.bottom = 50;
ellipse.cx = 10;
ellipse.cy = 10;
mouseCaptured = false;
}
void CCSIT861a3VasilkovskiyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CCSIT861a3VasilkovskiyDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
// CCSIT861a3VasilkovskiyDlg message handlers
BOOL CCSIT861a3VasilkovskiyDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CCSIT861a3VasilkovskiyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CCSIT861a3VasilkovskiyDlg::OnPaint()
{
//Create pen and pointer to the old pen
CPen blackPen;
blackPen.CreatePen(PS_SOLID, 1, RGB (0, 0, 0));
//Create a bursh
CBrush blackBrush(centerRectColor);
CBrush redBrush(rightRectColor);
CBrush hatchRedBrush(HS_CROSS, ellipseColor);
//Set up object for painting
CPaintDC dc (this);
CRect rect;
GetClientRect (&rect);
dc.SetMapMode (MM_ANISOTROPIC);
dc.SetWindowExt (100, 100);
dc.SetViewportExt (rect.Width (), rect.Height ());
//select pen
dc.SelectObject(&blackPen);
//Rectangle red interior color
dc.SelectObject(&redBrush);
dc.Rectangle(rightRect); //(75, 35, 90, 50);
//Rectangel black interior
dc.SelectObject(&blackBrush);//Select Brush
dc.Rectangle( centerRect);//(40, 20, 55, 80);
//Ellipse
dc.SelectObject(&hatchRedBrush);//Select Brush
dc.Ellipse(ellipse.cx, ellipse.cy, (ellipse.cx) + 10, (ellipse.cy) + 10);//10, 10, 20, 20);
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CCSIT861a3VasilkovskiyDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
//void CAboutDlg::OnLButtonDown(UINT nFlags, CPoint point)
//{
// // TODO: Add your message handler code here and/or call default
// //SetCapture();
// CClientDC dc(this);
// CRect rect;
// GetClientRect(&rect);
// dc.SetMapMode(MM_ANISOTROPIC);
// dc.SetWindowExt(100, 100);
// dc.SetViewportExt(rect.Width(), rect.Height());
// CRect rectEllipse(10, 10, 20, 20);
//
// ellipseColor = RGB(0,0,0);
//
// CDialogEx::OnLButtonDown(nFlags, point);
//}
//void CAboutDlg::OnLButtonUp(UINT nFlags, CPoint point)
//{
// // TODO: Add your message handler code here and/or call default
// ReleaseCapture ();
// CDialogEx::OnLButtonUp(nFlags, point);
//}
//void CAboutDlg::OnMouseMove(UINT nFlags, CPoint point)
//{
// // TODO: Add your message handler code here and/or call default
//
// CDialogEx::OnMouseMove(nFlags, point);
//}
void CCSIT861a3VasilkovskiyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetWindowExt(100, 100);
dc.SetViewportExt(rect.Width(), rect.Height());
CRect rectEllipse(ellipse.cx, ellipse.cy, 20, 20);//(10, 10, 20, 20);
CRgn circle;
dc.LPtoDP(rectEllipse);
circle.CreateEllipticRgnIndirect(rectEllipse);
if (circle.PtInRegion(point))
{
SetCapture();
mouseCaptured = true;
ellipseColor = RGB(0,0,255);
InvalidateRect(rectEllipse, FALSE);
}
CDialogEx::OnLButtonDown(nFlags, point);
}
void CCSIT861a3VasilkovskiyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
ReleaseCapture ();
mouseCaptured = false;
CDialogEx::OnLButtonUp(nFlags, point);
}
void CCSIT861a3VasilkovskiyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (mouseCaptured)
{
/*
Code to drag and drop and redraw ellipse
*/
InvalidateRect(rectEllipse, TRUE);
}
CDialogEx::OnMouseMove(nFlags, point);
}
I think Mark Ransom's comment is right, you need to invalidate two rectangles on MouseMove.
CRect rectEllipse(ellipse.cx, ellipse.cy,(ellipse.cx) + 10, (ellipse.cy) + 10);
if (mouseCaptured)
{ InvalidateRect(rectEllipse, TRUE);
ellipse.cx = point.x;
ellipse.cy = point.y;
CRect rectNew(ellipse.cx, ellipse.cy,(ellipse.cx) + 10, (ellipse.cy) + 10);
InvalidateRect(rectNew, TRUE);
}
Also, on OnLButtonUp()
if (mouseCaptured)
{ ellipseColor = RGB(255, 0, 0);
CRect rectEllipse(ellipse.cx, ellipse.cy,(ellipse.cx) + 10, (ellipse.cy) + 10);
InvalidateRect(rectEllipse, TRUE);
}