Discussion:
Drawing a rectangle via mouse drag?
(too old to reply)
Charles Tam
2008-03-31 00:07:00 UTC
Permalink
In MFC 6, how do I draw a rectangle via a mouse drag?
Is there any example code I could look at?
Scott McPhillips [MVP]
2008-03-31 00:51:50 UTC
Permalink
Post by Charles Tam
In MFC 6, how do I draw a rectangle via a mouse drag?
Is there any example code I could look at?
Here's a minimal example:

void CSDIView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptStart = point;
m_ptEnd = point;
SetCapture();
}

void CSDIView::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ m_ptEnd = point;
Invalidate();
}
}

void CSDIView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ ReleaseCapture();
m_ptEnd = point;
Invalidate();
}
}

void CSDIView::OnDraw(CDC* pDC)
{
CRect r(m_ptStart, m_ptEnd);
pDC->Rectangle(&r);
}
--
Scott McPhillips [VC++ MVP]
Charles Tam
2008-03-31 04:16:00 UTC
Permalink
Hi Scott,

I've modified your code in OnMouseMove to support SDI applications. It
seems to be working fine. Please reply otherwise.

void CXxxDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
m_ptEnd = point;
Invalidate();
}

CRect r(m_ptStart, m_ptEnd);
CPaintDC dc(this);
dc.GetSafeHdc();
dc.Rectangle(&r);
}
Post by Scott McPhillips [MVP]
Post by Charles Tam
In MFC 6, how do I draw a rectangle via a mouse drag?
Is there any example code I could look at?
void CSDIView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptStart = point;
m_ptEnd = point;
SetCapture();
}
void CSDIView::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ m_ptEnd = point;
Invalidate();
}
}
void CSDIView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ ReleaseCapture();
m_ptEnd = point;
Invalidate();
}
}
void CSDIView::OnDraw(CDC* pDC)
{
CRect r(m_ptStart, m_ptEnd);
pDC->Rectangle(&r);
}
--
Scott McPhillips [VC++ MVP]
AliR (VC++ MVP)
2008-03-31 14:19:47 UTC
Permalink
What part of Scott's OnMouseMove did not support SDI? One has nothing to do
with other?

Why are you drawing your rectangle in the OnMouseMove method? All your
drawing code should be in OnPaint, just the way Scott posted it.

In your OnMouseMove, while there is capture you are recording the endpoint
and then invalidating the client area which will cause a WM_PAINT to get
posted after OnMouseMove returns, and then drawing a rect which will get
erased when the WM_PAINT from the Invalidate() call gets processed.

Anyway drawing anything in OnMouseMove is pointless.

AliR.
Post by Charles Tam
Hi Scott,
I've modified your code in OnMouseMove to support SDI applications. It
seems to be working fine. Please reply otherwise.
void CXxxDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
m_ptEnd = point;
Invalidate();
}
CRect r(m_ptStart, m_ptEnd);
CPaintDC dc(this);
dc.GetSafeHdc();
dc.Rectangle(&r);
}
Post by Scott McPhillips [MVP]
Post by Charles Tam
In MFC 6, how do I draw a rectangle via a mouse drag?
Is there any example code I could look at?
void CSDIView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptStart = point;
m_ptEnd = point;
SetCapture();
}
void CSDIView::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ m_ptEnd = point;
Invalidate();
}
}
void CSDIView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ ReleaseCapture();
m_ptEnd = point;
Invalidate();
}
}
void CSDIView::OnDraw(CDC* pDC)
{
CRect r(m_ptStart, m_ptEnd);
pDC->Rectangle(&r);
}
--
Scott McPhillips [VC++ MVP]
Scott McPhillips [MVP]
2008-03-31 14:33:30 UTC
Permalink
Post by Charles Tam
Hi Scott,
I've modified your code in OnMouseMove to support SDI applications. It
seems to be working fine. Please reply otherwise.
void CXxxDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
m_ptEnd = point;
Invalidate();
}
CRect r(m_ptStart, m_ptEnd);
CPaintDC dc(this);
dc.GetSafeHdc();
dc.Rectangle(&r);
}
CPaintDC is specialized for use only in a WM_PAINT handler. It is an error
to use it elsewhere. When painting outside of a WM_PAINT handler you should
use CClientDC.

