POLYLINE.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:17k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * POLYLINE.C
  3.  *
  4.  * Window procedure for the polyline drawing window and support functions.
  5.  * This window is not complicated.  On creation it allocates a block of
  6.  * memory for a POLYLINE structure that contains 20 POINTs.  We do not
  7.  * attempt to reallocate this array at all just to maintain simplicity.
  8.  * This sample is to demonstrate OLE, not LocalReAlloc.
  9.  *
  10.  * Copyright(c) Microsoft Corp. 1992-1994 All Rights Reserved
  11.  * Win32 version, January 1994
  12.  */
  13. #include <windows.h>
  14. #include "cosmo.h"
  15. /*
  16.  * HACK:  To fix some Invalid hDC rips, we need to supress certain
  17.  * operations on metafile DC's: GetMapMode, DPtoLP, LPtoDP.
  18.  * We use this flag to indicate supression.
  19.  */
  20. BOOL fMetaDC=FALSE;
  21. /*
  22.  * HPolylineWindowCreate
  23.  *
  24.  * Purpose:
  25.  *  Creates a Polyline window within the client area of hWndParent.
  26.  *
  27.  * Parameters:
  28.  *  hWndParent      HWND of the parent window.
  29.  *  hInstance       HINSTANCE of the application instance.
  30.  *
  31.  * Return Value:
  32.  *  HWND            Result of the CreateWindowEx call.
  33.  *
  34.  */
  35. HWND WINAPI HPolylineWindowCreate(HWND hWndParent, HINSTANCE hInstance)
  36.     {
  37.     RECT        rc;
  38.     HWND        hWndT;
  39.     /*
  40.      * Create the secondary window for this application in a
  41.      * shrunk client area.
  42.      */
  43.     GetClientRect(hWndParent, &rc);
  44.     InflateRect(&rc, -8, -8);
  45.     //Create the editor window.
  46.     hWndT=CreateWindowEx(WS_EX_NOPARENTNOTIFY, rgpsz[IDS_CLASSPOLYLINE]
  47.         , rgpsz[IDS_CLASSPOLYLINE], WS_CHILD | WS_VISIBLE, rc.left
  48.         , rc.top, rc.right-rc.left, rc.bottom-rc.top
  49.         , hWndParent, (HMENU)ID_POLYLINE, hInstance, NULL);
  50.     return hWndT;
  51.     }
  52. /*
  53.  * PolylineWndProc
  54.  *
  55.  * Purpose:
  56.  *  Window procedure for the polyline drawing window.
  57.  *
  58.  * Parameters:
  59.  *  The standard.
  60.  *
  61.  * Return Value:
  62.  *  Standard.
  63.  */
  64. LRESULT WINAPI PolylineWndProc(HWND hWnd, UINT iMsg
  65.     , WPARAM wParam, LPARAM lParam)
  66.     {
  67.     PAINTSTRUCT     ps;
  68.     HDC             hDC;
  69.     HWND            hWndParent;
  70.     HLOCAL          hMem;
  71.     LPPOLYLINE      ppl;
  72.     RECT            rc;
  73.     DWORD           dwRet=0L;
  74.    #ifdef WIN32
  75.     ppl=(LPPOLYLINE)(PSTR)GetWindowLong(hWnd, 0);
  76.    #else
  77.     ppl=(LPPOLYLINE)(PSTR)GetWindowWord(hWnd, 0);
  78.    #endif
  79.     if (WM_USER <= iMsg)
  80.         return LPolylineUserMessage(hWnd, iMsg, wParam, lParam, ppl);
  81.     switch (iMsg)
  82.         {
  83.         case WM_NCCREATE:
  84.             hMem=LocalAlloc(LPTR, CBPOLYLINE);
  85.             if (NULL==hMem)
  86.                 return 0L;
  87.            #ifdef WIN32
  88.             SetWindowLong(hWnd, 0, (LONG)hMem);
  89.            #else
  90.             SetWindowWord(hWnd, 0, (WORD)hMem);
  91.            #endif
  92.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  93.         case WM_NCDESTROY:
  94.            #ifdef WIN32
  95.             hMem=(HLOCAL)GetWindowLong(hWnd, 0);
  96.            #else
  97.             hMem=(HLOCAL)GetWindowWord(hWnd, 0);
  98.            #endif
  99.             LocalFree(hMem);
  100.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  101.         case WM_CREATE:
  102.             //Stash away the current window rectangle.
  103.             GetClientRect(hWnd, &rc);
  104.             RECTTORECTS(rc, ppl->rc);
  105.             ppl->wVerMaj=VERSIONMAJOR;
  106.             ppl->wVerMin=VERSIONMINOR;
  107.             ppl->cPoints=0;
  108.             break;
  109.         case WM_PAINT:
  110.             hDC=BeginPaint(hWnd, &ps);
  111.             if (0!=ppl->cPoints)
  112.                 {
  113.                 ppl->fDrawEntire=TRUE;
  114.                 PolylineDraw(hWnd, hDC, ppl);
  115.                 }
  116.             EndPaint(hWnd, &ps);
  117.             break;
  118.         case WM_LBUTTONDOWN:
  119.             //Stop if we are already at the limit.
  120.             if (CPOLYLINEPOINTS==ppl->cPoints)
  121.                 {
  122.                 MessageBeep(0);
  123.                 break;
  124.                 }
  125.             //Stuff the new point in the array.
  126.             ppl->rgpt[ppl->cPoints].x=LOWORD(lParam);
  127.             ppl->rgpt[ppl->cPoints].y=HIWORD(lParam);
  128.             ppl->cPoints++;
  129.             //Draw the lines to this new point only.
  130.             hDC=GetDC(hWnd);
  131.             ppl->fDrawEntire=FALSE;
  132.             PolylineDraw(hWnd, hDC, ppl);
  133.             ReleaseDC(hWnd, hDC);
  134.             hWndParent=GetParent(hWnd);
  135.            #ifdef WIN32
  136.             SendMessage(hWndParent, WM_COMMAND
  137.                 , MAKELONG(ID_POLYLINE, PLN_POINTCHANGE), (LPARAM)hWnd);
  138.            #else
  139.             SendMessage(hWndParent, WM_COMMAND
  140.                 , ID_POLYLINE, MAKELONG(hWnd, PLN_POINTCHANGE));
  141.            #endif
  142.             break;
  143.         default:
  144.             dwRet=DefWindowProc(hWnd, iMsg, wParam, lParam);
  145.             break;
  146.         }
  147.     return dwRet;
  148.     }
  149. /*
  150.  * LPolylineUserMessage
  151.  *
  152.  * Purpose:
  153.  *  Handles all window-specific messages WM_USER and greater,
  154.  *  for the Polyline window:
  155.  *
  156.  *  PLM_RECTSET:        Changes the size of the window and scales the
  157.  *                      data points.
  158.  *
  159.  *  PLM_POLYLINESET:    Sets the current data points and the rectangle
  160.  *                      used to generate the figure.
  161.  *
  162.  *  PLM_POLYLINEGET:    Retrieves the current data points and rectangle
  163.  *                      used to generate the figure.
  164.  *
  165.  *  PLM_POLYLINENEW:    Resets the data points to defaults, meaning
  166.  *                      a blank figure.
  167.  *
  168.  *  PLM_BACKUPUNDO:     Backs the figure up one point.
  169.  *
  170.  *  PLM_BITMAPGET:      Retrieves a bitmap (DDB) of the current image.
  171.  *
  172.  *  PLM_METAFILEGET:    Retrieves a metafile for the current image.
  173.  *
  174.  *  PLM_METAFILEPICTGET:Retrieves a METAFILEPICT structure of the image for
  175.  *                      use in clipboard I/O.
  176.  *
  177.  * Parameters:
  178.  *  hWnd            HWND of the Polyline window.
  179.  *  iMsg            UINT message to process.
  180.  *  wParam          WPARAM parameter of the message.
  181.  *  lParam          LPARAM pameter of the message.
  182.  *  ppl             LPPOLYLINE to the window's extra data structure.
  183.  *
  184.  * Return Value:
  185.  *  DWORD           Value to return from the window procedure
  186.  *                  that recieved the message.
  187.  */
  188. DWORD PASCAL LPolylineUserMessage(HWND hWnd, UINT iMsg, WPARAM wParam
  189.     , LPARAM lParam, LPPOLYLINE ppl)
  190.     {
  191.     DWORD           dwRet=0L;
  192.     HWND            hWndParent;
  193.     HBITMAP         hBmp, hBmpT;
  194.     HDC             hDC, hMemDC;
  195.     LPPOLYLINE      pplT;
  196.     LPMETAFILEPICT  pMF;
  197.     HGLOBAL         hMem;
  198.     HMETAFILE       hMF;
  199.     RECT            rc;
  200.     LPRECT          pRect;
  201.     UINT            i;
  202.     LONG            l, cx, cy, cxT, cyT;
  203.     hWndParent=GetParent(hWnd);
  204.     switch (iMsg)
  205.         {
  206.         case PLM_RECTSET:
  207.             /*
  208.              * Resize the window to the given size, letting WM_SIZE handlers
  209.              * take care of the rest.
  210.              */
  211.             pRect=(LPRECT)lParam;
  212.             /*
  213.              * Scale all the current points to new dimensions.  ppl->rc
  214.              * has the old dimensions, pRect points to the new.  We
  215.              * force each of cx and cy to 1 if they are zero to prevent
  216.              * exceptions.
  217.              */
  218.             RECTSTORECT(ppl->rc, rc);
  219.             cxT=rc.right  - rc.left;
  220.             cyT=rc.bottom - rc.top;
  221.             RECTTORECTS(ppl->rc, *pRect);
  222.             cx=pRect->right  - pRect->left;
  223.             cy=pRect->bottom - pRect->top;
  224.             //Prevent crashes
  225.             if (0L==cxT)
  226.                 cxT=1;
  227.             if (0L==cyT)
  228.                 cyT=1;
  229.             //Loop through each point, scaling if necessary.
  230.             for (i=0; i< ppl->cPoints; i++)
  231.                 {
  232.                 //Must use DWORD to insure proper scaling.
  233.                 if (cx!=cxT)
  234.                     {
  235.                     l=((LONG)ppl->rgpt[i].x*cx);
  236.                     ppl->rgpt[i].x=(short)(l/cxT);
  237.                     }
  238.                 if (cy!=cyT)
  239.                     {
  240.                     l=((LONG)ppl->rgpt[i].y*cy);
  241.                     ppl->rgpt[i].y=(short)(l/cyT);
  242.                     }
  243.                 }
  244.             SetWindowPos(hWnd, NULL, pRect->left, pRect->top, (int)cx
  245.                 , (int)cy, SWP_NOMOVE | SWP_NOZORDER);
  246.             //Check if we need to notify the parent.
  247.             if (0!=wParam)
  248.                 {
  249.                #ifdef WIN32
  250.                 SendMessage(hWndParent, WM_COMMAND
  251.                     , MAKELONG(ID_POLYLINE, PLN_SIZECHANGE), (LPARAM)hWnd);
  252.                #else
  253.                 SendMessage(hWndParent, WM_COMMAND
  254.                     , ID_POLYLINE, MAKELONG(hWnd, PLN_SIZECHANGE));
  255.                #endif
  256.                 }
  257.             //Insure repaint
  258.             InvalidateRect(hWnd, NULL, TRUE);
  259.             UpdateWindow(hWnd);
  260.             break;
  261.         case PLM_POLYLINESET:
  262.             /*
  263.              * Copy the structure in lParam to ppl and repaint to
  264.              * reflect the new point set.  Note that unlike the
  265.              * PLM_RECTSET message, we do no scaling, assuming that
  266.              * the rectangle in the POLYLINE structure is appropriate
  267.              * for the data.
  268.              */
  269.             pplT=(LPPOLYLINE)lParam;
  270.             *ppl=*pplT;
  271.             //Resize this window to fit the data and notify the parent.
  272.             SetWindowPos(hWnd, NULL, ppl->rc.left, ppl->rc.top
  273.                 , ppl->rc.right-ppl->rc.left, ppl->rc.bottom-ppl->rc.top
  274.                 , SWP_NOMOVE | SWP_NOZORDER);
  275.             if (0!=wParam)
  276.                 {
  277.                #ifdef WIN32
  278.                 SendMessage(hWndParent, WM_COMMAND
  279.                     , MAKELONG(ID_POLYLINE, PLN_SIZECHANGE), (LPARAM)hWnd);
  280.                #else
  281.                 SendMessage(hWndParent, WM_COMMAND
  282.                     , ID_POLYLINE, MAKELONG(hWnd, PLN_SIZECHANGE));
  283.                #endif
  284.                 }
  285.             //Insure a repaint.
  286.             InvalidateRect(hWnd, NULL, TRUE);
  287.             UpdateWindow(hWnd);
  288.             break;
  289.         case PLM_POLYLINEGET:
  290.             //Copy the structure in ppl to lParam.  No repaint needed.
  291.             pplT=(LPPOLYLINE)lParam;
  292.             *pplT=*ppl;
  293.             break;
  294.         case PLM_POLYLINENEW:
  295.             //Clean out the POLYLINE structure and repaint the window.
  296.             for (i=0; i< CPOLYLINEPOINTS; i++)
  297.                 {
  298.                 ppl->rgpt[i].x=0;
  299.                 ppl->rgpt[i].y=0;
  300.                 }
  301.             ppl->cPoints=0;
  302.             InvalidateRect(hWnd, NULL, TRUE);
  303.             UpdateWindow(hWnd);
  304.             break;
  305.         case PLM_BACKUPUNDO:
  306.             //Decrement the number of active points and repaint.
  307.             if (ppl->cPoints > 0)
  308.                 {
  309.                 ppl->cPoints--;
  310.                 InvalidateRect(hWnd, NULL, TRUE);
  311.                 UpdateWindow(hWnd);
  312.                 }
  313.             //Notify parent window of the change.
  314.            #ifdef WIN32
  315.             SendMessage(hWndParent, WM_COMMAND
  316.                 , MAKELONG(ID_POLYLINE, PLN_POINTCHANGE), (LPARAM)hWnd);
  317.            #else
  318.             SendMessage(hWndParent, WM_COMMAND
  319.                 , ID_POLYLINE, MAKELONG(hWnd, PLN_POINTCHANGE));
  320.            #endif
  321.             break;
  322.         case PLM_BITMAPGET:
  323.             /*
  324.              * Create and return a bitmap of the window contents.
  325.              * The bitmap is the size of the POLYLINE edit window.
  326.              */
  327.             hDC=GetDC(hWnd);
  328.             hMemDC=CreateCompatibleDC(hDC);
  329.             GetClientRect(hWnd, &rc);
  330.             hBmp=CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
  331.             if (NULL!=hBmp)
  332.                 {
  333.                 //Draw the POLYLINE into the bitmap.
  334.                 hBmpT=SelectObject(hMemDC, hBmp);
  335.                 ppl->fDrawEntire=TRUE;
  336.                 PolylineDraw(hWnd, hMemDC, ppl);
  337.                 ppl->fDrawEntire=FALSE;
  338.                 SelectObject(hMemDC, hBmpT);
  339.                 }
  340.             DeleteDC(hMemDC);
  341.             ReleaseDC(hWnd, hDC);
  342.             //Return the created bitmap handle.
  343.             dwRet=(DWORD)(UINT)hBmp;
  344.             break;
  345.         case PLM_METAFILEGET:
  346.             //Create a memory metafile and return its handle.
  347.             hDC=(HDC)CreateMetaFile(NULL);
  348.             hMF=NULL;
  349.             if (NULL!=hDC)
  350.                 {
  351.                 /*
  352.                  * This is absolutely essential to the metafile so it
  353.                  * can be scaled in the clipboard and any destination
  354.                  * application.
  355.                  */
  356.                 fMetaDC=TRUE;
  357.                 SetMapMode(hDC, MM_ANISOTROPIC);
  358.                 GetClientRect(hWnd, &rc);
  359.                 SetWindowOrgEx(hDC, 0, 0, NULL);
  360.                 SetWindowExtEx(hDC, rc.right, rc.bottom, NULL);
  361.                 ppl->fDrawEntire=TRUE;
  362.                 PolylineDraw(hWnd, hDC, ppl);
  363.                 ppl->fDrawEntire=FALSE;
  364.                 hMF=CloseMetaFile(hDC);
  365.                 fMetaDC=FALSE;
  366.                 }
  367.             dwRet=(DWORD)(UINT)hMF;
  368.             break;
  369.         case PLM_METAFILEPICTGET:
  370.             /*
  371.              * Create a METAFILEPICT structure for the clipboard.
  372.              * First attempt to get a metafile.
  373.              */
  374.             lParam=SendMessage(hWnd, PLM_METAFILEGET, 0, 0L);
  375.             hMF=(HMETAFILE)(UINT)lParam;
  376.             if (NULL==hMF)
  377.                 break;
  378.             //Allocate the METAFILEPICT structure.
  379.             hMem=GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE
  380.                 , sizeof(METAFILEPICT));
  381.             if (NULL==hMem)
  382.                 {
  383.                 DeleteMetaFile(hMF);
  384.                 break;
  385.                 }
  386.             /*
  387.              * Global lock only fails in PMODE if the selector is invalid
  388.              * (like it was discarded) or references a 0 length segment,
  389.              * neither of which can happen here.
  390.              */
  391.             pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  392.             pMF->hMF=hMF;
  393.             pMF->mm=MM_ANISOTROPIC;             //Required by OLE libraries.
  394.             //Insert the extents in MM_HIMETRIC units.
  395.             GetClientRect(hWnd, &rc);
  396.             RectConvertToHiMetric(hWnd, &rc);     //Found in CLIP.C
  397.             pMF->xExt=rc.right;
  398.             pMF->yExt=rc.bottom;
  399.             GlobalUnlock(hMem);
  400.             dwRet=(DWORD)(UINT)hMem;
  401.             break;
  402.         default:
  403.             break;
  404.         }
  405.     return dwRet;
  406.     }
  407. /*
  408.  * PolylineDraw
  409.  *
  410.  * Purpose:
  411.  *  Paints the current line in the polyline window.
  412.  *
  413.  * Parameters:
  414.  *  hWnd            HWND of the polyline window.
  415.  *  hDC             HDC to draw on, could be a metafile or printer DC.
  416.  *  ppl            LPPOLYLINE to the polyline structure.
  417.  *
  418.  * Return Value:
  419.  *  none
  420.  */
  421. void PASCAL PolylineDraw(HWND hWnd, HDC hDC, LPPOLYLINE ppl)
  422.     {
  423.     HBRUSH          hBrush, hBrushT;
  424.     HPEN            hPen, hPenT;
  425.     UINT            i, j;
  426.     UINT            nMM;
  427.     POINTS          pt;
  428.     POINT           rgpt[CPOLYLINEPOINTS];
  429.     RECT            rc;
  430.     COLORREF        cr;
  431.     GetClientRect(hWnd, &rc);
  432.     //Get the line color.
  433.     cr=GetSysColor(COLOR_WINDOWTEXT);
  434.     //Make a 32-bit working copy of the point array for DPtoLP.
  435.     for (i=0; i < ppl->cPoints; i++)
  436.         {
  437.         rgpt[i].x=ppl->rgpt[i].x;
  438.         rgpt[i].y=ppl->rgpt[i].y;
  439.         }
  440.     /*
  441.      * If the mapping mode is not MM_TEXT, convert the points to
  442.      * whatever mapping mode in in effect before drawing.
  443.      * This specifically supports metafiles in MM_ANISOTROPIC.
  444.      */
  445.     nMM=fMetaDC ? MM_TEXT : GetMapMode(hDC);
  446.     if (MM_TEXT!=nMM)
  447.         DPtoLP(hDC, rgpt, ppl->cPoints);
  448.     hPen=CreatePen(PS_SOLID, 1, cr);
  449.     hPenT=SelectObject(hDC, hPen);
  450.     hBrush=CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  451.     hBrushT=SelectObject(hDC, hBrush);
  452.     /*
  453.      * Either draw the entire figure or just a single point.  The
  454.      * entire figure also includes erasing the background completely,
  455.      * since hDC may be a metafile DC.  Drawing a single point just
  456.      * updates the figure for that new point.
  457.      */
  458.     if (ppl->fDrawEntire)
  459.         {
  460.         //Erase the background for bitmaps and metafiles.
  461.         SelectObject(hDC, GetStockObject(NULL_PEN));
  462.         Rectangle(hDC, rc.left, rc.top, rc.right+1, rc.bottom+1);
  463.         SelectObject(hDC, hPen);
  464.         /*
  465.          * If we are drawing the entire figure, then loop through each
  466.          * point drawing a line to each successive point.
  467.          */
  468.         for (i=0; i < ppl->cPoints; i++)
  469.             {
  470.             for (j=i; j < ppl->cPoints; j++)
  471.                 {
  472.                 MoveToEx(hDC, rgpt[i].x, rgpt[i].y, NULL);
  473.                 LineTo(hDC, rgpt[j].x, rgpt[j].y);
  474.                 }
  475.             }
  476.         }
  477.     else
  478.         {
  479.         /*
  480.          * If we are only drawing the last point, just cycle once
  481.          * through previous points.
  482.          */
  483.         //Get the last point entered in the array.
  484.         j=ppl->cPoints-1;
  485.         pt.x=(short)rgpt[j].x;
  486.         pt.y=(short)rgpt[j].y;
  487.         for (i=0; i < j; i++)
  488.             {
  489.             MoveToEx(hDC, pt.x, pt.y, NULL);
  490.             LineTo(hDC, rgpt[i].x, rgpt[i].y);
  491.             }
  492.         }
  493.     //If we only had one point, draw a dot to indicate it's position.
  494.     if (1==ppl->cPoints)
  495.         SetPixel(hDC, rgpt[0].x, rgpt[0].y, cr);
  496.     SelectObject(hDC, hPenT);
  497.     SelectObject(hDC, hBrushT);
  498.     DeleteObject(hBrush);
  499.     DeleteObject(hPen);
  500.     return;
  501.     }