Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
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.
 
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 2-Apr-13 0:13am
Edited 2-Apr-13 0:51am
v3
Comments
Jochen Arndt at 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 at 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 at 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 at 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 at 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.
Mobile.Instinct at 2-Apr-13 7:23am
   
Hey thanks for your input. I tried the UpdateWindow() after Invalidate() but no luck yet. The drawing is happening but I have to minimize and then reopen the window again to see the graph.. but it does not keep getting updated as and when the values change...
Jochen Arndt at 2-Apr-13 7:33am
   
That is because resizing results in redrawing. So the data are plotted but the screen is not updated. You must now only find out why redrawing is not triggered.
 
As already noted: You call Invalidate() of the m_GraphWindowCtrl but handle WM_PAINT (OnPaint) for the CCurveDlg.

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

in
 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.
  Permalink  
Comments
Mobile.Instinct at 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)

  Print Answers RSS
0 OriginalGriff 406
1 Marcin Kozub 225
2 Sergey Alexandrovich Kryukov 205
3 Raul Iloc 170
4 Maciej Los 164
0 OriginalGriff 8,289
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,624
3 Maciej Los 4,989
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web03 | 2.8.1411023.1 | Last Updated 2 Apr 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100