Solved

Drawing program - refreshing objects without redrawing the ENTIRE screen

Posted on 2000-03-04
15
195 Views
Last Modified: 2010-04-02
My questions are in the 2nd comment below this question:

Consider the following code:

#include <windows.h>
#include "resource.h"
#include "ObjectsDrawn.h"
#define ID_TIMER 1

int xCoordStart,
      yCoordStart,
      xCoordEnd,
      yCoordEnd,
      CollectionIndex;

bool FirstClick;

ObjectsDrawn Collection[100];



LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

TCHAR szAppName[] = TEXT ("MenuDemo") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     HWND     hwnd ;
     MSG      msg ;
     WNDCLASS wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = szAppName ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Menu Demonstration"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static int idColor [5] = { WHITE_BRUSH,  LTGRAY_BRUSH, GRAY_BRUSH,
                                DKGRAY_BRUSH, BLACK_BRUSH } ;
     static int iSelection = IDM_BKGND_WHITE ;
     HMENU      hMenu ;
     HDC hdc;
     switch (message)
     {
     case WM_COMMAND:
          hMenu = GetMenu (hwnd) ;
         
          switch (LOWORD (wParam))
          {
          case IDM_APP_EXIT:
               SendMessage (hwnd, WM_CLOSE, 0, 0) ;
               return 0 ;
             
          }
          break ;

              case WM_CREATE:
                    FirstClick = false;
                    CollectionIndex = 0;

              case WM_LBUTTONDOWN:
                    if (!FirstClick)
                    {
                          xCoordStart = LOWORD(lParam);
                          yCoordStart = HIWORD(lParam);                  
                          Collection[CollectionIndex].SetLineStart(xCoordStart,yCoordStart);
                          hdc = GetDC(hwnd);
                          MoveToEx(hdc,xCoordStart,yCoordStart,NULL);
                          ReleaseDC(hwnd, hdc);
                          FirstClick = true;
                    }
                    else if (FirstClick)
                    {                     
                          //InvalidateRect(hwnd,NULL,TRUE);                        
                          xCoordEnd = LOWORD(lParam);
                          yCoordEnd = HIWORD(lParam);
                          Collection[CollectionIndex].SetLineEnd(xCoordEnd,yCoordEnd);                        
                          Collection[CollectionIndex].DrawObject(hwnd);                        
                          FirstClick = false;
                          CollectionIndex++;
                    }
                   return 0;
              case WM_MOUSEMOVE:
                    if (FirstClick)
                    {
                          int counter;
                          xCoordEnd = LOWORD(lParam);
                          yCoordEnd = HIWORD(lParam);
                          Collection[CollectionIndex].SetLineEnd(xCoordEnd,yCoordEnd);
                          Collection[CollectionIndex].DrawObject(hwnd);                        
                          Sleep(100);
                          InvalidateRect(hwnd,NULL,TRUE);                        
                          for(counter = 0; counter < CollectionIndex; counter++)
                                Collection[counter].DrawObject(hwnd);
                    }
                    else if (!FirstClick)
                    {
                          int counter;
                                                    InvalidateRect(hwnd,NULL,TRUE);                        
                          for(counter = 0; counter < CollectionIndex; counter++)
                                Collection[counter].DrawObject(hwnd);
                    }

      case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}
0
Comment
Question by:knowlton
  • 10
  • 5
15 Comments
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Here is the code for ObjectsDrawn.cpp:

#include "ObjectsDrawn.h"

ObjectsDrawn::ObjectsDrawn()
{
      type = 1;
      
}      

void ObjectsDrawn::SetType(int temptype)
{
      type = temptype;
      
}      

int ObjectsDrawn::GetType()
{
      return type;
}      


void ObjectsDrawn::SetLineStart(int tempX,int tempY)
{
      xCoordStart = tempX;
      yCoordStart = tempY;
}      

void ObjectsDrawn::SetLineEnd(int tempX, int tempY)
{
      xCoordEnd = tempX;
      yCoordEnd = tempY;
}

int ObjectsDrawn::GetLineXStart()
{
  return xCoordStart;
}      

int ObjectsDrawn::GetLineYStart()
{
  return yCoordStart;
}      

int ObjectsDrawn::GetLineXEnd()
{
  return xCoordEnd;
}      

int ObjectsDrawn::GetLineYEnd()
{
  return yCoordEnd;
}      

void ObjectsDrawn::DrawLine(HWND &hwnd)
{
      HDC hdc;
      hdc = GetDC(hwnd);
      MoveToEx(hdc, xCoordEnd, yCoordEnd, NULL);
      LineTo(hdc, xCoordStart, yCoordStart);
      ReleaseDC(hwnd, hdc);
}      