It also does not make sense to call Invalidate() and then paint. The
Invalidate() is going to cause WM_PAINT as soon as you return, and that will
erase or overwrite your illegal painting.

Why are you trying to paint on a dialog?
--
Scott McPhillips [VC++ MVP]
Joseph M. Newcomer
2008-03-31 18:06:11 UTC
Permalink
See bleow...
Post by Charles Tam
Hi Scott,
I've modified your code in OnMouseMove to support SDI applications. It
seems to be working fine. Please reply otherwise.
void CXxxDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
****
GetCapture only has to be non-NULL. If you have capture, you get the message; if you
don't have capture, you're not in dragging mode. No need to compare to this
*****
Post by Charles Tam
{
m_ptEnd = point;
Invalidate();
*****
See my later post; typically you do not Invalidate() the whole area, or any part of it,
during dragging
****
Post by Charles Tam
}
CRect r(m_ptStart, m_ptEnd);
CPaintDC dc(this);
****
This makes no sense here. CPaintDC can only be used in OnPaint handlers
****
Post by Charles Tam
dc.GetSafeHdc();
****
This makes no sense because it does nothing.
****
Post by Charles Tam
dc.Rectangle(&r);
****
Probably wrong; you did not select the HOLLOW_BRUSH to fill, so you will get a solid white
rectangle that will overwrite everything. See my example.

Note that SDI is no different from any CWnd, so it is not clear what you had to "change"
to use it with SDI.
****
Post by Charles Tam
}
Post by Scott McPhillips [MVP]
Post by Charles Tam
In MFC 6, how do I draw a rectangle via a mouse drag?
Is there any example code I could look at?
void CSDIView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptStart = point;
m_ptEnd = point;
SetCapture();
}
void CSDIView::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ m_ptEnd = point;
Invalidate();
}
}
void CSDIView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{ ReleaseCapture();
m_ptEnd = point;
Invalidate();
}
}
void CSDIView::OnDraw(CDC* pDC)
{
CRect r(m_ptStart, m_ptEnd);
pDC->Rectangle(&r);
}
--
Scott McPhillips [VC++ MVP]
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
unknown
2008-07-25 21:05:42 UTC
Permalink
Hi all

I am new to C++,I tried the first, Drawing a rectangle via mouse drag? example by Scott McPhillips , it works fine ,, but
the 2ed example
Drawing a rectangle via mouse drag? by Joseph M. errors out saying
error C2660: 'DrawFocusRect' : function does not take 4 parameters.
Please let me know how to draw transparent rectangle , with a solid drak border.
Thanks
Priyanka
Scott McPhillips [MVP]
2008-07-25 21:39:07 UTC
Permalink
Post by unknown
Hi all
I am new to C++,I tried the first, Drawing a rectangle via mouse drag?
example by Scott McPhillips , it works fine ,, but
the 2ed example
Drawing a rectangle via mouse drag? by Joseph M. errors out saying
error C2660: 'DrawFocusRect' : function does not take 4 parameters.
Please let me know how to draw transparent rectangle , with a solid drak border.
Thanks
Priyanka
There are two DrawFocusRect functions, one is an API and one is a CDC member
function. Neither one of them takes 4 parameters! Neither one of them
draws with a solid dark border!

Why do you have 4 parameters? Perhaps you should show your code.
--
Scott McPhillips [VC++ MVP]
Ajay Kalra
2008-07-26 03:32:33 UTC
Permalink
You should see MSDN for simple things like this(method definitions). Why do
you have these parameters?

