Click here to Skip to main content
15,884,472 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello,
I am using a pre-defined function for plotting graphs in MFC i.e. Polybezier function that takes in multiple points and allows you to draw a curve. Basically I need it for a multithreaded application that plots the points as and when we receive it. Below is the code for it, kindly please let me know what is wrong with it.

C++
void CCurveDlg::DrawCurve(CDC& argDc)
{
   CDC* pDC =  &argDc;
   CBrush* pOldBrush = pDC->GetCurrentBrush();
   CPen* pOldPen = pDC->GetCurrentPen();

   CRect rectClient;
   m_GraphWindowCtrl.GetWindowRect(&rectClient);
   ScreenToClient(&rectClient); 

   CBrush brush;
   CBrush* pBrush;
   brush.CreateSolidBrush(RGB(0,255,0));  
   pBrush = pDC->SelectObject(&brush);

   CRect txtRectX,txtRectY;
   CPen pen;
   CPen* pPen;
   pen.CreatePen(PS_SOLID | PS_COSMETIC, 1, RGB(0,0,0));
   pPen = pDC->SelectObject(&pen);
   pDC->MoveTo(rectClient.TopLeft());
   CString tempStr;

   CPoint Pt;   
   Pt.x = rectClient.left + iSec;// iSec is just for updating it every second
   Pt.y = (rectClient.bottom - rectClient.top) - m_lStrainTotal/10000;

   if(rectClient.PtInRect(Pt))
      pDC->PolyBezier(&Pt, 20);

   iSec++;

   pDC->SelectObject(&pOldPen);
   pDC->SelectObject(&pOldBrush);
}


Any suggestions on where I am going wrong? It does not plot anything btw.
Posted
Updated 1-Apr-13 23:51pm
v3
Comments
Jochen Arndt 2-Apr-13 5:30am    
It is difficult to answer without knowing about the relationship of CCurveDlg, m_GraphWindowCtrl and the passed CDC.

rectClient coordinates are from m_GraphWindCtrl, will be relative to the CCurveDlg client area and are then used to plot the data. Are the resulting points inside your plot area?

Another problem may be the threads. UI elements of one thread should not be directly updated from another one.
Mobile.Instinct 2-Apr-13 5:41am    
Yes the points are inside the plot area. I am a bit confused over the fact that is it possible to update points using threads or will it automatically do using the OnPaint() function. DrawCurve(..) is in the OnPaint() function.
Jochen Arndt 2-Apr-13 6:46am    
When you use the 'Reply' button right above a comment, the original poster will get an email notification.

OnPaint() is called when updating of the control is requested (when UpdateWindow() or RedrawWindow() is called). If necessary, you must trigger updating yourself.

Is m_GraphWindowCtrl a child window of CCurveDlg? If so, you might move the code to m_GraphWindowCtrl::OnPaint().

To trigger the update from another thread, pass the handle to the graph window to the other thread, store it there in a member variable, and send a user defined message using the window handle after the plot data has been updated. The graph window must handle this user defined message and can call UpdateWindow() or RedrawWindow(). Using a user defined message ensures that no invalid cross-thread calls are used.
Mobile.Instinct 2-Apr-13 7:06am    
Yes m_GraphWindowCtrl is a member variable of the graph window that is a child window of the CCurveDlg. I am using m_GraphWindowCtrl.Invalidate() when the value is updated in the Thread. Will give it a try with RedrawWindow or UpdateWindow.
Jochen Arndt 2-Apr-13 7:16am    
Call UpdateWindow() after Invalidate() to trigger redrawing.

When calling m_GraphWindowCtrl.Invalidate(), you should update from OnPaint() of the same class (actually you are updating from CCurveDlg::OnPaint()).

Invalidate() is thread safe (can be called from other threads). But UpdateWindow() and RedrawWindow() should be only called from the GUI thread that owns the window.

1 solution

in
C++
CPoint Pt;
...
pDC->PolyBezier(&Pt, 20);

you are telling PolyBezier that you are passing an array of 20 POINT structures, but you actually have only a single one allocated and filled in Pt.

Also:
- ScreenY/YMeter are never used. So are OffsetX/Y.
- If your logic for coordinate calculation works can not be seen from the code. Just check it with your debugger.
- Make your life easier by using SaveDC / RestoreDC instead of saving / restoring all settings by hand. That way you are probably not going to forget one.
 
Share this answer
 
Comments
Mobile.Instinct 2-Apr-13 5:47am    
Oh ok thanks for that information but the thing is I have an array of 20 points but not in Pt. The variable 'm_lStrainTotal' get updated every time the thread is run and that in turn updates the Point 'Pt' which I am guessing should update the Polybezier function that would help me plot the curve.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900