Click here to Skip to main content
15,886,067 members
Articles / Programming Languages / C++
Article

Dynamic Line Drawing Activex Control

Rate me:
Please Sign up or sign in to vote.
2.05/5 (6 votes)
15 Jan 20073 min read 35.8K   1.5K   23   4
Activex Control for Line Drawing at runtime

Sample Image - TestLine_Activex.gif

Introduction

For simple ActiveX Control’s example, I have seen, provides design time drawing of various shapes. In this example I tried to do in a very simple way to create a Line at runtime when the ActiveX control’s class is used, i.e. drawing a line in your application at runtime like it happens in MS Word using drawing tool. You can resize the line and move the line. A simple example for using this ActiveX is also attached herewith. This example can be extended to any shapes.

Background

When I have to create simple lines on the graph for various calculation of curves thought to create a simple line drawing ActiveX control which would help the user to draw the line at run time and get the results based on the line and curve intersections, projection etc.

Using the Code:

Download the ActiveX demo and compile the TestLine.dsw in VC 6.0 it will create the TestLine ActiveX control and then compile the TestDlg.dsw in VC 6.0 to see the demo of this ActiveX controls working. Click on the “Line” button to press the left button and move the mouse as you like and release the same a TestLine Control is created base on this operation. Double clicking on the line will provide option to resize of move the line.

Source Code Description

When the mouse is double clicked over the line, then:

void CTestLineCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
 // node_points variable is set so that nodal points can be drawn
 // for resizing or moving operation
 if (!node_points)
 {
     node_points = true;
     Invalidate();
 }
 ...

If the left mouse button is pressed on the middle of the line then moved the line is moved else if the left mouse button pressed on any of the ends of the line then the line is redrawn till the point where the mouse is released.

void CTestLineCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
 if (node_points)
 {
     // moving the control....!
     if (nodeRectMid.PtInRect(point))
     {
       moveLine = true;
       //save current cursor coordinate
       mPoint1 = point;
       ClientToScreen(&mPoint1); //pMsg->pt;
       mPoint2 = mPoint1;
     } else {// re-drawing the line..
         if (nodeRect1.PtInRect(point))
         {
           //node_points = false;
           lPoint1 = lPoint2;
           lPoint2 = point;
           drawLine = true;
         } else if (nodeRect2.PtInRect(point)) {
           //node_points = false;
           drawLine = true;
          }
     }
 }
 //...
 //...
}

If drawLine variable is set then on Mouse move draw a line on the parent by removing the old once the mouse is release move the control to the new position and erase the line.

If moveLine variable is set then move the line to the new position.

CTestLineCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
 if (drawLine)
 {
     CWnd* prnt = GetParent();
     // Draw the dotted line..! on the parent...!
     CPoint p1, p2, p3;
     // Get the first point and
     // then get the new point
     p1 = lPoint1;
     p2 = lPoint3;
     p3 = point;
     ClientToScreen(&p1);
     ClientToScreen(&p3);
     // store this point in terms
     // of screen for next use..!
     lPoint3 = p3;

     // Make the point for the parent.
     if (prnt)
     {
      prnt->ScreenToClient(&p1);
      prnt->ScreenToClient(&p2);
      prnt->ScreenToClient(&p3);
     }
     // Get the device context of the parent
     CDC *pdc = prnt->GetDC();
    
     // Redraw the old region
     int xEpsilon = 0;
     int yEpsilon = 0;
     CPoint pts[5];
    
     if (p2.x > p1.x )
     {
      xEpsilon = -2;
     } else {
      xEpsilon = 2;
     }
    
     if (p1.y > p1.y)
     {
      yEpsilon = -2;
     } else {
      yEpsilon = 2;
     }

 pts[0].x = p1.x + xEpsilon;
 pts[0].y = p1.y ;

 pts[1].x = p1.x + xEpsilon;
 pts[1].y = p1.y + yEpsilon;

 pts[2].x = p2.x - xEpsilon;
 pts[2].y = p2.y + yEpsilon;

 pts[3].x = p2.x - xEpsilon;
 pts[3].y = p2.y ;

 pts[4].x = pts[0].x;
 pts[4].y = pts[0].y;

 CRgn *rgn;
 rgn = new CRgn();
 rgn->CreatePolygonRgn(pts, 5, WINDING);
 prnt->InvalidateRgn(rgn);

 //prnt->Invalidate();
 // Draw the line..!

 CPen *myPen = new CPen(PS_DASH, 1, RGB(0, 0, 0));
 CPen* OldPen = pdc->SelectObject(myPen);

 pdc->MoveTo(p1.x, p1.y);
 pdc->LineTo(p3.x, p3.y);

 delete rgn;
 pdc->SelectObject(OldPen);
 delete myPen;
 }

 if(moveLine)
 {
  CWnd* prnt = GetParent();
  GetWindowRect(&MainRect);
  CPoint temp;
  temp.x = MainRect.left ;
  temp.y = MainRect.top ;

  if (prnt)
    prnt->ScreenToClient(&temp);

  int chX = (mPoint2.x - mPoint1.x);
  int chY = (mPoint2.y - mPoint1.y);

  mPoint1 = mPoint2;
  mPoint2 = point;
  ClientToScreen(&mPoint2); //pMsg->pt;

  MoveWindow(temp.x + chX,
  //count the relative position
  temp.y + chY,
  MainRect.Width(),
  //if the width doesn’t change
  MainRect.Height(),
  //if the height doesn’t change
  TRUE);
}

