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

  1. /********************************************************************
  2.  *       Copyright (c) 1991 by Borland International, Inc.          *
  3.  *                                                                  *
  4.  *                           BCWDEMOA.C                             *
  5.  *                                                                  *
  6.  *  This program is one of three demo programs provided with Turbo  *
  7.  *  Debugger for Windows. It contains two bugs that you can find    *
  8.  *  using TDW and the chapter in the TD User's Guide that explains  *
  9.  *  how to debug an MS-Windows program. The original, bug-free ver- *
  10.  *  sion, BCWDEMO.C, demonstrates how to write a simple Windows     *
  11.  *  graphics program in Turbo C++.  It's called Simple Paint and    *
  12.  *  provides three objects the user can draw, a line, an ellipse,   *
  13.  *  and a rectangle.  Simple Paint also provides the user with      *
  14.  *  three choices of line thicknesses and three choices of colors,  *
  15.  *  red, 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.     if (CurrentPoint >= 0)
  279.     {
  280.     hdc = BeginPaint(hWnd,&ps);
  281.     /*
  282.      * Determine which rectangle on the window is invalid.
  283.      * If no rectangle is marked invalid, it will be a full
  284.      * window repaint.
  285.      */
  286.     GetUpdateRect(hWnd,&theRect,0);
  287.     if (IsRectEmpty(&theRect))
  288.         GetClientRect(hWnd,&theRect);
  289.  
  290.     /*
  291.      * Create a memory DC and bitmap the same
  292.      * size as the update rectangle.
  293.      */
  294.     hMemDC = CreateCompatibleDC(hdc);
  295.     theBitmap = CreateCompatibleBitmap(hdc,
  296.                        theRect.right-theRect.left,
  297.                        theRect.bottom-theRect.top);
  298.     SelectObject(hMemDC,theBitmap);
  299.  
  300.     /*
  301.      * Erase the memBitmap.
  302.      */
  303.     BitBlt(hMemDC, 0, 0,
  304.            theRect.right-theRect.left,
  305.            theRect.bottom-theRect.top,
  306.            hdc, 0, 0, SRCCOPY);
  307.  
  308.     /*
  309.      * Draw only those shapes that lie
  310.      * within the update rectangle.
  311.      */
  312.     for (i = 0; i <= CurrentPoint; ++i)
  313.     {
  314.         IntersectRect(&destRect, &thisShape[i].Points, &theRect);
  315.         if (!IsRectEmpty(&destRect))
  316.         DrawShape(hMemDC,
  317.               thisShape[i].Points.left-theRect.left,
  318.               thisShape[i].Points.top-theRect.top,
  319.               thisShape[i].Points.right-theRect.left,
  320.               thisShape[i].Points.bottom-theRect.top,
  321.               thisShape[i].theShape,thisShape[i].PenWidth,
  322.               thisShape[i].PenColor,thisShape[i].Slope);
  323.         /*
  324.          * Note that when drawing the shape, the shape's
  325.          * position was transformed so that the origin was
  326.          * at the upper-left corner of the update rectangle.
  327.          * This is the point (0,0) on the bitmap that will
  328.          * map onto (theRect.left,theRect.right).
  329.          */
  330.     }
  331.  
  332.     /*
  333.      * Finally, copy the bitmap onto the update rectangle.
  334.      */
  335.     BitBlt(hdc, theRect.left, theRect.top,
  336.            theRect.right-theRect.left,
  337.            theRect.bottom-theRect.top,
  338.            hMemDC, 0, 0, SRCCOPY);
  339.  
  340.     DeleteDC(hMemDC);
  341.     DeleteObject(theBitmap);
  342.     ReleaseDC(hWnd,hdc);
  343.     EndPaint(hWnd,&ps);
  344.      }
  345.  
  346. }
  347.  
  348.  
  349. /**********************************************************
  350.  * static variables oldx, oldy, mouseDown
  351.  *    Used to maintain both the state of the mouse position
  352.  *    and the button status between mouse messages.
  353.  **********************************************************/
  354.  
  355. static    oldx = -1, oldy = -1, mouseDown = 0;
  356.  
  357. /******************************************************************
  358.  * function DoLButtonDown
  359.  *    When the left button on the mouse is pressed, this routine
  360.  *    saves the origin of this shape, the current pen parameters,
  361.  *    and the current shape into the shapes array.  The mouse
  362.  *    button is also marked as pressed.
  363.  ******************************************************************/
  364.  
  365. void DoLButtonDown(HWND hWnd, LONG lParam)
  366. {
  367.     /*
  368.      * Redirect all subsequent mouse movements to this
  369.      * window until the mouse button is released.
  370.      */
  371.     SetCapture(hWnd);
  372.     oldy = thisShape[++CurrentPoint].Points.top = HIWORD(lParam);
  373.     oldx = thisShape[CurrentPoint].Points.left = LOWORD(lParam);
  374.     thisShape[CurrentPoint].theShape = CurrentShape;
  375.     thisShape[CurrentPoint].PenWidth = PenWidth;
  376.     thisShape[CurrentPoint].PenColor = PenColor;
  377.  
  378.     mouseDown = 1;
  379.  
  380. }
  381.  
  382. /******************************************************************
  383.  * function DoLButtonUp
  384.  *    When the Left mouse button is released, this routine
  385.  *    allows other windows to receive mouse messages and saves
  386.  *    the position of the mouse as the other corner of a bounding
  387.  *    rectangle for the shape.
  388.  ******************************************************************/
  389.  
  390. void DoLButtonUp(HWND hWnd, LONG lParam)
  391. {
  392.     ReleaseCapture();
  393.  
  394.     /*
  395.      * For rectangles to work with the IntersectRect function,
  396.      * they must be stored as left, top, right, bottom.
  397.      */
  398.     SetRect(&thisShape[CurrentPoint].Points,
  399.         min(thisShape[CurrentPoint].Points.left, LOWORD(lParam)),
  400.         min(thisShape[CurrentPoint].Points.top, HIWORD(lParam)),
  401.         max(thisShape[CurrentPoint].Points.left, LOWORD(lParam)),
  402.         max(thisShape[CurrentPoint].Points.top, HIWORD(lParam)));
  403.  
  404.     /*
  405.      * if the origin of the line has changed, it should be drawn
  406.      * from upper-right to lower left and therefore has negative
  407.      * slope.  Otherwise it will have positive slope.
  408.      */
  409.     if (CurrentShape == LINE)
  410.     thisShape[CurrentPoint].Slope =
  411.         thisShape[CurrentPoint].Points.left ==
  412.         LOWORD(lParam) ||
  413.         thisShape[CurrentPoint].Points.top ==
  414.         HIWORD(lParam) ?
  415.         -1 : 1;
  416.  
  417.     /*
  418.      * Mark this region on the window as
  419.      * needing redrawing and force an update.
  420.      */
  421.     InvalidateRect(hWnd, &thisShape[CurrentPoint].Points, 0);
  422.     UpdateWindow(hWnd);
  423.     mouseDown = 0;
  424.     oldx = -1;
  425.     oldy = -1;
  426. }
  427.  
  428. static int SaveROP;
  429.  
  430. /**********************************************************************
  431.  * function DoMouseMove
  432.  *    When the mouse is moved and the button is down, this function
  433.  *    draws the current shape.  It uses the Raster Operation NOTXORPEN
  434.  *    to draw the shape.  When this mode is used, drawing the
  435.  *    same image twice returns the image to its original state.
  436.  *    NOTXORPEN turns black on black white, black on white black
  437.  *    and white on white white.
  438.  **********************************************************************/
  439.  
  440. void DoMouseMove(HWND hWnd,LONG lParam)
  441. {
  442.     HDC hdc;
  443.  
  444.     if (mouseDown)
  445.     {
  446.     hdc = GetDC(hWnd);
  447.     /*
  448.      * Erase the old shape.
  449.      */
  450.     SaveROP = SetROP2(hdc,R2_NOTXORPEN);
  451.     DrawShape(hdc, thisShape[CurrentPoint].Points.left,
  452.           thisShape[CurrentPoint].Points.top, oldx, oldy,
  453.           thisShape[CurrentPoint].theShape,
  454.           thisShape[CurrentPoint].PenWidth,
  455.           thisShape[CurrentPoint].PenColor, 1);
  456.     /*
  457.      * At this point, the slope must be positive because
  458.      * the coordinates could not have been switched.
  459.      * The next step is to draw the new shape.
  460.      */
  461.  
  462.     oldx = LOWORD(lParam);
  463.     oldy = HIWORD(lParam);
  464.     DrawShape(hdc, thisShape[CurrentPoint].Points.left,
  465.           thisShape[CurrentPoint].Points.top, oldx, oldy,
  466.           thisShape[CurrentPoint].theShape,
  467.           thisShape[CurrentPoint].PenWidth,
  468.           thisShape[CurrentPoint].PenColor, 1);
  469.     SetROP2(hdc,SaveROP);
  470.     ReleaseDC(hWnd,hdc);
  471.     }
  472.  
  473. }
  474.  
  475. /*********************************************************************
  476.  * function DoWMCommand
  477.  *    When a menu item is selected, this function changes the current
  478.  *    state of shape selections to match the user's menu selection.
  479.  *******************************************************************/
  480.  
  481. int DoWMCommand(WORD wParam)
  482. {
  483.     switch(wParam)
  484.     {
  485.     case MID_QUIT:
  486.         PostQuitMessage(0);
  487.         break;
  488.  
  489.     case MID_LINE:
  490.         CurrentShape = LINE;
  491.         break;
  492.  
  493.     case MID_ELLIPSE:
  494.         CurrentShape = ELLIPSE;
  495.         break;
  496.  
  497.     case MID_RECTANGLE:
  498.         CurrentShape = RECTANGLE;
  499.         break;
  500.  
  501.     case MID_THIN:
  502.         PenWidth = 1;
  503.         break;
  504.  
  505.     case MID_REGULAR:
  506.         PenWidth = 3;
  507.         break;
  508.  
  509.     case MID_THICK:
  510.         PenWidth = 5;
  511.         break;
  512.  
  513.     case MID_RED:
  514.         PenColor = RGB(255,0,0);
  515.         break;
  516.  
  517.     case MID_GREEN:
  518.         PenColor = RGB(0,255,0);
  519.         break;
  520.  
  521.     case MID_BLACK:
  522.         PenColor = RGB(0,0,0);
  523.         break;
  524.  
  525.     default:
  526.         return 0;
  527.     }
  528.  
  529.     return 1;
  530. }
  531.