void ObjectsDrawn::DrawObject(HWND &hwnd)
{
      if(type == 1)
            DrawLine(hwnd);
}

0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Now my questions:

This is how I want the program to function:

1)  Program starts.
2)  User left clicks somewhere in the client area, setting the starting endpoint of the line.
3)  As the user moves the mouse around on the screen, the LINE "rubber-bands" to each new mouse location, showing the user where the line will be drawn to if the mouse is clicked a second time.
4)  When the user clicks a second time, the line is drawn permanently and the information is stored in an array of "Objects".
5)  More lines can be drawn and the old line will still be preserved.

I hope this gives you an idea of what I am trying to do.

Now, as I have run the program, I can tell that the line information for each object is being preserved and all of the lines I have drawn previously are being stored and reproduced on demand during this for loop:

for(counter = 0; counter < CollectionIndex; counter++)
  Collection[counter].DrawObject(hwnd);

But I am refreshing the ENTIRE screen each time I draw.  I want a more elegant solution to all of this but I don't know what to do.

I have thought about passing in an OBJECT COLOR each time I draw the lines on the screen.  I could pass in the COLOR white to "erase" lines and the color black to drawn the lines, but this also seems like a hack for a better way.

I would appreciate any help someone could give me.

0
 
LVL 5

Expert Comment

by:Wyn
Comment Utility
Add a "if" condition to lines in WM_MOUSEMOVE:
like:
if(firsttime){  
InvalidateRect(hwnd,NULL,TRUE);
firsttime=false;
}

0
 
LVL 5

Expert Comment

by:Wyn
Comment Utility
But better.You need do all the drawing into a mem DC and bitblt() into your window'DC.This will prevent the refreshing.
Regards
W.Yinan
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Wyn:

I am rejecting your answer because I want to leave the question open to other comments.  I am sorry I should have explained that I just wanted comments for the time-being.

I understand what you mean about bitblt and the memDC, although I haven't actually tried this in Win32 I have done this type of thing in Delphi.  And yes, it does work quite well.

My one concern is how can I acheive the "rubberband" effect while I am drawing moving the mouse around prior to the second mouse-click?

Thanks!

Tom
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Can I still show the line "rubber-banding" while using the memDC and bitblt techniques?

0
 
LVL 5

Accepted Solution

by:
Wyn earned 100 total points
Comment Utility
change the code around DrawObject,for example:
HDC memdc;
RECT rect;
HBITMAP  bitmap;
  case WM_MOUSEMOVE:
  if (FirstClick)
  {
memdc=CreateCompatibleDC(0);
GetWindowRect(hwnd,&rect) ;
bitmap=CreateCompatibleBitmap(memdc,rect.rigth-rect.left,rect.bottom-rect.top);
HBITMAP oldbitmap=SelectObject(memdc,bitmap);
  for(counter = 0; counter < CollectionIndex; counter++)
  Collection[counter].DrawObject(memdc);
BltBit(....);
DeleteObject(SelectObjet(memdc,oldbitmap));
DeleteDC(memdc);
}
//.........


You should rewrite the DrawLine function,pass the memdc into it:
void ObjectsDrawn::DrawLine(HDC hdc)
{
MoveToEx(hdc, xCoordEnd, yCoordEnd, NULL);
LineTo(hdc, xCoordStart, yCoordStart);
}

Regards
W.Yinan
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 5

Expert Comment

by:Wyn
Comment Utility
How about this?
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
I will try your suggestions.

This may take me a few hours.  I am still learning this stuff.

Tom
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Wyn:

I appreciate your help, BUT I still don't get it.

What I need to do is draw and erase the line rapidly until the use clicks the left mouse button again.

I have made some changes to my code in an effort to use the memDc and BitBlit:

Here is my code as it stands now:

/*-----------------------------------------
   MENUDEMO.C -- Menu Demonstration
                 (c) Charles Petzold, 1998
  -----------------------------------------*/

#include <windows.h>
#include "resource.h"
#include "ObjectsDrawn.h"

int xCoordStart,
      yCoordStart,
      xCoordEnd,
      yCoordEnd,
      CollectionIndex,
      object_type;

const int INVALID = 0;
const int LINE = 1;
const int SQUARE = 2;
const int ELLIPSE = 3;

bool FirstClick;

ObjectsDrawn Collection[100];


LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

