home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c081_11 / 11.ddi / TDWEXMPL.ZIP / BCWDEMOB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-13  |  15.0 KB  |  532 lines

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