POLYWIN.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * POLYWIN.CPP
- * Polyline Component Chapter 23
- *
- * Window procedure for the polyline drawing window and support
- * functions.
- *
- * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
- *
- * Kraig Brockschmidt, Microsoft
- * Internet : kraigb@microsoft.com
- * Compuserve: >INTERNET:kraigb@microsoft.com
- */
- #include "polyline.h"
- /*
- * PolylineWndProc
- *
- * Purpose:
- * Window procedure for the polyline drawing window.
- */
- LRESULT APIENTRY PolylineWndProc(HWND hWnd, UINT iMsg
- , WPARAM wParam, LPARAM lParam)
- {
- PCPolyline ppl;
- PAINTSTRUCT ps;
- HDC hDC;
- POINTS pt;
- RECT rc;
- //CHAPTER23MOD
- COMMANDPARAMS(wID, wCode, hWndMsg);
- //End CHAPTER23MOD
- ppl=(PCPolyline)GetWindowLong(hWnd, PLWL_STRUCTURE);
- switch (iMsg)
- {
- case WM_CREATE:
- ppl=(PCPolyline)((LPCREATESTRUCT)lParam)->lpCreateParams;
- SetWindowLong(hWnd, PLWL_STRUCTURE, (LONG)ppl);
- ppl->m_hWnd=hWnd;
- break;
- case WM_PAINT:
- hDC=BeginPaint(hWnd, &ps);
- GetClientRect(hWnd, &rc);
- ppl->Draw(hDC, FALSE, TRUE, &rc, NULL);
- EndPaint(hWnd, &ps);
- break;
- case WM_LBUTTONDOWN:
- //CHAPTER23MOD
- //We become UI Active with mouse action
- if (!ppl->m_fUIActive && NULL!=ppl->m_pIOleIPSite)
- ppl->UIActivate();
- //End CHAPTER23MOD
- //Stop if we are already at the limit.
- if (CPOLYLINEPOINTS==ppl->m_pl.cPoints)
- {
- MessageBeep(0);
- break;
- }
- //Convert the points into 0-32767 range
- GetClientRect(hWnd, &rc);
- pt=MAKEPOINTS(lParam);
- ppl->PointScale(&rc, &pt, FALSE);
- ppl->m_pl.rgpt[ppl->m_pl.cPoints++]=pt;
- //Draw the lines to this new point only.
- hDC=GetDC(hWnd);
- ppl->Draw(hDC, FALSE, FALSE, &rc, NULL);
- ReleaseDC(hWnd, hDC);
- if (NULL!=ppl->m_pAdv)
- ppl->m_pAdv->OnPointChange();
- ppl->SendAdvise(OBJECTCODE_DATACHANGED);
- break;
- //CHAPTER23MOD
- case WM_COMMAND:
- if (ID_HATCHWINDOW==wID
- && HWN_BORDERDOUBLECLICKED==wCode)
- {
- ppl->m_pImpIOleObject->DoVerb(OLEIVERB_OPEN, NULL
- , ppl->m_pIOleClientSite, -1, NULL, NULL);
- }
- break;
- //End CHAPTER23MOD
- default:
- return DefWindowProc(hWnd, iMsg, wParam, lParam);
- }
- return 0L;
- }
- /*
- * CPolyline::Draw
- *
- * Purpose:
- * Paints the current line in the polyline window.
- *
- * Parameters:
- * hDC HDC to draw on, a metafile or printer DC.
- * fMetafile BOOL indicating if hDC is a metafile or not,
- * so we can avoid operations that RIP.
- * fEntire BOOL indicating if we should draw the entire
- * figure or not.
- * pRect LPRECT defining the bounds in which to draw.
- * ppl PPOLYLINEDATA to draw. If NULL, use current.
- *
- * Return Value:
- * None
- */
- void CPolyline::Draw(HDC hDC, BOOL fMetafile, BOOL fEntire
- , LPRECT pRect, PPOLYLINEDATA ppl)
- {
- HBRUSH hBrush;
- HPEN hPen;
- HGDIOBJ hObj1, hObj2;
- UINT i, j;
- int nDC;
- POINTS pt1,pt2;
- POINT rgpt[CPOLYLINEPOINTS];
- if (NULL==ppl)
- ppl=&m_pl;
- nDC=SaveDC(hDC);
- for (i=0; i < ppl->cPoints; i++)
- {
- rgpt[i].x=ppl->rgpt[i].x;
- rgpt[i].y=ppl->rgpt[i].y;
- }
- //Printer and frozen differences handled in IViewObject::Draw
- hPen=CreatePen(ppl->iLineStyle, 1, ppl->rgbLine);
- hObj1=SelectObject(hDC, hPen);
- hBrush=CreateSolidBrush(ppl->rgbBackground);
- hObj2=SelectObject(hDC, hBrush);
- SetBkColor(hDC, ppl->rgbBackground);
- /*
- * Either draw the entire figure or just a single point. The
- * entire figure also includes erasing the background completely,
- * since hDC may be a metafile DC. Drawing a single point just
- * updates the figure for that new point.
- */
- if (fEntire || 0==ppl->cPoints)
- {
- //Erase the background for bitmaps and metafiles.
- SelectObject(hDC, GetStockObject(NULL_PEN));
- Rectangle(hDC, pRect->left, pRect->top, pRect->right+1
- , pRect->bottom+1);
- SelectObject(hDC, hPen);
- /*
- * If we are drawing the entire figure, then loop through
- * each point drawing a line to each successive point.
- */
- for (i=0; i < ppl->cPoints; i++)
- {
- for (j=i; j < ppl->cPoints; j++)
- {
- pt1.x=(short)rgpt[i].x;
- pt1.y=(short)rgpt[i].y;
- pt2.x=(short)rgpt[j].x;
- pt2.y=(short)rgpt[j].y;
- PointScale(pRect, &pt1, TRUE);
- PointScale(pRect, &pt2, TRUE);
- MoveToEx(hDC, pt1.x, pt1.y, NULL);
- LineTo(hDC, pt2.x, pt2.y);
- }
- }
- }
- else
- {
- /*
- * If we are only drawing the last point, just cycle once
- * through previous points.
- */
- //Get the last point entered in the array.
- j=ppl->cPoints-1;
- pt1.x=(short)rgpt[j].x;
- pt1.y=(short)rgpt[j].y;
- PointScale(pRect, &pt1, TRUE);
- for (i=0; i < j; i++)
- {
- pt2.x=(short)rgpt[i].x;
- pt2.y=(short)rgpt[i].y;
- PointScale(pRect, &pt2, TRUE);
- MoveToEx(hDC, pt1.x, pt1.y, NULL);
- LineTo(hDC, pt2.x, pt2.y);
- }
- }
- //If we have one point, draw a dot to indicate it's position.
- if (1==ppl->cPoints)
- {
- pt1.x=(short)rgpt[0].x;
- pt1.y=(short)rgpt[0].y;
- PointScale(pRect, &pt1, TRUE);
- SetPixel(hDC, pt1.x, pt1.y, m_pl.rgbLine);
- }
- SelectObject(hDC, hObj1);
- SelectObject(hDC, hObj2);
- DeleteObject(hBrush);
- DeleteObject(hPen);
- RestoreDC(hDC, nDC);
- return;
- }
- /*
- * CPolyline::PointScale
- *
- * Purpose:
- * Scales a point to or from a relative window coordinate to a
- * 0-32767 coordinate.
- *
- * Parameters:
- * pRect LPRECT of the window.
- * ppt LPPOINTS to convert
- * fScaleToWindow BOOL indicating direction of scaling.
- *
- * Return Value:
- * None
- */
- void CPolyline::PointScale(LPRECT pRect, LPPOINTS ppt
- , BOOL fScaleToWindow)
- {
- DWORD cx, cy;
- //Window size
- cx=(DWORD)(pRect->right-pRect->left);
- cy=(DWORD)(pRect->bottom-pRect->top);
- //Prevent crashes
- if (0L==cx) cx=1;
- if (0L==cy) cy=1;
- //Must use DWORD to insure proper scaling.
- /*
- * As an in-proc server we may not have a rectangle where the
- * top left was (0,0) which was always true when we drew to
- * a Polyline window. But this may be a container's hDC in
- * which case we'd better place the points in the container's
- * rectangle. That is, we have to add/subtract pRect->left
- * and ->top in these calculations.
- */
- if (fScaleToWindow)
- {
- ppt->x=pRect->left+(UINT)(((DWORD)ppt->x*cx) >> 15);
- ppt->y=pRect->top+(UINT)(((DWORD)ppt->y*cy) >> 15);
- }
- else
- {
- ppt->x=(UINT)(((DWORD)(ppt->x - pRect->left) << 15)/cx);
- ppt->y=(UINT)(((DWORD)(ppt->y - pRect->top) << 15)/cy);
- }
- return;
- }
- /*
- * PolyDlgProc
- *
- * Purpose:
- * Dialog procedure for a window in which to display the Polyline
- * for editing. This pretty much handles all editing functionality
- * for the embedded object.
- */
- BOOL APIENTRY PolyDlgProc(HWND hDlg, UINT iMsg
- , WPARAM wParam, LPARAM lParam)
- {
- PCPolyline ppl=NULL;
- RECT rc;
- UINT uID, uTemp;
- UINT cx, cy;
- //CHAPTER23MOD
- //hWnd and pt variables moved to CalcPolyRectInDialog.
- //End CHAPTER23MOD
- #ifdef WIN32
- ppl=(PCPolyline)GetProp(hDlg, PROP_POINTER);
- #else
- WORD w1, w2;
- w1=(WORD)GetProp(hDlg, PROP_SELECTOR);
- w2=(WORD)GetProp(hDlg, PROP_OFFSET);
- ppl=(PCPolyline)MAKELP(w1, w2);
- #endif
- switch (iMsg)
- {
- case WM_INITDIALOG:
- ppl=(PCPolyline)lParam;
- ppl->m_hDlg=hDlg;
- #ifdef WIN32
- //Properties are 32-bits in Win32
- SetProp(hDlg, PROP_POINTER, (HANDLE)ppl);
- #else
- SetProp(hDlg, PROP_SELECTOR, (HANDLE)SELECTOROF(ppl));
- SetProp(hDlg, PROP_OFFSET, (HANDLE)OFFSETOF(ppl));
- #endif
- //CHAPTER23MOD
- //Get the rectangle that Polyline occupies
- CalcPolyRectInDialog(hDlg, &rc);
- //End CHAPTER23MOD
- //Try to create the window.
- ppl->m_pImpIPolyline->Init(hDlg, &rc, WS_CHILD | WS_VISIBLE
- , ID_POLYLINE);
- //Set the initial line style radiobutton.
- ppl->m_pImpIPolyline->LineStyleGet(&uTemp);
- CheckRadioButton(hDlg, ID_LINESOLID, ID_LINEDASHDOTDOT
- , uTemp+ID_LINEMIN);
- return FALSE;
- case WM_SHOWWINDOW:
- if (LOWORD(wParam))
- {
- //Center the dialog on the screen
- cx=GetSystemMetrics(SM_CXSCREEN);
- cy=GetSystemMetrics(SM_CYSCREEN);
- GetWindowRect(hDlg, &rc);
- SetWindowPos(hDlg, NULL, (cx-(rc.right-rc.left))/2
- , (cy-(rc.bottom-rc.top))/2, 0, 0, SWP_NOZORDER
- | SWP_NOSIZE);
- //We didn't SetFocus from WM_INITDIALOG. Do it now.
- SetFocus(GetDlgItem(hDlg, IDOK));
- }
- break;
- case WM_COMMAND:
- uID=LOWORD(wParam);
- switch (uID)
- {
- case IDOK:
- //Close the dialog, but save first.
- if (NULL!=ppl)
- {
- //CHAPTER23MOD
- HRESULT hr;
- /*
- * Instead of just closing, see if we can
- * activate in-place again--we know we're an
- * inside out object and want to be activated
- * when we can be. If we can't activate
- * in-place, then close like we normally
- * would. Note that this makes sense only
- * with an inside-out supporting container,
- * which we determine from whether it ever
- * used OLEIVERB_INPLACEACTIVATE.
- */
- hr=ResultFromScode(E_FAIL);
- if (ppl->m_fContainerKnowsInsideOut)
- {
- hr=ppl->InPlaceActivate
- (ppl->m_pIOleClientSite, FALSE);
- }
- if (FAILED(hr))
- {
- ppl->m_pImpIOleObject->Close
- (OLECLOSE_SAVEIFDIRTY);
- }
- //End CHAPTER23MOD
- }
- break;
- case ID_UNDO:
- if (NULL!=ppl)
- ppl->m_pImpIPolyline->Undo();
- break;
- case ID_COLORLINE:
- case ID_COLORBACK:
- if (NULL!=ppl)
- {
- UINT i;
- COLORREF rgColors[16];
- CHOOSECOLOR cc;
- //Invoke the color chooser for either color
- uTemp=(ID_COLORBACK==uID)
- ? POLYLINECOLOR_BACKGROUND
- : POLYLINECOLOR_LINE;
- for (i=0; i<16; i++)
- rgColors[i]=RGB(0, 0, i*16);
- memset(&cc, 0, sizeof(CHOOSECOLOR));
- cc.lStructSize=sizeof(CHOOSECOLOR);
- cc.lpCustColors=rgColors;
- cc.hwndOwner=hDlg;
- cc.Flags=CC_RGBINIT;
- ppl->m_pImpIPolyline->ColorGet(uTemp
- , &cc.rgbResult);
- if (ChooseColor(&cc))
- {
- //rgColor is just some COLORREF pointer
- ppl->m_pImpIPolyline->ColorSet(uTemp
- , cc.rgbResult, rgColors);
- }
- }
- break;
- case ID_LINESOLID:
- case ID_LINEDASH:
- case ID_LINEDOT:
- case ID_LINEDASHDOT:
- case ID_LINEDASHDOTDOT:
- if (NULL!=ppl)
- {
- ppl->m_pImpIPolyline
- ->LineStyleSet(uID-ID_LINEMIN, &uTemp);
- }
- break;
- }
- break;
- case WM_DESTROY:
- #ifdef WIN32
- RemoveProp(hDlg, PROP_POINTER);
- #else
- RemoveProp(hDlg, PROP_SELECTOR);
- RemoveProp(hDlg, PROP_OFFSET);
- #endif
- break;
- case WM_CLOSE:
- //This will do the IDOK handling, then send POLYM_CLOSE
- SendCommand(hDlg, IDOK, 0, NULL);
- break;
- case POLYM_CLOSE:
- ShowWindow(hDlg, SW_HIDE);
- ppl->SendAdvise(OBJECTCODE_HIDEWINDOW);
- break;
- }
- return FALSE;
- }
- //CHAPTER23MOD
- /*
- * CalcPolyRectInDialog
- *
- * Purpose:
- * Calculates the rectangle that the Polyline should occupy in the
- * dialog box. This is separated for in-place handling because
- * when we open the dialog from an in-place active situation we
- * have to move the Polyline window from the container into the
- * dialog and position it properly.
- *
- * Parameters:
- * hDlg HWND of the dialog.
- * prc LPRECT in which to store the rectangle.
- *
- * Return Value:
- * None
- */
- void CalcPolyRectInDialog(HWND hDlg, LPRECT prc)
- {
- HWND hWnd;
- POINT pt;
- hWnd=GetDlgItem(hDlg, ID_POLYLINERECT);
- GetWindowRect(hWnd, prc);
- SETPOINT(pt, prc->left, prc->top);
- ScreenToClient(hDlg, &pt);
- //Set the polyline just within the black frame
- SetRect(prc, pt.x, pt.y, pt.x+(prc->right-prc->left)
- , pt.y+(prc->bottom-prc->top));
- InflateRect(prc, -1, -1);
- return;
- }
- //End CHAPTER23MOD