Once the left button is release set the drawLine or moveLine variable to false if they were previously set and set the region of Control window to that of line.

// // Now the rect is found change the window position and size<BR>// // Set the window<BR>// MoveWindow(temp.x,<BR>// temp.y,<BR>// w,<BR>// h,<BR>// FALSE);<BR>//<BR>// ...<BR>//<BR>// SetTheLineRgn();<BR>

Draw the line and node_point At runtime onDraw will not be called onPaint will be called for drawing on the control.

// dc.MoveTo(lPoint1.x, lPoint1.y);<BR>// dc.LineTo(lPoint2.x, lPoint2.y);<BR>//<BR>//<BR>// if (node_points)<BR>// {<BR>// if ((lPoint1.x != lPoint2.x) || (lPoint1.y != lPoint2.y))<BR>// {<BR>//<BR>// CalculateNodeAreas();<BR>// dc.Rectangle(nodeRect1);<BR>// dc.Rectangle(nodeRectMid);<BR>// dc.Rectangle(nodeRect2);<BR>// }<BR>// 

Sample application to use the code: TestDlg:<BR>
1. Create a Button called Line: On clicking on the button set the drawLine variable to true:

<BR>//OnDrawline()<BR>//{<BR>// // preparing to draw the line<BR>// <code>drawLine = true;</code><BR>//} 

2. On left button down record the first point

//void CTestDlg::OnLButtonDown(UINT nFlags, CPoint point)<BR>//{<BR>// // Record the first point.<BR>// if (drawLine)<BR>// {<BR>// <code>p1 = point;</code><BR>// }<BR>//...<BR>//}

3. On mouse move by pressing the left button record the second point.

//void CTestDlg::OnMouseMove(UINT nFlags, CPoint point)<BR>//{<BR>// if (drawLine && nFlags == MK_LBUTTON)<BR>// {<BR>// <code>p2 = point;</code><BR>// Invalidate();<BR>// }<BR>//<BR>//...<BR>//}

4 Now create the control with those to specified point

//void CTestDlg::OnLButtonUp(UINT nFlags, CPoint point)<BR>//{<BR>// if (drawLine)<BR>// {<BR>// drawLine = false;<BR>// p2 = point;<BR>// if (lineIndex < MAX_NO_OF_LINE)<BR>// {<BR>// myLine[lineIndex] = new CTestLine();<BR>// CTestLine* tLine = myLine[lineIndex];<BR>// lineIndex++;<BR>//<BR>// int x1, x2, y1, y2;<BR>// CRect rect;<BR>// if (p2.x > p1.x)<BR>// {<BR>// rect.left = p1.x;<BR>// rect.right = p2.x;<BR>// x1 = 0;<BR>// x2 = p2.x - p1.x;<BR>// } else {<BR>// rect.left = p2.x;<BR>// rect.right = p1.x;<BR>// x1 = 0;<BR>// x2 = p1.x - p2.x;<BR>// }<BR>//<BR>// if (p2.y > p1.y)<BR>// {<BR>// rect.top = p1.y;<BR>// rect.bottom = p2.y;<BR>// y1 = 0;<BR>// y2 = p2.y - p1.y;<BR>// } else {<BR>// rect.top = p2.y;<BR>// rect.bottom = p1.y;<BR>// y1 = 0;<BR>// y2 = p1.y - p2.y;<BR>// }<BR>//<BR>// tLine->Create("testLine", WS_CHILD | WS_VISIBLE, rect, this, 10, NULL);<BR>// tLine->ShowWindow(SW_SHOWNORMAL);<BR>// ClientToScreen(&p1);<BR>// ClientToScreen(&p2);<BR>// tLine->ScreenToClient(&p1);<BR>// tLine->ScreenToClient(&p2);<BR>// tLine->SetPoint1(p1.x, p1.y);<BR>// tLine->SetPoint2(p2.x, p2.y);<BR>// tLine->Invalidate();<BR>//<BR>// } else {<BR>// MessageBox("Unable to draw Line. Increase the No of Line!");<BR>// }<BR>//<BR>// Invalidate();<BR>//<BR>// }<BR>// CDialog::OnLButtonUp(nFlags, point);<BR>//}

Most important thing I learnt that understating the user operation and creating the combined region and setting the same for that line control’s window. This is my quick try to create the control as simple way as it can be. It might encounter to some bugs as it is not tested in all the environments. Most important thing I learnt that understating the user operation and creating the combined region and setting the same for that line control’s window.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionthe zipped folders can not download Pin
Jeffrey_Martin4-Aug-12 6:26
Jeffrey_Martin4-Aug-12 6:26 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey20-Feb-12 19:54
professionalManoj Kumar Choubey20-Feb-12 19:54 
Generalerror executing the demo project Pin
xupi12-Jul-07 1:32
xupi12-Jul-07 1:32 
Hi, I'm having problems when i compile the demo project to try it.
When I try to draw a line the program crashes!!!

Could you check it please??

thanks
Generalno files to download Pin
Muhammad Gouda16-May-07 23:59
Muhammad Gouda16-May-07 23:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.