home *** CD-ROM | disk | FTP | other *** search
/ Mastering Visual Basic 6 / mastvb6.iso / leadtools / ocx32.lt / DRAWVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-10  |  20.4 KB  |  691 lines

  1. // drawView.cpp : implementation of the CDrawView class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "draw.h"
  6.  
  7. #include "drawDoc.h"
  8. #include "drawView.h"
  9.  
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15.  
  16. extern CDrawApp theApp;
  17.  
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CDrawView
  20.  
  21. IMPLEMENT_DYNCREATE(CDrawView, CFormView)
  22.  
  23. BEGIN_MESSAGE_MAP(CDrawView, CFormView)
  24.     //{{AFX_MSG_MAP(CDrawView)
  25.     ON_WM_SIZE()
  26.     ON_MESSAGE(WM_DOREALIZE, OnDoRealize)
  27.     ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  28.     ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
  29.     //}}AFX_MSG_MAP
  30. END_MESSAGE_MAP()
  31.  
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CDrawView construction/destruction
  34.  
  35. CDrawView::CDrawView()
  36.     : CFormView(CDrawView::IDD)
  37. {
  38.     //{{AFX_DATA_INIT(CDrawView)
  39.         // NOTE: the ClassWizard will add member initialization here
  40.     //}}AFX_DATA_INIT
  41.     // TODO: add construction code here
  42.  
  43. }
  44.  
  45. CDrawView::~CDrawView()
  46. {
  47. }
  48.  
  49. void CDrawView::DoDataExchange(CDataExchange* pDX)
  50. {
  51.     CFormView::DoDataExchange(pDX);
  52.     //{{AFX_DATA_MAP(CDrawView)
  53.     DDX_Control(pDX, IDC_LEADCTRL1, m_Lead);
  54.     //}}AFX_DATA_MAP
  55. }
  56.  
  57. BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs)
  58. {
  59.     // TODO: Modify the Window class or styles here by modifying
  60.     //  the CREATESTRUCT cs
  61.  
  62.     return CFormView::PreCreateWindow(cs);
  63. }
  64.  
  65. /////////////////////////////////////////////////////////////////////////////
  66. // CDrawView diagnostics
  67.  
  68. #ifdef _DEBUG
  69. void CDrawView::AssertValid() const
  70. {
  71.     CFormView::AssertValid();
  72. }
  73.  
  74. void CDrawView::Dump(CDumpContext& dc) const
  75. {
  76.     CFormView::Dump(dc);
  77. }
  78.  
  79. CDrawDoc* CDrawView::GetDocument() // non-debug version is inline
  80. {
  81.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDrawDoc)));
  82.     return (CDrawDoc*)m_pDocument;
  83. }
  84. #endif //_DEBUG
  85.  
  86. /////////////////////////////////////////////////////////////////////////////
  87. // CDrawView message handlers
  88. LRESULT CDrawView::OnDoRealize(WPARAM wParam, LPARAM lParam)
  89. {
  90.     if( !IsWindow(m_Lead.m_hWnd) )
  91.         return FALSE;
  92.     if(lParam)
  93.     {
  94.         return m_Lead.SendMessage(WM_PALETTECHANGED, wParam);
  95.     }
  96.     else
  97.     {
  98.         UINT nColorsChanged = 0;
  99.         CDC* pdc;
  100.  
  101.         pdc = theApp.m_pMainWnd->GetDC();
  102.         HPALETTE hpal = (HPALETTE)m_Lead.GetPalette((OLE_HANDLE) pdc->m_hDC);
  103.         if(hpal)
  104.         {
  105.             CPalette pal;
  106.  
  107.             pal.Attach(hpal);
  108.             CPalette* oldPalette = pdc->SelectPalette(&pal, (BOOL) lParam);
  109.             nColorsChanged = pdc->RealizePalette();
  110.             if (nColorsChanged > 0)
  111.             {
  112.                 m_Lead.InvalidateRect(NULL, FALSE);
  113.             }
  114.             pdc->SelectPalette(oldPalette, TRUE);
  115.         }
  116.         theApp.m_pMainWnd->ReleaseDC(pdc);
  117.         return ((LRESULT) (BOOL) (nColorsChanged > 0));
  118.     }
  119. }
  120.  
  121. void CDrawView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) 
  122. {
  123.     CFormView::OnActivateView(bActivate, pActivateView, pDeactiveView);
  124.     if (bActivate)
  125.     {
  126.         ASSERT(pActivateView == this);
  127.         OnDoRealize((WPARAM)theApp.m_pMainWnd->m_hWnd, (LPARAM) FALSE);   // same as SendMessage(WM_DOREALIZE);
  128.     }
  129. }
  130.  
  131. void CDrawView::OnSize(UINT nType, int cx, int cy) 
  132. {
  133.     CFormView::OnSize(nType, cx, cy);
  134.  
  135.     if( IsWindow(m_Lead.m_hWnd) )
  136.         m_Lead.MoveWindow(CRect( 0, 0, cx, cy));
  137. }
  138.  
  139. CLead* CDrawView::GetDocLead() 
  140. {
  141.     CDrawDoc* pDoc = GetDocument();
  142.     return(&pDoc->m_Lead);
  143. }
  144.  
  145. void CDrawView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
  146. {
  147.     // Note that this program has one instance of the Lead control for each 
  148.     // view, plus the one instance for the document, which is used as the master copy.
  149.     // The UpdateAllViews function calls this function once for each view; and 
  150.     // this function uses the master copy to update each view.
  151.  
  152.     ASSERT(pSender != this);
  153.     UNUSED(pSender);     // unused in release builds
  154.  
  155.     CDrawDoc* pDoc = GetDocument();
  156.  
  157.     // Save the current rectangles used for zooming and scrolling.
  158.     float xLeft = m_Lead.GetDstLeft(), yTop = m_Lead.GetDstTop(), 
  159.           xWidth = m_Lead.GetDstWidth(), yHeight = m_Lead.GetDstHeight();
  160.     float xsLeft = m_Lead.GetSrcLeft(), ysTop = m_Lead.GetSrcTop(), 
  161.           xsWidth = m_Lead.GetSrcWidth(), ysHeight = m_Lead.GetSrcHeight();
  162.  
  163.     // Avoid repainting until we are ready.
  164.     m_Lead.SetAutoRepaint(FALSE);
  165.  
  166.     // Update the this view's bitmap with the document bitmap.
  167.     m_Lead.SetBackErase(TRUE);
  168.     m_Lead.SetBitmap(GetDocLead()->GetBitmap());
  169.     m_Lead.SetPaintPalette(PAINTPALETTE_AUTO);
  170.     m_Lead.SetPaintDither(PAINTDITHER_DIFFUSION);
  171.     m_Lead.SetBitonalScaling(BITONALSCALING_NORMAL);
  172.    
  173.    
  174.     if (lHint == 2) // All views, except the sender, are updated after a drawing change.
  175.     {
  176.         // Restore the saved rectangles.
  177.         m_Lead.SetDstRect(xLeft, yTop, xWidth, yHeight);
  178.         m_Lead.SetDstClipRect(xLeft, yTop, xWidth, yHeight);
  179.         m_Lead.SetSrcRect(xsLeft, ysTop, xsWidth, ysHeight);
  180.         m_Lead.SetSrcClipRect(xsLeft, ysTop, xsWidth, ysHeight);
  181.     }
  182.     else if (lHint == 1) // Zooming is disabled, and the view is returned to normal.
  183.     {
  184.         // Set the default display rectangles.
  185.         float xExt = m_Lead.GetBitmapWidth(),
  186.             yExt = m_Lead.GetBitmapHeight();
  187.         m_Lead.SetDstRect(0.0f, 0.0f, xExt, yExt);
  188.         m_Lead.SetDstClipRect(0.0f, 0.0f, xExt, yExt);
  189.         m_Lead.SetSrcRect(0.0f, 0.0f, xExt, yExt);
  190.         m_Lead.SetSrcClipRect(0.0f, 0.0f, xExt, yExt);
  191.  
  192.         // Fit the LEAD control to the client area and enable autoscrolling.
  193.         CRect   rcClient;
  194.         GetClientRect(rcClient);
  195.         m_Lead.MoveWindow(0, 0, rcClient.right, rcClient.bottom, FALSE); 
  196.         m_Lead.SetAutoScroll(TRUE);
  197.  
  198.         // Update the window title because we have stopped drawing.
  199.         pDoc->SetTitle(pDoc->GetTitle());
  200.     }
  201.  
  202.  
  203.     // invalidate the entire pane, erase background too
  204.     Invalidate(TRUE);
  205.     m_Lead.SetAutoRepaint(TRUE);
  206. }
  207.  
  208. void CDrawView::OnInitialUpdate() 
  209. {
  210.     CFormView::OnInitialUpdate();
  211.  
  212.     // Set the default display rectangles.
  213.     float xExt = m_Lead.GetBitmapWidth(),
  214.         yExt = m_Lead.GetBitmapHeight();
  215.     m_Lead.SetDstRect(0.0f, 0.0f, xExt, yExt);
  216.     m_Lead.SetDstClipRect(0.0f, 0.0f, xExt, yExt);
  217.     m_Lead.SetSrcRect(0.0f, 0.0f, xExt, yExt);
  218.     m_Lead.SetSrcClipRect(0.0f, 0.0f, xExt, yExt);
  219.  
  220.     // Disable the scroll bars in the parent window
  221.     SetScrollSizes(MM_TEXT,CSize(1,1));
  222.  
  223.     // Fit the LEAD control to the client area and enable autoscrolling.
  224.     CRect   rcClient;
  225.     GetClientRect(rcClient);
  226.     m_Lead.MoveWindow(0, 0, rcClient.right, rcClient.bottom, FALSE); 
  227.     m_Lead.SetAutoScroll(TRUE);
  228.         
  229. }
  230.  
  231. BEGIN_EVENTSINK_MAP(CDrawView, CFormView)
  232.     //{{AFX_EVENTSINK_MAP(CDrawView)
  233.     ON_EVENT(CDrawView, IDC_LEADCTRL1, -605 /* MouseDown */, OnMouseDownLeadctrl1, VTS_I2 VTS_I2 VTS_I4 VTS_I4)
  234.     ON_EVENT(CDrawView, IDC_LEADCTRL1, -606 /* MouseMove */, OnMouseMoveLeadctrl1, VTS_I2 VTS_I2 VTS_I4 VTS_I4)
  235.     ON_EVENT(CDrawView, IDC_LEADCTRL1, -607 /* MouseUp */, OnMouseUpLeadctrl1, VTS_I2 VTS_I2 VTS_I4 VTS_I4)
  236.     //}}AFX_EVENTSINK_MAP
  237. END_EVENTSINK_MAP()
  238.  
  239. void CDrawView::OnMouseDownLeadctrl1(short Button, short Shift, long X, long Y) 
  240. {
  241.     CDrawDoc *pDoc = GetDocument();
  242.     CLead *pLead = &pDoc->m_Lead;
  243.  
  244.     if( Button != 1 )
  245.         return;
  246.  
  247.     if( pDoc->nDraw != ID_DRAW_DISABLE )
  248.     {
  249.         // Initialize the zoom factors
  250.         if (m_Lead.GetBitmap() != 0)
  251.         {
  252.             ZoomFactorX = m_Lead.GetDstWidth() / m_Lead.GetSrcWidth();
  253.             ZoomFactorY = m_Lead.GetDstHeight() / m_Lead.GetSrcHeight();
  254.         }
  255.         // Determine the mouse coordinates on the screen
  256.         StartX = (int)X;
  257.         StartY = (int)Y;
  258.  
  259.         // Determine the mouse coordinates on the bitmap
  260.         BStartX = (int)((StartX / ZoomFactorX) - (m_Lead.GetDstLeft() / ZoomFactorX) + m_Lead.GetSrcLeft());
  261.         BStartY = (int)((StartY / ZoomFactorY) - (m_Lead.GetDstTop() / ZoomFactorY) + m_Lead.GetSrcTop());
  262.  
  263.         // Set the conditions that the OnMouseMove and OnMouseUp functions check.
  264.         bFirstDraw = TRUE;
  265.         bDrawing = TRUE;
  266.  
  267.         // Take control of when the image paints.
  268.         m_Lead.SetAutoRepaint(FALSE);
  269.     }
  270.  
  271.  
  272.     // The rest of this is function is only for pasting
  273.     if( pDoc->nDraw == ID_DRAW_PASTE )
  274.     {
  275.         // Set the mouse to an hourglass while pasting
  276.         HCURSOR hOldCursor = ::SetCursor(::LoadCursor(NULL,MAKEINTRESOURCE(IDC_WAIT)));
  277.  
  278.         // Get the image from the clipboard
  279.         PasteClipboard(BStartX, BStartY);
  280.  
  281.         ::SetCursor(hOldCursor);
  282.     }
  283.  
  284. }
  285.  
  286. void CDrawView::OnMouseMoveLeadctrl1(short Button, short Shift, long X, long Y) 
  287. {
  288.   CDrawDoc *pDoc = GetDocument();
  289.   CLead *pLead = &pDoc->m_Lead;
  290.  
  291.   if( pDoc->nDraw == ID_DRAW_OBJECT )
  292.   {
  293.     m_Lead.SetMousePointer(2);
  294.  
  295.     char szCaption[50];
  296.     wsprintf(szCaption, "Mouse X = %d, Mouse Y = %d", X, Y);
  297.     char text[500];
  298.     GetWindowText(text,sizeof(text));
  299.     GetParent()->SetWindowText(szCaption);
  300.  
  301.     if( Button == 1 )
  302.     {
  303.       HDC LeadDC = (HDC)m_Lead.GetClientDC();
  304.  
  305.       HPEN hOldPen = (HPEN)::SelectObject(LeadDC, GetStockObject(WHITE_PEN));
  306.       HBRUSH hOldBrush = (HBRUSH)::SelectObject(LeadDC, GetStockObject(HOLLOW_BRUSH));
  307.  
  308.       int DisplayMode = ::SetROP2(LeadDC, R2_NOT);
  309.  
  310.       switch(pDoc->nObject)
  311.       {
  312.         case ID_OBJECT_ELLIPSE:
  313.           if( !bFirstDraw )
  314.             ::Ellipse(LeadDC, StartX, StartY, EndX, EndY);
  315.  
  316.           EndX = (int)X;
  317.           EndY = (int)Y;
  318.           ::Ellipse(LeadDC, StartX, StartY, EndX, EndY);
  319.           break;
  320.         case ID_OBJECT_LINE:
  321.           if( !bFirstDraw )
  322.           {
  323.             MoveToEx( LeadDC, StartX, StartY, NULL );
  324.             LineTo(LeadDC, EndX, EndY);
  325.           }
  326.           EndX = (int)X;
  327.           EndY = (int)Y;
  328.           MoveToEx( LeadDC, StartX, StartY, NULL );
  329.           LineTo(LeadDC, EndX, EndY);
  330.           break;
  331.         case ID_OBJECT_RECTANGLE:
  332.           if( !bFirstDraw )
  333.             Rectangle(LeadDC, StartX, StartY, EndX, EndY);
  334.           EndX = (int)X;
  335.           EndY = (int)Y;
  336.           Rectangle(LeadDC, StartX, StartY, EndX, EndY);
  337.           break;
  338.       }
  339.       bFirstDraw = FALSE;
  340.       SetROP2(LeadDC, DisplayMode);
  341.       m_Lead.ReleaseClientDC();
  342.     }
  343.   }
  344.   else if(pDoc->nDraw == ID_DRAW_COPY || pDoc->nDraw == ID_DRAW_ZOOMIN)
  345.   {
  346.     m_Lead.SetMousePointer(2);
  347.  
  348.     char szCaption[50];
  349.     wsprintf(szCaption, "Mouse X = %d, Mouse Y = %d", X, Y);
  350.     GetParent()->SetWindowText(szCaption);
  351.  
  352.     if( Button == 1 )
  353.     {
  354.         int rbX, rbY;
  355.         if( X >= StartX )
  356.             rbX = StartX;
  357.         else
  358.             rbX = (int)X;
  359.  
  360.         if( Y >= StartY )
  361.             rbY = StartY;
  362.         else
  363.             rbY = (int)Y;
  364.  
  365.         int rbWidth = abs(StartX - (int)X);
  366.         int rbHeight = abs(StartY - (int)Y);
  367.         int OldScale = m_Lead.GetScaleMode();
  368.         m_Lead.SetScaleMode(3);
  369.         m_Lead.SetRubberBandRect((float)rbX, (float)rbY, (float)rbWidth, (float)rbHeight);
  370.         m_Lead.SetRubberBandVisible(TRUE);
  371.         m_Lead.SetScaleMode (OldScale);
  372.     }
  373.   }
  374.   else if( pDoc->nDraw == ID_DRAW_PASTE)
  375.   {
  376.     char szCaption[50];
  377.     wsprintf(szCaption, "Mouse X = %d, Mouse Y = %d", X, Y);
  378.     GetParent()->SetWindowText(szCaption);
  379.     m_Lead.SetMousePointer(10);
  380.   }
  381.   else
  382.     m_Lead.SetMousePointer(0);
  383. }
  384.  
  385. void CDrawView::OnMouseUpLeadctrl1(short Button, short Shift, long X, long Y) 
  386. {
  387.     long ColorRGB;
  388.     CDrawDoc *pDoc = GetDocument();
  389.     CLead *pLead = &pDoc->m_Lead;
  390.  
  391.     HPEN hPen;
  392.     HPEN hOldBitmapPen;
  393.     HBRUSH hOldBitmapBrush;
  394.  
  395.     if( bDrawing )
  396.     {
  397.       EndX = (int)X;
  398.       EndY = (int)Y;
  399.       
  400.       BEndX = (int)((EndX / ZoomFactorX) - (m_Lead.GetDstLeft() / ZoomFactorX) + m_Lead.GetSrcLeft());
  401.       BEndY = (int)((EndY / ZoomFactorY) - (m_Lead.GetDstTop() / ZoomFactorY) + m_Lead.GetSrcTop());
  402.  
  403.       m_Lead.SetAutoRepaint(TRUE);
  404.       if( pDoc->nDraw == ID_DRAW_OBJECT )
  405.       {
  406.         switch(pDoc->nColor)
  407.         {
  408.           case ID_COLOR_BLACK:
  409.             ColorRGB = RGB(0, 0, 0);
  410.             break;
  411.           case ID_COLOR_BLUE:
  412.             ColorRGB = RGB(0, 0, 255);
  413.             break;
  414.           case ID_COLOR_GREEN:
  415.             ColorRGB = RGB(0, 255, 0);
  416.             break;
  417.           case ID_COLOR_RED:
  418.             ColorRGB = RGB(255, 0, 0);
  419.             break;
  420.           case ID_COLOR_WHITE:
  421.             ColorRGB = RGB(255, 255, 255);
  422.             break;
  423.         }
  424.  
  425.         // the ClientDC uses client window coordinates, 
  426.         // but the BitmapDC uses Bitmap coordinates !!
  427.         HDC LeadBitmapDC = (HDC)m_Lead.GetBitmapDC();
  428.  
  429.         hPen = ::CreatePen(PS_SOLID, pDoc->nThickness, ColorRGB);
  430.  
  431.         hOldBitmapPen = (HPEN)::SelectObject(LeadBitmapDC, hPen);
  432.         hOldBitmapBrush = (HBRUSH)::SelectObject(LeadBitmapDC, GetStockObject(HOLLOW_BRUSH));
  433.  
  434.         switch( pDoc->nObject )
  435.         {
  436.           case ID_OBJECT_ELLIPSE:
  437.             Ellipse(LeadBitmapDC, BStartX, BStartY, BEndX, BEndY);
  438.             break;
  439.           case ID_OBJECT_LINE:
  440.             MoveToEx(LeadBitmapDC, BStartX, BStartY, NULL);
  441.             LineTo(LeadBitmapDC, BEndX, BEndY);
  442.             break;
  443.           case ID_OBJECT_RECTANGLE:
  444.             Rectangle(LeadBitmapDC, BStartX, BStartY, BEndX, BEndY);
  445.             break;
  446.         }
  447.     
  448.         ::SelectObject(LeadBitmapDC, hOldBitmapPen);
  449.         ::SelectObject(LeadBitmapDC, hOldBitmapBrush);
  450.  
  451.         bDrawing = FALSE;
  452.         m_Lead.ReleaseBitmapDC();
  453.         DeleteObject(hPen);
  454.         m_Lead.SetBackErase(FALSE);
  455.         pLead->SetBitmap(m_Lead.GetBitmap());
  456.  
  457.         pDoc->UpdateAllViews(this, (LPARAM)2, NULL);
  458.       }
  459.       else if( pDoc->nDraw == ID_DRAW_COPY )
  460.       {
  461.         CLead *pFrameLead = theApp.GetMainLead();
  462.         m_Lead.SetMousePointer(11);
  463.  
  464.         //Get rid of the rectangle
  465.         m_Lead.SetRubberBandVisible(FALSE);
  466.  
  467.  
  468.         //Get the width and height of the selected area
  469.         float ImageWidth = (float)abs(BEndX - BStartX);
  470.         float ImageHeight = (float)abs(BEndY - BStartY);
  471.  
  472.         // Create the second bitmap
  473.         pFrameLead->CreateBitmap(ImageWidth, ImageHeight, m_Lead.GetBitmapBits());
  474.         if (m_Lead.GetBitmapBits() < 16)
  475.         {
  476.             int NoColors = 1 << m_Lead.GetBitmapBits();
  477.             for( int i = 0; i < NoColors; i++ )
  478.             {
  479.                 pFrameLead->SetBitmapPalette(i, m_Lead.GetBitmapPalette(i));
  480.             }
  481.         }
  482.         pFrameLead->Fill(RGB(0, 0, 0));
  483.         
  484.         float xSrc, ySrc;
  485.         // Find the top left corner of the selected rectangle.
  486.         if (BStartX < BEndX)
  487.             xSrc = (float)BStartX;
  488.         else
  489.             xSrc = (float)BEndX;
  490.         if (BStartY < BEndY)
  491.             ySrc = (float)BStartY;
  492.         else
  493.             ySrc = (float)BEndY;
  494.  
  495.         // Use the Combine method to copy the selected rectangle to the second bitmap.
  496.         pFrameLead->Combine(0.0f, 0.0f, ImageWidth, ImageHeight, m_Lead.GetBitmap(), xSrc, ySrc, CB_OP_ADD | CB_DST_0);
  497.             
  498.  
  499.         // Copy the second bitmap to the clipboard
  500.         pFrameLead->Copy(COPY_DIB);
  501.         // Change next option to paste
  502.         pDoc->nDraw = ID_DRAW_PASTE;
  503.  
  504.         m_Lead.SetMousePointer(0);
  505.       }
  506.       else if( pDoc->nDraw == ID_DRAW_ZOOMIN )
  507.       {
  508.  
  509.          float CropLeft, CropTop;
  510.         // Find the top left corner of the selected rectangle.
  511.         if (BStartX < BEndX)
  512.             CropLeft = (float)BStartX;
  513.         else
  514.             CropLeft = (float)BEndX;
  515.         if (BStartY < BEndY)
  516.             CropTop = (float)BStartY;
  517.         else
  518.             CropTop = (float)BEndY;
  519.  
  520.         // Get the width and height of the selected rectangle.
  521.         float CropWidth = (float)abs(BEndX - BStartX);
  522.         float CropHeight = (float)abs(BEndY - BStartY);
  523.  
  524.         // Quit if the selected area is too small.
  525.         if (CropWidth < 1 || CropHeight < 1)
  526.         {
  527.             m_Lead.SetRubberBandVisible(FALSE); // Hides the rubberband
  528.             m_Lead.SetBackErase(FALSE); // Forces a repaint
  529.             bFirstDraw = FALSE;
  530.             return;
  531.         }
  532.  
  533.         // Size and redisplay the control, using the new source rectangle.
  534.         // Set the variables used for preserving the aspect ratio.
  535.         float HeightFactor = CropHeight;
  536.         float WidthFactor = CropWidth;
  537.         CRect rcWindow;
  538.         GetClientRect(rcWindow);
  539.         float HeightAllowed = (float)rcWindow.Height();
  540.         float WidthAllowed = (float)rcWindow.Width();
  541.  
  542.         // Place the lead control on the form, preserving the selected area's aspect ratio.
  543.         // Check to see if using the maximum width will make the image too tall.
  544.         // Set the dimensions based on the result.
  545.         float Left, Width, Height, Top;
  546.         if(((WidthAllowed * HeightFactor) / WidthFactor) < HeightAllowed)
  547.         {
  548.           Left = 0.0f;
  549.           Width = WidthAllowed;
  550.           Height = (Width * HeightFactor) / WidthFactor;
  551.           Top = (HeightAllowed - Height) / 2;
  552.         }
  553.         else
  554.         {
  555.           Top = 0.0f;
  556.           Height = HeightAllowed;
  557.           Width = (Height * WidthFactor) / HeightFactor;
  558.           Left = (WidthAllowed - Width) / 2;
  559.         }
  560.         rcWindow.SetRect(0, 0, (int) Width, (int) Height);
  561.         rcWindow.OffsetRect((int) Left, (int) Top);
  562.  
  563.         // Hide the Lead control while we adjust the display.
  564.         m_Lead.ShowWindow(SW_HIDE);
  565.         m_Lead.MoveWindow(rcWindow);
  566.  
  567.         // Zoom in on the source rectangle
  568.         m_Lead.SetSrcRect(CropLeft, CropTop, CropWidth, CropHeight);
  569.         m_Lead.SetSrcClipRect(CropLeft, CropTop, CropWidth, CropHeight);
  570.  
  571.         // Set the image display size to match the Lead control.
  572.         m_Lead.SetDstRect(0.0f, 0.0f, m_Lead.GetScaleWidth(), m_Lead.GetScaleHeight());
  573.         m_Lead.SetDstClipRect(0.0f, 0.0f, m_Lead.GetScaleWidth(), m_Lead.GetScaleHeight());
  574.  
  575.         // Show the adjusted display.
  576.         m_Lead.ShowWindow(SW_SHOW);
  577.         
  578.         m_Lead.SetRubberBandVisible(FALSE); // Hides the rubberband
  579.         m_Lead.SetMousePointer(0);
  580.  
  581.         // Display the Lead control
  582.         m_Lead.ForceRepaint();
  583.       }
  584.     }
  585. }
  586.  
  587. void CDrawView::OnEditPaste() 
  588. {
  589.     PasteClipboard(0, 0);
  590. }
  591.  
  592. BOOL CDrawView::PasteClipboard( long BStartX, long BStartY )
  593. {
  594.     CDrawDoc *pDoc = GetDocument();
  595.     CLead *pLead = &pDoc->m_Lead;
  596.     CLead *pFrameLead = theApp.GetMainLead();
  597.     if( !ClipboardHasBitmap() )
  598.     {
  599.         MessageBox("No image data on the clipboard", "ERROR");
  600.         return FALSE;
  601.     }
  602.  
  603.     if( pFrameLead->Paste( COPY_DIB ) || !pFrameLead->GetBitmapBits() )
  604.         // an error occured during pasting
  605.         return FALSE;
  606.  
  607.     // If the LEAD control has a palette, see if the new data has the same palette.
  608.     // Initialize the flag
  609.     BOOL fMustDoColorRes = FALSE;
  610.     if ( m_Lead.GetBitmapBits() < 16 )
  611.     {
  612.         if( pFrameLead->GetBitmapBits() > 8)
  613.         {
  614.             // The new data has no palette
  615.             fMustDoColorRes = TRUE;
  616.         }
  617.         else
  618.         {
  619.             // Check to see if the palettes match
  620.             int NoColors = 1 << m_Lead.GetBitmapBits();
  621.             for( int i = 0; i < NoColors; i++ )
  622.             {
  623.                 if( m_Lead.GetBitmapPalette(i) != pFrameLead->GetBitmapPalette(i) )
  624.                 {
  625.                     fMustDoColorRes = TRUE;
  626.                     break;
  627.                 }
  628.             }
  629.         }
  630.         // If it is not the same palette, let the user decide whether to continue.
  631.         if (fMustDoColorRes == TRUE)
  632.         {
  633.             if ( MessageBox("Palette mismatch. Convert to 24-bit", "Notice", MB_YESNO))
  634.             {
  635.                 m_Lead.ColorRes(24, CRP_BYTEORDERBGR, 0, 0);
  636.                 pFrameLead->ColorRes(24, CRP_BYTEORDERBGR, 0, 0);
  637.             }
  638.             else
  639.             {
  640.                 return FALSE;
  641.             }
  642.         }
  643.     }
  644.     else if(m_Lead.GetBitmapBits() != pFrameLead->GetBitmapBits())
  645.     {
  646.         // Convert the new data to the same bits per pixel as the LEAD control (16 or higher)
  647.         pFrameLead->ColorRes(m_Lead.GetBitmapBits(), CRP_BYTEORDERBGR, 0, 0);
  648.     }
  649.  
  650.     // Combine the new data with the current bitmap at the current position.
  651.     long MyOp = CB_OP_ADD | CB_DST_0; // Operation flags for a simple paste
  652.     m_Lead.Combine((float)BStartX, (float)BStartY, pFrameLead->GetSrcWidth(), pFrameLead->GetSrcHeight(),pFrameLead->GetBitmap(),0.0f,0.0f, MyOp);
  653.  
  654.     // Repaint the changed portion of the bitmap, unless the palette has changed.
  655.     if (fMustDoColorRes == FALSE)
  656.     {
  657.         m_Lead.SetSrcClipRect((float)BStartX, (float)BStartY,  pFrameLead->GetSrcWidth(), pFrameLead->GetSrcHeight());
  658.         m_Lead.SetBackErase(FALSE);
  659.         m_Lead.ForceRepaint;
  660.         m_Lead.SetSrcClipRect(m_Lead.GetSrcLeft(), m_Lead.GetSrcTop(),  m_Lead.GetSrcWidth(), m_Lead.GetSrcHeight());
  661.     }
  662.  
  663.     // Copy this view's bitmap to the document's master copy.
  664.     pLead->SetBitmap(m_Lead.GetBitmap());
  665.     
  666.     // Update other views of the bitmap; also update this one if the palette has changed.
  667.     if (fMustDoColorRes == FALSE)
  668.         pDoc->UpdateAllViews(this, (LPARAM)2, NULL); // Update views except this one
  669.     else
  670.         pDoc->UpdateAllViews(NULL, (LPARAM)2, NULL); // Update views, including this one
  671.     return TRUE;
  672. }
  673.  
  674. void CDrawView::OnUpdateEditPaste(CCmdUI* pCmdUI) 
  675. {
  676.    pCmdUI->Enable( ClipboardHasBitmap() );
  677. }
  678.  
  679. BOOL CDrawView::ClipboardHasBitmap()
  680. {
  681.     BOOL retval = FALSE;
  682.     if( OpenClipboard() )
  683.     {
  684.         retval = IsClipboardFormatAvailable(CF_DIB);
  685.         CloseClipboard();
  686.     }
  687.     return retval;
  688. }
  689.  
  690.  
  691.