TCHAR szAppName[] = TEXT ("MenuDemo") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     HWND     hwnd ;
     MSG      msg ;
     WNDCLASS wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = szAppName ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
            MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                                    szAppName, MB_ICONERROR) ;
            return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Menu Demonstration"),
                                    WS_OVERLAPPEDWINDOW,
                                    CW_USEDEFAULT, CW_USEDEFAULT,
                                    CW_USEDEFAULT, CW_USEDEFAULT,
                                    NULL, NULL, hInstance, NULL) ;

       if (hwnd == NULL)
             {
                  MessageBox(NULL, TEXT("Not enough memory to create bitmap!"),
                        szAppName, MB_ICONERROR);
                  return 0;
             }

     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
            TranslateMessage (&msg) ;
            DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}


void GetLargestDisplayMode (int * pcxBitmap, int * pcyBitmap)
{
     DEVMODE devmode ;
     int     iModeNum = 0 ;

     * pcxBitmap = * pcyBitmap = 0 ;

     ZeroMemory (&devmode, sizeof (DEVMODE)) ;
     devmode.dmSize = sizeof (DEVMODE) ;
     
     while (EnumDisplaySettings (NULL, iModeNum++, &devmode))
     {
          * pcxBitmap = max (* pcxBitmap, (int) devmode.dmPelsWidth) ;
          * pcyBitmap = max (* pcyBitmap, (int) devmode.dmPelsHeight) ;
     }
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static BOOL      fLeftButtonDown, fRightButtonDown;
       static HBITMAP      hBitmap;
       static HDC            hdcMem;
       static int            cxBitmap, cyBitmap, cxClient, cyClient, xMouse, yMouse;
       HMENU                  hMenu ;
     HDC                  hdc;
       PAINTSTRUCT ps;

     switch (message)
     {
            case WM_COMMAND:
                  hMenu = GetMenu (hwnd) ;
                  switch (LOWORD (wParam))
                        {
                              case IDM_CLEAR:
                                    return 0 ;              
                              case IDM_APP_EXIT:
                                    SendMessage (hwnd, WM_CLOSE, 0, 0) ;
                                    return 0 ;
                              case IDM_EDIT_DRAWLINE:
                                    int iFlag;
                                    iFlag = GetMenuState(hMenu,IDM_EDIT_DRAWLINE,MF_BYCOMMAND);
                                    if(iFlag == 0)
                                          {
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWLINE,MF_CHECKED);
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWCIRCLE,MF_UNCHECKED);
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWRECT,MF_UNCHECKED);
                                                object_type = LINE;
                                          }
                                    return 0;
                              case IDM_EDIT_DRAWCIRCLE:
                                    iFlag = GetMenuState(hMenu,IDM_EDIT_DRAWCIRCLE,MF_BYCOMMAND);
                                    if(iFlag == 0)
                                          {
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWCIRCLE,MF_CHECKED);
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWLINE,MF_UNCHECKED);
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWRECT,MF_UNCHECKED);
                                                object_type = LINE;
                                          }
                                    return 0;
                              case IDM_EDIT_DRAWRECT:
                                    iFlag = GetMenuState(hMenu,IDM_EDIT_DRAWRECT,MF_BYCOMMAND);
                                    if(iFlag == 0)
                                          {
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWRECT,MF_CHECKED);
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWLINE,MF_UNCHECKED);
                                                CheckMenuItem(hMenu,IDM_EDIT_DRAWCIRCLE,MF_UNCHECKED);
                                                object_type = SQUARE;
                                          }
                                    return 0;

                              case IDM_APP_HELP:
                                    MessageBox (hwnd, TEXT ("Help not yet implemented!"),
                                          szAppName, MB_ICONEXCLAMATION | MB_OK) ;
                                    return 0 ;
               
                              case IDM_APP_ABOUT:
                                    MessageBox (hwnd, TEXT ("Menu Demonstration Program\n")
                                          TEXT ("(c) Charles Petzold, 1998"),
                                          szAppName, MB_ICONINFORMATION | MB_OK) ;
                                    return 0 ;
                        }
                  break ;

                  case WM_CREATE:
                        object_type = LINE;
                        GetLargestDisplayMode (&cxBitmap, &cyBitmap);
                        hdc = GetDC(hwnd);
                        hBitmap = CreateCompatibleBitmap(hdc, cxBitmap, cyBitmap);
                        hdcMem = CreateCompatibleDC(hdc);
                        ReleaseDC(hwnd, hdc);

                        if (!hBitmap)
                              {
                              DeleteDC(hdcMem);
                              return - 1;
                              }
                        SelectObject(hdcMem, hBitmap);
                        PatBlt(hdcMem, 0, 0, cxBitmap, cyBitmap, WHITENESS);
                        return 0;

                  case WM_SIZE:
                        cxClient = LOWORD(lParam);
                        cyClient = HIWORD(lParam);
                        return 0;


                  case WM_LBUTTONDOWN:
                        if(!fRightButtonDown)
                              SetCapture(hwnd);
                        if(!Collection[CollectionIndex].GetFirstCoordsStatus())
                              {
                                    xMouse = LOWORD (lParam);
                                    yMouse = HIWORD (lParam);
                                    Collection[CollectionIndex].SetLineStart(xMouse,yMouse);
                                    Collection[CollectionIndex].SetFirstCoordsStatus(true);
                                    MoveToEx(hdc,xMouse,yMouse,NULL);
                                    MoveToEx(hdcMem,xMouse,yMouse,NULL);                                    
                              }
                        else
                              {
                                    xMouse = LOWORD (lParam);
                                    yMouse = HIWORD (lParam);
                                    MoveToEx(hdc,xMouse,yMouse,NULL);
                                    MoveToEx(hdcMem,xMouse,yMouse,NULL);                                    
                                    Collection[CollectionIndex].SetLineEnd(xMouse,yMouse);
                                    Collection[CollectionIndex].SetFirstCoordsStatus(false);
                                    Collection[CollectionIndex].DrawObject(hwnd);
                                    CollectionIndex++;
                              }

                        return 0;

                  case WM_LBUTTONUP:
                        if (fLeftButtonDown)
                              SetCapture(NULL);
                        fLeftButtonDown = FALSE;
                        return 0;

                  case WM_RBUTTONDOWN:
                        if (!fLeftButtonDown)
                              SetCapture(hwnd);
                        xMouse = LOWORD(lParam);
                        yMouse = HIWORD(lParam);
                        fRightButtonDown = TRUE;
                        return 0;

                  case WM_RBUTTONUP:
                        if(fRightButtonDown)
                              SetCapture(NULL);
                        fRightButtonDown = FALSE;
                        return 0;

                  case WM_MOUSEMOVE:
                        if(Collection[CollectionIndex].GetFirstCoordsStatus())
                              {
                                    hdc = GetDC(hwnd);
                                    SelectObject(hdc,GetStockObject(fLeftButtonDown ? BLACK_PEN : WHITE_PEN));
                                    SelectObject(hdcMem,GetStockObject(fLeftButtonDown ? BLACK_PEN : WHITE_PEN));
                                    xMouse = (short) LOWORD(lParam);
                                    yMouse = (short) HIWORD(lParam);
                                    Collection[CollectionIndex].SetLineEnd(xMouse,yMouse);
                                    Collection[CollectionIndex].DrawObject(hwnd);
                                    ReleaseDC(hwnd, hdc);
                              }
                        if(!fLeftButtonDown && !fRightButtonDown)
                              return 0;
                        
                        return 0;

                  case WM_PAINT:
                        hdc = BeginPaint(hwnd, &ps);
                        int result;
                        //PatBlt(hdc, 0, 0, cxBitmap, cyBitmap, WHITENESS);
                        BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0,0, SRCCOPY);
                        EndPaint(hwnd, &ps);
                        return 0;

                  case WM_DESTROY:
                        DeleteDC(hdcMem);
                        DeleteObject(hBitmap);
                        PostQuitMessage (0) ;
                        return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Wyn:

Here is my new ObjectsDrawn class:

#include "ObjectsDrawn.h"

ObjectsDrawn::ObjectsDrawn()
{
      type = 1;
      
}      

void ObjectsDrawn::SetType(int temptype)
{
      type = temptype;
      StartCoordsSet = false;
      
}      

int ObjectsDrawn::GetType()
{
      return type;
}      

bool ObjectsDrawn::GetFirstCoordsStatus()
{
      return StartCoordsSet;
}      

void ObjectsDrawn::SetFirstCoordsStatus(bool tempstatus)
{
      StartCoordsSet = tempstatus;
}      

void ObjectsDrawn::SetLineStart(int tempX,int tempY)
{
      xCoordStart = tempX;
      yCoordStart = tempY;
}      

void ObjectsDrawn::SetLineEnd(int tempX, int tempY)
{
      xCoordEnd = tempX;
      yCoordEnd = tempY;
}

int ObjectsDrawn::GetLineXStart()
{
  return xCoordStart;
}      

int ObjectsDrawn::GetLineYStart()
{
  return yCoordStart;
}      

int ObjectsDrawn::GetLineXEnd()
{
  return xCoordEnd;
}      

int ObjectsDrawn::GetLineYEnd()
{
  return yCoordEnd;
}      

void ObjectsDrawn::DrawLine(HWND &hwnd)
{
      HDC hdc;
      hdc = GetDC(hwnd);
      MoveToEx(hdc, xCoordEnd, yCoordEnd, NULL);
      LineTo(hdc, xCoordStart, yCoordStart);
      ReleaseDC(hwnd, hdc);
}      