--
Ajay
Post by unknown
Hi all
I am new to C++,I tried the first, Drawing a rectangle via mouse drag?
example by Scott McPhillips , it works fine ,, but
the 2ed example
Drawing a rectangle via mouse drag? by Joseph M. errors out saying
error C2660: 'DrawFocusRect' : function does not take 4 parameters.
Please let me know how to draw transparent rectangle , with a solid drak border.
Thanks
Priyanka
Joseph M. Newcomer
2008-07-26 04:45:37 UTC
Permalink
It may be a typo in which case I will have to fix it, let me know where it is. When in
doubt, RTFM.
joe
Post by unknown
Hi all
I am new to C++,I tried the first, Drawing a rectangle via mouse drag? example by Scott McPhillips , it works fine ,, but
the 2ed example
Drawing a rectangle via mouse drag? by Joseph M. errors out saying
error C2660: 'DrawFocusRect' : function does not take 4 parameters.
Please let me know how to draw transparent rectangle , with a solid drak border.
Thanks
Priyanka
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
a***@gmail.com
2008-08-12 03:44:51 UTC
Permalink
//This would make a hollow brush
CClientDC dc(this);
dc.SelectStockObject(HOLLOW_BRUSH);
Joseph M. Newcomer
2008-03-31 18:02:31 UTC
Permalink
The classic rubber-banding approach is to do all the painting in OnMouseMove using one of
the complement-methods, such as XOR, XORNOT, etc.; each time you repaint the existing
rectangle and then draw the new one using CClientDC. When the mouse is released, you
typically Invalidate() and the OnPaint handler knows how to draw the selected items (e.g.,
reverse-video or some such). This is a classic from the Scribble tutorial

CPoint anchor;
CPoint endpoint;

void CMyClass::OnLButtonDown(...CPoint point)
{
anchor = endpoint = point;
CClientDC dc(this);
dc.DrawFocusRect(anchor.x, anchor.y, endpoint.x, endpoint.y);// very small rectangle
SetCapture();
}

void CMyClass::OnMouseMove(..., CPoint point)
{
if(GetCapture() != NULL)
{ /* rubber band */
CClientDC dc(this);
dc.DrawFocusRect(anchor.x, anchor.y, endpoint.x, endpoint.y);
endpoint = point;
dc.DrawFocusRect(anchor.x, anchor.y, endpoint.x, endpoint.y);
} /* rubber band */

void CMyClass::OnLButtonUp(..., CPoint point)
{
if(GetCapture() != NULL)
{ /* banding */
CClientDC dc(this);
dc.DrawFocusRect(anchor.x, anchor.y, endpoint.x, endpoint.y);
Selection = CRect(anchor.x, anchor.y, point.x, point.y);
ReleaseCapture();
InvalidateRect(&Selection);
} /* banding */

I think DrawFocusRect does an xor; if not, you will have to SetROP2 to select a
complementing mode.

The advantage of this technique is that it doesn't require redrawing everything, or for
that matter, anything, until the selection process has finished.
joe
Post by Charles Tam
In MFC 6, how do I draw a rectangle via a mouse drag?
Is there any example code I could look at?
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
d***@gmail.com
2019-07-16 15:27:41 UTC
Permalink
Post by Charles Tam
In MFC 6, how do I draw a rectangle via a mouse drag?
Is there any example code I could look at?
You will probably want to increase the size of the pen so it it easier to see.
This is done with the SPI_SETFOCUSBORDERWIDTH. After the function is done you should set it back to the old value because this is a system setting.


void CMyClass::OnLButtonDown(...CPoint point)
{
anchor = endpoint = point;

CClientDC dc(this);

dc.SelectObject(create_focus_pen());

dc.DrawFocusRect(anchor.x, anchor.y, endpoint.x, endpoint.y);// very small rectangle
SetCapture();
}

...


HPEN create_focus_pen()
{
LONG width;
LONG height;

unsigned int newheight;

newheight = 6;

SystemParametersInfo(SPI_SETFOCUSBORDERHEIGHT, 0, (unsigned int*)newheight, SPIF_SENDCHANGE);
SystemParametersInfo(SPI_SETFOCUSBORDERWIDTH, 0, (unsigned int*)newheight, SPIF_SENDCHANGE);

SystemParametersInfo(SPI_GETFOCUSBORDERHEIGHT, 0, &height, 0);
SystemParametersInfo(SPI_GETFOCUSBORDERWIDTH, 0, &width, 0);

LOGBRUSH lb = { }; // initialize to zero
lb.lbColor = 0xffffff; // white
lb.lbStyle = BS_HATCHED;
lb.lbHatch = HS_FDIAGONAL;

return ExtCreatePen(PS_GEOMETRIC | PS_DOT, width, &lb, 0, 0);
}

Continue reading on narkive:
Loading...