home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 4.ddi / TDWEXMPL.ZIP / BCWDEMOB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  15.2 KB  |  533 lines

  1. /********************************************************************
  2.  *       Copyright (c) 1992 by Borland International, Inc.          *
  3.  *                                                                  *
  4.  *                           BCWDEMOB.C                             *
  5.  *                                                                  *
  6.  *  This program is one of three demo programs provided with Turbo  *
  7.  *  Debugger for Windows. It contains a memory bug you can find     *
  8.  *  using TDW and the chapter in the TD User's Guide that explains  *
  9.  *  how to debug a Windows program. The original, bug-free version  *
  10.  *  BCWDEMO.C, demonstrates how to write a simple Windows graphics  *
  11.  *  program in Borland C++.  It's called Simple Paint and provides  *
  12.  *  three objects the user can draw, a line, an ellipse, and a      *
  13.  *  rectangle.  Simple Paint also provides the user with three      *
  14.  *  choices of line thicknesses and three choices of colors, red,   *
  15.  *  green, and black.                                               *
  16.  ********************************************************************/
  17.  
  18. #define STRICT
  19.  
  20. #include <windows.h>
  21. #include "bcwdemo.h"
  22.  
  23. /*****************************************************
  24.  * FUNCTION PROTOTYPES
  25.  *****************************************************/
  26.  
  27. /*
  28.  * DoWMCommand processes WM_COMMAND messages.  WM_COMMAND
  29.  * is generated when the user selects something from the menu.
  30.  */
  31. int DoWMCommand(WORD wParam, HWND hWnd);
  32.  
  33. /*
  34.  * DoLButtonDown process WM_LBUTTONDOWN messages.  WM_LBUTTONDOWN
  35.  * is generated when the user presses the left mouse button.
  36.  */
  37. void DoLButtonDown(HWND hWnd,LONG lParam);
  38.  
  39. /*
  40.  * DoLButtonUp processes WM_LBUTTONUP messages.  WM_LBUTTONUP
  41.  * is generated when the user releases the left mouse button.
  42.  */
  43. void DoLButtonUp(HWND hWnd,LONG lParam);
  44.  
  45. /*
  46.  * DoMouseMove processes WM_MOUSEMOVE messages.  WM_MOUSEMOVE
  47.  * is generated when the user moves the mouse.
  48.  */
  49. void DoMouseMove(HWND hWnd,LONG lParam);
  50.  
  51. /*
  52.  * DoPaint processes WM_PAINT messages.  WM_PAINT is generated
  53.  * whenever UpdateWindow is called or another window is moved,
  54.  * revealing a portion of the window receiving this message.
  55.  */
  56. void DoPaint(HWND hWnd);
  57.  
  58. /*
  59.  * WndProc is the callback function (window proc)
  60.  * for the Simple Paint class of windows.
  61.  */
  62. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  63.  
  64. /*
  65.  * DrawShape draws a shape into a device context
  66.  * at a given location.
  67.  */
  68. void DrawShape(HDC hdc,int x,int y,int x2, int y2,int Shape,
  69.            int PenWidth,COLORREF PenColor,int Slope);
  70.  
  71. /***************************************************************
  72.  * Global Variables
  73.  ***************************************************************/
  74.  
  75. int CurrentShape = LINE;       /* Maintains the status of the shape
  76.                     * the user is drawing. Default is
  77.                     * to draw with a line.             */
  78.  
  79. int PenWidth = 3;           /* Maintains the current pen width.
  80.                     * Default width is medium.         */
  81.  
  82. COLORREF PenColor = RGB(255,0,0);  /* Maintains the current pen color.
  83.                     * Default color is red.            */
  84.  
  85.  
  86. /*
  87.  * Structure definition to track
  88.  * what shapes have been drawn.
  89.  */
  90. struct SSHAPE {
  91.     RECT     Points;       /* Location of the shape.           */
  92.     int     PenWidth,       /* Pen width for the shape.         */
  93.          theShape;       /* Shape this structure represents. */
  94.     COLORREF PenColor;       /* Color of the shape.              */
  95.     int     Slope;           /* Used to determine direction lines
  96.                     * should be drawn. If slope > 0 then
  97.                     * draw from UpperLeft to LowerRight.
  98.                     * Else draw from LowerLeft
  99.                     * to UpperRight.               */
  100. };
  101.  
  102. typedef struct SSHAPE SHAPE;
  103.  
  104. #define nPoints 100
  105. SHAPE thisShape[nPoints];       /* Array that stores the shapes
  106.                     * the user draws.              */
  107. int CurrentPoint = -1;           /* Indicates the number of shapes
  108.                     * the user has drawn.             */
  109.  
  110. /**********************************************************
  111.  * function WinMain
  112.  *    Standard WinMain function.
  113.  **********************************************************/
  114. #pragma argsused
  115. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  116.            LPSTR lpszCmdLine, int nCmdShow )
  117. {
  118.     WNDCLASS    wndClass;
  119.     MSG        msg;
  120.     HWND    hWnd;
  121.  
  122.     /*
  123.      * Register window class style if first
  124.      * instance of this program.
  125.      */
  126.     if ( !hPrevInstance )
  127.     {
  128.     wndClass.style        = CS_HREDRAW | CS_VREDRAW ;
  129.     wndClass.lpfnWndProc    = WndProc;
  130.     wndClass.cbClsExtra     = 0;
  131.     wndClass.cbWndExtra    = 0;
  132.     wndClass.hInstance     = hInstance;
  133.     wndClass.hIcon         = LoadIcon(hInstance, "IDI_SIMPLEPAINT");
  134.     wndClass.hCursor    = LoadCursor(NULL, IDC_ARROW );
  135.     wndClass.hbrBackground    = GetStockObject(WHITE_BRUSH );
  136.     wndClass.lpszMenuName    = szAppName;
  137.     wndClass.lpszClassName    = szAppName;
  138.  
  139.     if (!RegisterClass(&wndClass))
  140.     return FALSE;
  141.     }
  142.  
  143.     /*
  144.      * Create and display the window.
  145.      */
  146.     hWnd = CreateWindow(szAppName,"Simple Paint",
  147.             WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,
  148.             CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
  149.  
  150.     ShowWindow(hWnd, nCmdShow);
  151.     UpdateWindow(hWnd);
  152.  
  153.     while (GetMessage(&msg, NULL, 0, 0))
  154.     {
  155.     TranslateMessage(&msg );
  156.     DispatchMessage(&msg );
  157.     }
  158.     return 0;
  159. }
  160.  
  161. /*******************************************************
  162.  * function WndProc
  163.  *    Handles all messages received by the window
  164.  *******************************************************/
  165.  
  166. LRESULT CALLBACK WndProc (HWND hWnd, UINT Message,
  167.              WPARAM wParam, LPARAM lParam)
  168. {
  169.     switch(Message)
  170.     {
  171.     case WM_COMMAND:
  172.         return DoWMCommand(wParam, hWnd);
  173.  
  174.     case WM_LBUTTONDOWN:
  175.         DoLButtonDown(hWnd,lParam);
  176.         break;
  177.  
  178.     case WM_LBUTTONUP:
  179.         DoLButtonUp(hWnd,lParam);
  180.         break;
  181.  
  182.     case WM_MOUSEMOVE:
  183.         DoMouseMove(hWnd,lParam);
  184.         break;
  185.  
  186.     case WM_PAINT:
  187.         DoPaint(hWnd);
  188.         break;
  189.  
  190.     case WM_DESTROY:
  191.         PostQuitMessage(0);
  192.         break;
  193.  
  194.     default:
  195.         return DefWindowProc(hWnd,Message,wParam,lParam);
  196.     }
  197.     return 0;
  198. }
  199.  
  200. /*****************************************************************
  201.  * function DrawShape
  202.  *
  203.  *    Draws the shape given by Shape parameter using PenWidth
  204.  *    and PenColor in the rectangle bounded by x,y,x2,y2.  The
  205.  *    Slope parameter is used with line shapes to determine if
  206.  *    lines should be drawn with a negative or positive slope.
  207.  *****************************************************************/
  208.  
  209. void DrawShape(HDC hdc, int x, int y, int x2, int y2, int Shape,
  210.            int PenWidth, COLORREF PenColor, int Slope)
  211. {
  212.     HANDLE    saveObject;
  213. //DEBUG:    int         SaveROP;
  214.  
  215.     /*
  216.      * Create the proper pen for this shape.  Save the
  217.      * previously selected object from this DC.
  218.      */
  219.     saveObject = SelectObject(hdc, CreatePen(PS_SOLID,
  220.                          PenWidth,
  221.                          PenColor));
  222.     switch(Shape)
  223.     {
  224.     case LINE:
  225.         /*
  226.          *  Rectangles that save a shape's position must be stored
  227.          *  as upper-left and lower-right.  To draw a line from
  228.          *  upper-right to lower-left, the line must have a
  229.          *  negative slope.
  230.          */
  231.         if (Slope > 0)
  232.         {
  233.         MoveTo(hdc,x,y);
  234.         LineTo(hdc,x2,y2);
  235.         }
  236.         else
  237.         {
  238.         MoveTo(hdc,x,y2);
  239.         LineTo(hdc,x2,y);
  240.         }
  241.         break;
  242.  
  243.     case ELLIPSE:
  244.         Ellipse(hdc,x,y,x2,y2);
  245.         break;
  246.  
  247.     case RECTANGLE:
  248.         Rectangle(hdc,x,y,x2,y2);
  249.         break;
  250.     }
  251.     /*
  252.      *  Delete the currently selected object (the pen) and select
  253.      *    whatever object was currently selected when we entered
  254.      *    this routine.
  255.      */
  256.     SelectObject(hdc,saveObject);
  257. }
  258.  
  259. /****************************************************************
  260.  * function DoPaint
  261.  *    Processes WM_PAINT messages.  WM_PAINT is generated
  262.  *    whenever UpdateWindow is called or another window is moved,
  263.  *    revealing a portion of the window receiving this message.
  264.  ****************************************************************/
  265.  
  266. void DoPaint(HWND hWnd)
  267. {
  268.     int         i;
  269. //DEBUG:    int         saveROP;
  270.  
  271.     HDC        hdc,
  272.         hMemDC;
  273.  
  274.     RECT    theRect,
  275.         destRect;
  276.  
  277.     HBITMAP    theBitmap;
  278.     PAINTSTRUCT    ps;
  279.  
  280.     hdc = BeginPaint(hWnd,&ps);
  281.  
  282.     if (CurrentPoint >= 0)
  283.     {
  284.     /*
  285.      * Determine which rectangle on the window is invalid.
  286.      * If no rectangle is marked invalid, it will be a full
  287.      * window repaint.
  288.      */
  289.     GetUpdateRect(hWnd,&theRect,0);
  290.     if (IsRectEmpty(&theRect))
  291.         GetClientRect(hWnd,&theRect);
  292.  
  293.     /*
  294.      * Create a memory DC and bitmap the same
  295.      * size as the update rectangle.
  296.      */
  297.     hMemDC = CreateCompatibleDC(hdc);
  298.     theBitmap = CreateCompatibleBitmap(hdc,
  299.                        theRect.right-theRect.left,
  300.                        theRect.bottom-theRect.top);
  301.     SelectObject(hMemDC,theBitmap);
  302.  
  303.     /*
  304.      * Erase the memBitmap.
  305.      */
  306.     BitBlt(hMemDC, 0, 0,
  307.            theRect.right-theRect.left,
  308.            theRect.bottom-theRect.top,
  309.            hdc, 0, 0, SRCCOPY);
  310.  
  311.     /*
  312.      * Draw only those shapes that lie
  313.      * within the update rectangle.
  314.      */
  315.     for (i = 0; i <= CurrentPoint; ++i)
  316.     {
  317.         IntersectRect(&destRect, &thisShape[i].Points, &theRect);
  318.         if (!IsRectEmpty(&destRect))
  319.         DrawShape(hMemDC,
  320.               thisShape[i].Points.left-theRect.left,
  321.               thisShape[i].Points.top-theRect.top,
  322.               thisShape[i].Points.right-theRect.left,
  323.               thisShape[i].Points.bottom-theRect.top,
  324.               thisShape[i].theShape,thisShape[i].PenWidth,
  325.               thisShape[i].PenColor,thisShape[i].Slope);
  326.         /*
  327.          * Note that when drawing the shape, the shape's
  328.          * position was transformed so that the origin was
  329.          * at the upper-left corner of the update rectangle.
  330.          * This is the point (0,0) on the bitmap that will
  331.          * map onto (theRect.left,theRect.right).
  332.          */
  333.     }
  334.  
  335.     /*
  336.      * Finally, copy the bitmap onto the update rectangle.
  337.      */
  338.     BitBlt(hdc, theRect.left, theRect.top,
  339.            theRect.right-theRect.left,
  340.            theRect.bottom-theRect.top,
  341.            hMemDC, 0, 0, SRCCOPY);
  342.  
  343.     DeleteDC(hMemDC);
  344.     DeleteObject(theBitmap);
  345.     }
  346.     EndPaint(hWnd,&ps);
  347. }
  348.  
  349.  
  350. /**********************************************************
  351.  * static variables oldx, oldy, mouseDown
  352.  *    Used to maintain both the state of the mouse position
  353.  *    and the button status between mouse messages.
  354.  **********************************************************/
  355.  
  356. static    oldx = -1, oldy = -1, mouseDown = 0;
  357.  
  358. /******************************************************************
  359.  * function DoLButtonDown
  360.  *    When the left button on the mouse is pressed, this routine
  361.  *    saves the origin of this shape, the current pen parameters,
  362.  *    and the current shape into the shapes array.  The mouse
  363.  *    button is also marked as pressed.
  364.  ******************************************************************/
  365.  
  366. void DoLButtonDown(HWND hWnd, LONG lParam)
  367. {
  368.     /*
  369.      * Redirect all subsequent mouse movements to this
  370.      * window until the mouse button is released.
  371.      */
  372.     SetCapture(hWnd);
  373.     oldy = thisShape[++CurrentPoint].Points.top = HIWORD(lParam);
  374.     oldx = thisShape[CurrentPoint].Points.left = LOWORD(lParam);
  375.     thisShape[CurrentPoint].theShape = CurrentShape;
  376.     thisShape[CurrentPoint].PenWidth = PenWidth;
  377.     thisShape[CurrentPoint].PenColor = PenColor;
  378.  
  379.     mouseDown = 1;
  380.  
  381. }
  382.  
  383. /******************************************************************
  384.  * function DoLButtonUp
  385.  *    When the Left mouse button is released, this routine
  386.  *    allows other windows to receive mouse messages and saves
  387.  *    the position of the mouse as the other corner of a bounding
  388.  *    rectangle for the shape.
  389.  ******************************************************************/
  390.  
  391. void DoLButtonUp(HWND hWnd, LONG lParam)
  392. {
  393.     if (mouseDown == 0) return;
  394.     ReleaseCapture();
  395.  
  396.     /*
  397.      * For rectangles to work with the IntersectRect function,
  398.      * they must be stored as left, top, right, bottom.
  399.      */
  400.     SetRect(&thisShape[CurrentPoint].Points,
  401.         min(thisShape[CurrentPoint].Points.left, LOWORD(lParam)),
  402.         min(thisShape[CurrentPoint].Points.top, HIWORD(lParam)),
  403.         max(thisShape[CurrentPoint].Points.left, LOWORD(lParam)),
  404.         max(thisShape[CurrentPoint].Points.top, HIWORD(lParam)));
  405.  
  406.     /*
  407.      * if the origin of the line has changed, it should be drawn
  408.      * from upper-right to lower left and therefore has negative
  409.      * slope.  Otherwise it will have positive slope.
  410.      */
  411.     if (CurrentShape == LINE)
  412.     thisShape[CurrentPoint].Slope =
  413.         thisShape[CurrentPoint].Points.left ==
  414.         LOWORD(lParam) ||
  415.         thisShape[CurrentPoint].Points.top ==
  416.         HIWORD(lParam) ?
  417.         -1 : 1;
  418.  
  419.     /*
  420.      * Mark this region on the window as
  421.      * needing redrawing and force an update.
  422.      */
  423.     InvalidateRect(hWnd, &thisShape[CurrentPoint].Points, 0);
  424.     UpdateWindow(hWnd);
  425.     mouseDown = 0;
  426.     oldx = -1;
  427.     oldy = -1;
  428. }
  429.  
  430. static int SaveROP;
  431.  
  432. /**********************************************************************
  433.  * function DoMouseMove
  434.  *    When the mouse is moved and the button is down, this function
  435.  *    draws the current shape.  It uses the Raster Operation NOTXORPEN
  436.  *    to draw the shape.  When this mode is used, drawing the
  437.  *    same image twice returns the image to its original state.
  438.  *    NOTXORPEN turns black on black white, black on white black
  439.  *    and white on white white.
  440.  **********************************************************************/
  441.  
  442. void DoMouseMove(HWND hWnd,LONG lParam)
  443. {
  444.     HDC hdc;
  445.  
  446.     if (mouseDown)
  447.     {
  448.     hdc = GetDC(hWnd);
  449.     /*
  450.      * Erase the old shape.
  451.      */
  452.     SaveROP = SetROP2(hdc,R2_NOTXORPEN);
  453.     DrawShape(hdc, thisShape[CurrentPoint].Points.left,
  454.           thisShape[CurrentPoint].Points.top, oldx, oldy,
  455.           thisShape[CurrentPoint].theShape,
  456.           thisShape[CurrentPoint].PenWidth,
  457.           thisShape[CurrentPoint].PenColor, 1);
  458.     /*
  459.      * At this point, the slope must be positive because
  460.      * the coordinates could not have been switched.
  461.      * The next step is to draw the new shape.
  462.      */
  463.  
  464.     oldx = LOWORD(lParam);
  465.     oldy = HIWORD(lParam);
  466.     DrawShape(hdc, thisShape[CurrentPoint].Points.left,
  467.           thisShape[CurrentPoint].Points.top, oldx, oldy,
  468.           thisShape[CurrentPoint].theShape,
  469.           thisShape[CurrentPoint].PenWidth,
  470.           thisShape[CurrentPoint].PenColor, 1);
  471.     SetROP2(hdc,SaveROP);
  472.     ReleaseDC(hWnd,hdc);
  473.     }
  474.  
  475. }
  476.  
  477. /*********************************************************************
  478.  * function DoWMCommand
  479.  *    When a menu item is selected, this function changes the current
  480.  *    state of shape selections to match the user's menu selection.
  481.  *******************************************************************/
  482.  
  483. int DoWMCommand(WORD wParam, HWND hWnd)
  484. {
  485.     switch(wParam)
  486.     {
  487.     case MID_QUIT:
  488.        DestroyWindow(hWnd);
  489.         break;
  490.  
  491.     case MID_LINE:
  492.         CurrentShape = LINE;
  493.         break;
  494.  
  495.     case MID_ELLIPSE:
  496.         CurrentShape = ELLIPSE;
  497.         break;
  498.  
  499.     case MID_RECTANGLE:
  500.         CurrentShape = RECTANGLE;
  501.         break;
  502.  
  503.     case MID_THIN:
  504.         PenWidth = 1;
  505.         break;
  506.  
  507.     case MID_REGULAR:
  508.         PenWidth = 3;
  509.         break;
  510.  
  511.     case MID_THICK:
  512.         PenWidth = 5;
  513.         break;
  514.  
  515.     case MID_RED:
  516.         PenColor = RGB(255,0,0);
  517.         break;
  518.  
  519.     case MID_GREEN:
  520.         PenColor = RGB(0,255,0);
  521.         break;
  522.  
  523.     case MID_BLACK:
  524.         PenColor = RGB(0,0,0);
  525.         break;
  526.  
  527.     default:
  528.         return 0;
  529.     }
  530.  
  531.     return 1;
  532. }
  533.