# Working with OnPaint() and CRect/CPoint

This topic is 3035 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am working with Visual Studio and I am trying to learn how to draw simplistic shapes and objects. I have created a very simple dialog class which contains a group box which I have instantiated as m_ctrlView. Here is the painting logic:
void CTable::OnPaint()
{
CPaintDC dc(this);
OnPaintSeats(&dc, m_nSeatCount);
}

void CTable::OnPaintSeats(CPaintDC* pDC, int nSeatCount)
{
// Get the rect structure for the placement of the
// CStatic group control on the dialog box.
CRect rectView;
m_ctrlView.GetWindowRect(&rectView);
ScreenToClient(&rectView);

// Shrink the rectangle to add a buffer around the
// outside of the drawing area.
rectView.DeflateRect(40,40,40,40);

// Adjust the device context center point to the
// center location of the rectangle.
pDC->SetViewportOrg(rectView.CenterPoint());

// Some variable initializations
double dblPI        = 3.1415926;
int    nAngle       = 90;
int    nWidthOff    = 15;
int    nHeightOff   = 30;

// For each seat rectangle we want to draw, we iterate over
// points of an ellipse where the containing rect for the
// ellipse has a larger horizontal axis than a vertical.
//
// The ellipse is started at the 90 degree angle which puts
// it at the bottom center of the shape.  This is the first
// location we want to draw our seat rectangle.
for(int i=0; i < nSeatCount; )
{
float x = (rectView.Width()/2-nWidthOff)*cos(nAngle*dblPI/180);
float y = (rectView.Height()/2-nHeightOff)*sin(nAngle*dblPI/180);

// Based on the current point along the perimeter of
// the ellipse shape, we form a box that is 120 wide
// and 40 tall.
CRect seatBox(x-60, y-20, x+60, y+20);

// Move drawing cursor to the X,Y location
pDC->MoveTo(x,y);

// Draw the rectangle based on the seatBox rect
pDC->Rectangle(seatBox);

// Adjust the seatbox rect structure to screen coords and
// save it in a data structure for later processing when
ClientToScreen(&seatBox);
GetSeatByIndex(i)->SetRectangleRect(seatBox);

// Adjusts the angle to move to next from the center of
// the ellipse based on a full circle divided by the
// number of boxes we want to draw so they are evenly
// drawn along the perimeter of the ellipse.  Since we
// started at 90 degrees, the first box was at the exact
// bottom center of the ellipse shape.
nAngle += (360/nSeatCount);
if(nAngle>360) nAngle -= 360;

// increment to next seat
i++;
}
}

void CTable::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// For each seat that was drawn in the OnPaint()
// method, iterate over them and check if the
// double click was in a given box.  If so, then
// display a message.  If not, do nothing.
for(int i=0; GetMaxSeatCount(); i++) {
if( GetSeatByIndex(i)->GetRectangleRect().PtInRect(point) ) {
AfxMessageBox("You clicked in a box!");
break;
}
}
CDialog::OnLButtonDblClk(nFlags, point);
}


Now, great news is that the OnPaint() draws the rectangles where I want them, evenly distributed in the group box's rectangle; however, when I double click the left mouse button, sadly the message never appears. After some debugging work, it seems that the location where the rectangles were drawn versus the point coordinates that the left button click handler receives are off what appears to be on the Y axis. Any ideas why? Did I make a mistake in my drawing/calculations that is causing things to become off? I'm just learning so please any help is greatly appreciated. [Edited by - crancran on November 3, 2009 11:52:53 AM]

##### Share on other sites
You do stuff like this in your onPaint:

CRect rectView;
m_ctrlView.GetWindowRect(&rectView);
ScreenToClient(&rectView);

// Shrink the rectangle to add a buffer around the
// outside of the drawing area.
rect.DeflateRect(40,40,40,40);

// Adjust the device context center point to the
// center location of the rectangle.
pDC->SetViewportOrg(rectView.CenterPoint());

I see that you undo the ScreenToClient call before saving off a rectangle for later processing in OnClick, but you don't see seem to undo the DeflateRect, also try not undoing the screentoclient in the saved off rect and just calling clienttoScreen on the mouse click point in onClick

##### Share on other sites

Ok I commented out the DeflateRect call and I also removed the ClientToScreen() call when saving the rect off for later processing and calling ScreenToClient() on the point returned from the Double Click handler. Unfortunately, it still does not solve the problem. The handler's point triggers outside the originally drawn box below it for some reason :(.

##### Share on other sites

Does it have anything to do with the fact I adjust the (0,0) window origin to the center of the table?

I have even taken the logic as far as to create my own control derived from CStatic, set it up to receive the left button click & double click messages to see if it had something to do with drawing inside the dialog itself, and appears that I get the same problems with the offset whether it's drawn in a derived CStatic object called CTableView or if I draw it from within the dialog CTable.

Any help?

##### Share on other sites

I went back and adjusted my x/y calculations for my ellipse based on having the origin in the bottom right quadrent with respect to 0,0 being the top left corner of the client area and that seemed to have corrected the problem.