HomeC&C++WainTutorialsSamplesTip&TrickTools


And now a minor improvement to the line drawing, I will show how to show the line while moving the mouse.
The trick is here that we must remove the line we again, when the mouse moves. One way to do this is to draw the entire screen each time, but that would be slow and will mak the screen flicker.
A better way is to draw the line with at inverting pen, because if you draw the same line twice, it will disappear again.
In this new approach we will create the line when the button in clicked. We must change the LineClass because of this, and we must add a function to modify its end point:
class LineClass
{
public:
   LineClass(POINT aStart) :
      Start(aStart),
      End(aStart),
      First(true)
   {}

   void SetEnd(HDC &aDc, POINT aEnd)
   {
      Draw(aDc, true);
      End = aEnd;
      Draw(aDc, true);
   }
   void Draw(HDC &aDc, bool aMoving = false);
private:
   bool First;
   POINT Start;
   POINT End;
};
The First member variable is used because the first time the mouse is moved there is no line to remove.
The draw function got an additional paramter, which specify if it is to use a inverting pen to draw or not.
The SetEnd function first draw the line at the last last position, which will make it disapear, then it updates its position and draws itself again. Draw will in bot cases use the inverting pen.
The new Draw function will then look like this;
void LineClass::Draw(HDC &aDc, bool aMoving)
{
   if(First)
   {
      First = false;
      return;
   }

   if(aMoving)
   {
      SetROP2(aDc, R2_NOTXORPEN);
   }
   else
   {
      SetROP2(aDc, R2_COPYPEN);
   }
   HPEN Pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
   HPEN OldPen = (HPEN )SelectObject(aDc, Pen);
   MoveToEx(aDc, Start.x, Start.y, 0);
   LineTo(aDc, End.x, End.y);
   SelectObject(aDc, OldPen);
   DeleteObject(Pen);
}
The R2_NOTXORPEN parameter to SetROP2 sets the DC to output in XOR mode, that is inverting, R2_COPYPEN is the normal, non-inverting mode.
The button down function will now look this way;
void OnLButtonDown(HWND aHwnd, int aX, int aY)
{
   POINT P;
   P.x = aX;
   P.y = aY;
   LineClass Line(P);
   Lines.push_back(Line);
   IsDrawing = true;
}
But we must catch the mouse move event, so we add an entry to the switch in the window proc:
      case WM_MOUSEMOVE:
         OnMouseMove(hwnd, LOWORD(lParam), HIWORD(lParam));
         break;
The OnMouseMove function;
void OnMouseMove(HWND aHwnd, int aX, int aY)
{
   if(IsDrawing)
   {
      POINT P;
      P.x = aX;
      P.y = aY;
      HDC dc = GetDC(aHwnd);
      LineClass &Last = Lines.back();
      Last.SetEnd(dc, P);
   }
}
Lines.back() returns a reference to the last element in the vector, the one we are using now.
And finaly the button up function:
void OnLButtonUp(HWND aHwnd, int aX, int aY)
{
   if(IsDrawing)
   {
      POINT P;
      P.x = aX;
      P.y = aY;
      LineClass &Last = Lines.back();
      HDC dc = GetDC(aHwnd);
      Last.SetEnd(dc, P);
      Last.Draw(dc);
      ReleaseDC(aHwnd, dc);
      IsDrawing = false;
   }
}
The call to Draw will make the line to draw itself with a non inverting pen.
The complete code for the application can be found here