11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Chapter 13. Adding Special Features to Application<br />

{<br />

}<br />

return TRUE;<br />

Disabling Non-client Area Painting<br />

We also need to pay attention to non-client area. Although the window does not have a caption bar, it<br />

has resizable border, which also belongs to non-client area. By default, the border will be painted as a 3D<br />

frame, which can be used for resizing the window. To make it transparent, we need to handle message<br />

WM_NCPAINT. We don’t need to provide any implementation here because there is nothing to be painted. In<br />

the sample, this message is handled in CBalloonDlg::OnNcPaint(), which is an empty function:<br />

void CBalloonDlg::OnNcPaint()<br />

{<br />

}<br />

We do need to override CBalloonDlg::OnPaint() to paint the elliptical area. Within this function, an<br />

ellipse is drawn in the client area, also a pointer is drawn at the left bottom corner. Both ellipse and its<br />

pointer are painted using yellow color.<br />

Moving the Window with Mouse<br />

Because the application does not have caption bar, we must provide a method to let the window be<br />

moved through using mouse. This should be implemented by handling three messages: WM_LBUTTONDOWN,<br />

WM_LBUTTONUP and WM_MOUSEMOVE. When the left button is pressed down, we need to set the window<br />

capture. As the mouse moves (with left button held down), we need to move the window according to the<br />

new mouse position by calling function CWnd::MoveWindow(…). When the left button is released, we need to<br />

release the window capture.<br />

Two variables are declared in class CBalloonDlg for this purpose: Boolean type variable<br />

CBalloonDlg::m_bCapture and CPoint type variable CBalloonDlg::m_ptMouse. Here, CBalloonDlg::<br />

m_ptMouse is used to record the previous mouse position. Whenever the window needs to be moved, we<br />

call function CWnd::GetWindowRect(…) to obtain its current position and size, then offset the rectangle (The<br />

size and position of the window is stored in a CRect type variable) according to both current and previous<br />

mouse positions, and update variable CBalloonDlg::m_ptMosue. Since all the calculation is carried out in<br />

the desktop coordinate system, we need to call function CWnd::ClientToScreen(…) to convert the mouse<br />

position before using it (Mouse position is passed to the message handlers in the coordinate system of the<br />

application window). The following is the WM_MOUSEMOVE message handler implemented in the sample:<br />

void CBalloonDlg::OnMouseMove(UINT nFlags, CPoint point)<br />

{<br />

CRect rect;<br />

POINT pt;<br />

}<br />

CDialog::OnMouseMove(nFlags, point);<br />

if((nFlags & MK_LBUTTON) && m_bCapture)<br />

{<br />

pt=point;<br />

ClientToScreen(&pt);<br />

GetWindowRect(rect);<br />

rect.OffsetRect(CPoint(pt)-m_ptMouse);<br />

m_ptMouse=pt;<br />

MoveWindow(rect);<br />

}<br />

This implementation is slow, because when mouse moves a small distance, the whole window need to<br />

be redrawn at the new position. An alternative solution is to draw only the rectangular outline when mouse<br />

is moving (with the left button held down), and update the window only when the left button is released. To<br />

implement this, instead of calling function CWnd::MoveWindow(…) in WM_MOUSEMOVE message handler, we<br />

need to call function CDC::DrawDragRect(…) to erase the previous rectangle outline and draw a new one.<br />

407

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!