void ObjectsDrawn::DrawObject(HWND &hwnd)
{
      if(type == 1)
            DrawLine(hwnd);
}
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Okay.

Now what my program does is this:

I left click with my mouse.  This sets the START coordiates of the line.

As I move my mouse around the screen AFTER this first mouse click, a line is continuously REDRAWN from the START to the new mouse location.

When I click the mouse a second time, the final line is drawn and the entire process is reset.  The only PROBLEM is ALL of the previous lines are still there on the screen!  I want those extra lines to disappear as I move the mouse around until finally I left click again and the final (and ONLY) line is then drawn on the screen.

Can you explain your BitBlit code in more detail.  Explain each line to me, please:


YOU WROTE PREVIOUSLY:

change the code around DrawObject,for example:
HDC memdc;
RECT rect;
HBITMAP  bitmap;
  case WM_MOUSEMOVE:
  if (FirstClick)
  {
memdc=CreateCompatibleDC(0);
GetWindowRect(hwnd,&rect) ;
bitmap=CreateCompatibleBitmap(memdc,rect.rigth-rect.left,rect.bottom-rect.top);
HBITMAP oldbitmap=SelectObject(memdc,bitmap);
  for(counter = 0; counter < CollectionIndex; counter++)
  Collection[counter].DrawObject(memdc);
BltBit(....);
DeleteObject(SelectObjet(memdc,oldbitmap));
DeleteDC(memdc);
}
//.........


You should rewrite the DrawLine function,pass the memdc into it:
void ObjectsDrawn::DrawLine(HDC hdc)
{
MoveToEx(hdc, xCoordEnd, yCoordEnd, NULL);
LineTo(hdc, xCoordStart, yCoordStart);
}

============
How does this code allow me to "rubberband" the line around the screen as i move the mouse?  Do you understand what I mean by rubberbanding?

Thanks for your help!  I think with a little more explanation I can get this!

Tom
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Wyn:

I think I finally figured it out!

Here is my current WM_MOUSEMOVE:

case WM_MOUSEMOVE:
                        if(Collection[CollectionIndex].GetFirstCoordsStatus())
                              {
                                    int counter;
                                    hdc = GetDC(hwnd);
                                    SelectObject(hdc,GetStockObject(fLeftButtonDown ? BLACK_PEN : WHITE_PEN));
                                    SelectObject(hdcMem,GetStockObject(fLeftButtonDown ? BLACK_PEN : WHITE_PEN));
                                    xMouse = (short) LOWORD(lParam);
                                    yMouse = (short) HIWORD(lParam);
                                    Collection[CollectionIndex].SetLineEnd(xMouse,yMouse);
                                    PatBlt(hdc, 0, 0, cxBitmap, cyBitmap, WHITENESS);
                                    for(counter = 0; counter < CollectionIndex; counter++)
                                          Collection[counter].DrawObject(hwnd);
                                    Collection[CollectionIndex].DrawObject(hwnd);
                                    ReleaseDC(hwnd, hdc);
                              }
                        if(!fLeftButtonDown && !fRightButtonDown)
                              return 0;
                        
                        return 0;


There is a tiny bit of flicker, but the line rubber bands now!  

Thanks for your help.  You get the points!

0
 
LVL 5

Expert Comment

by:Wyn
Comment Utility
Why you give me the points?
Is my comments helpful?
However,thank you.
Best Regards
W.Yinan

Btw:what's rubberband exactly meaning?
(You told me and ,then,I can rehash the my code and try to explain it to you)

Thank for the pts ,i blush to get:)
0
 
LVL 5

Author Comment

by:knowlton
Comment Utility
Rubberbanding is like when you take a rubberband and stretch it between your fingers.  You can make it bigger or smaller but the basic object is still a rubberband.

When drawing a rectangle in a drawing program, rubberbanding refers to clicking with the mouse at a location, then dragging the mouse around the screen.  The rectangle grows bigger as you move the cursor away from the origin point, and smaller as you approach it, but the rectangle does not get permanently drawn until you click the mouse again.  Make sense?

Don't worry about the points.  You actually were quite helpful with your bitblt idea.  
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now