#include "StdAfx.h" #include ".\itemview.h" #include "SigmaDoc.h" #include "SigmaView.h" namespace NDrawView { BOOL SaveAs(CDC* pDC, const wchar_t* lpszFilename); CItemView::CItemView(CSigmaDoc * ppDoc) :CItemBase(ppDoc), m_offsetX(0), m_offsetY(0), m_offsetScreenX(0), m_offsetScreenY(0), m_zoomFactor(1.0), m_screenFactor(1.0) { m_type=ITEM_VIEW; bCaptureCursor=FALSE; m_bEnableCaptureCursor=TRUE; m_bOldViewMode=TRUE; m_type=ITEM_VIEW_DEFAULT; m_bRButtonDown = FALSE; zoomMode = 0; m_pMemViewDC = nullptr; m_ptLeft.x = 0; m_ptLeft.y = 0; } CItemView::CItemView(void) : CItemBase(NULL) , m_bRButtonDown(FALSE) { m_type=0;//ITEM_VIEW; bCaptureCursor=FALSE; m_bEnableCaptureCursor=TRUE; m_bOldViewMode=TRUE; m_type=ITEM_VIEW_DEFAULT; m_bRButtonDown = FALSE; zoomMode = 0; m_pMemViewDC = nullptr; m_offsetX = 0; m_offsetY = 0; m_zoomFactor = 1; m_offsetScreenX = 0; m_offsetScreenY = 0; m_screenFactor = 1; } CItemView::~CItemView(void) { } BOOL CItemView::GetViewRange(CRect8& rect) { CSigmaDoc* pDoc = (CSigmaDoc*)m_pDoc; if (pDoc->m_pXy == NULL) { return FALSE; } if(pDoc->m_pXy->GetCount()>0) { pDoc->GetDrawRange(rect); //pDoc->GetDraw()->GetRange(rect); //rect=pDoc->GetDraw()->m_range; return TRUE; } return FALSE; } void CItemView::EnableOldMode(BOOL bEnable) { m_bOldViewMode=bEnable; } BOOL CItemView::IsOldMode(void) { return m_bOldViewMode; } int CItemView::IsViewState(void) { return (this->GetType()!=ITEM_VIEW && this->GetType()!=0); } eCursorSelectStruct CItemView::GetCursor(void) { // switch(GetType()) // { // case ID_VIEW_WINDOW: // if(m_bRButtonDown || ::IsKeyDown(VK_SHIFT)) // return CursorCenterReduce; //// case ID_VIEW_ENLARGE: // return CursorCenterEnlarge; // case ID_VIEW_PAN: // return CursorViewPan1; // //case ID_VIEW_REDUCE: // // return CursorCenterReduce; // } return CursorDefault; } // void CItemView::SetScreenRect(CRect rect) { m_scressRect = rect; } void CItemView::OnLButtonDownForPreviewPrint(UINT nFlags, CPoint point) { ScreenToPrint(point); m_rectForPrint.left = GetDC()->GetRX(point.x); m_rectForPrint.top = GetDC()->GetRY(point.y); m_rectForPrint.right = m_rectForPrint.left; m_rectForPrint.bottom = m_rectForPrint.top; } void CItemView::OnMouseMoveForPreviewPrint(UINT nFlags, CPoint point) { ScreenToPrint(point); CXyDC * pXyDC = GetDC(); m_rectForPrint.right = pXyDC->GetRX(point.x); m_rectForPrint.bottom = pXyDC->GetRY(point.y); } void CItemView::OnLButtonUpForPreviewPrint(UINT nFlags, CPoint point) { ScreenToPrint(point); CXyDC *pXyDC = GetDC(); m_rectForPrint.right = pXyDC->GetRX(point.x); m_rectForPrint.bottom = pXyDC->GetRY(point.y); if (m_rectForPrint.IsEmpty()) return; double dx = m_rectForPrint.left - m_rectForPrint.right; double dy = m_rectForPrint.top - m_rectForPrint.bottom; m_offsetX += dx; m_offsetY += dy; pXyDC->OffsetRect(dx, dy); } void CItemView::ScreenToPrint(CPoint & point) { double factor = 1.0; if (!m_scressRect.IsRectEmpty()) { factor = m_clientRect.Height() * 1.0 / m_scressRect.Height(); } point.x *= factor; point.y *= factor; } void CItemView::GetViewFactors(double & offsetXOut, double & offsetYOut, double & zoomFactorOut) { offsetXOut = m_offsetX; offsetYOut = m_offsetY; zoomFactorOut = m_zoomFactor; } void CItemView::SetViewScreenFactors(double offsetX, double offsetY, double zoomFactor) { m_offsetScreenX = offsetX; m_offsetScreenY = offsetY; m_screenFactor = zoomFactor; } void CItemView::SetViewFactors(double offsetX, double offsetY, double zoomFactor) { m_offsetX = offsetX; m_offsetY = offsetY; m_zoomFactor = zoomFactor; CXyDC *pXyDC = GetDC(); pXyDC->Reduce(m_zoomFactor); pXyDC->OffsetRect(m_offsetX, m_offsetY); } // double CItemView::TransfromX(double x) { return (x - m_offsetScreenX) / m_screenFactor; } double CItemView::TransfromY(double y) { return (y - m_offsetScreenY) / m_screenFactor; } CRect CItemView::TransfromRect(CRect rtSource) { CRect rt; rt.left = TransfromX(rtSource.left); rt.right = TransfromX(rtSource.right); rt.top = TransfromY(rtSource.top); rt.bottom = TransfromY(rtSource.bottom); return rt; } double CItemView::DeTransfromX(double x) { return x * m_screenFactor + m_offsetScreenX; } double CItemView::DeTransfromY(double y) { return y * m_screenFactor + m_offsetScreenY; } CRect CItemView::DeTransfromRect(CRect rtSource) { CRect rt; rt.left = DeTransfromX(rtSource.left); rt.right = DeTransfromX(rtSource.right); rt.top = DeTransfromY(rtSource.top); rt.bottom = DeTransfromY(rtSource.bottom); return rt; } void CItemView::OnLButtonDown(CDC *pDC, UINT nFlags, CPoint point, int vk) { switch (GetType()) { case ID_VIEW_WINDOW: m_rect.left = GetDC()->GetRX(TransfromX(point.x)); m_rect.top = GetDC()->GetRY(TransfromY(point.y)); m_rect.right = m_rect.left; m_rect.bottom = m_rect.top; case ID_VIEW_PAN: m_ptLeft = point; //m_rect.left = GetDC()->GetRX(TransfromX(point.x)); //m_rect.top = GetDC()->GetRY(TransfromY(point.y)); //m_rect.right = m_rect.left; //m_rect.bottom = m_rect.top; bCaptureCursor = TRUE; //if (GetType() == ID_VIEW_PAN) // LButtonDownPan(point); break; } } void CItemView::OnLButtonUp(CDC *pDC, UINT nFlags, CPoint point, int vk) { //if (!bCaptureCursor) return; double factor = 1.5; //GetDrawDoc()->PushActionDC(GetType()); m_pDoc->PushActionDC(GetType()); CRect rt = GetClientRect(); CXyDC *pXyDC = GetDC(); //CBrush* pOldBrush = (CBrush*)pXyDC->GetDC()->SelectStockObject(NULL_BRUSH); //int old = GetDC()->GetDC()->SetROP2(R2_NOT); switch (GetType()) { case ID_VIEW_WINDOW: m_rect.right = pXyDC->GetRX(TransfromX(point.x)); m_rect.bottom = pXyDC->GetRY(TransfromX(point.y)); m_rect.NormalizeRect(); if (m_rect.IsEmpty()) { if (::IsKeyDown(VK_SHIFT) || vk == VK_SHIFT) { pXyDC->Reduce(1 / factor); m_zoomFactor *= 1 / factor; } else { pXyDC->Reduce(factor); m_zoomFactor *= 1 / factor; } CPoint2D p8 = pXyDC->GetReal(rt.CenterPoint()); double dx = m_rect.right - p8.x0; double dy = m_rect.bottom - p8.y0; m_offsetX += dx; m_offsetY += dy; pXyDC->OffsetRect(dx, dy); } else { if (::IsKeyDown(VK_SHIFT) || vk == VK_SHIFT) { //将客户区缩小到指定窗口内 CRect rect = pXyDC->GetScreen(m_rect); // 不需要转换 // rect = DeTransfromRect(rect); m_rect = pXyDC->GetReal(rt); pXyDC->Extend(m_rect, rect, EXTEND_MODE_DEFAULT); } else pXyDC->Extend(m_rect, rt, EXTEND_MODE_DEFAULT); } //GetDrawDoc()->Invalidate(); //GetDrawDoc()->InvalidateAttachView(); //是否进行绑定更新其它视图 break; case ID_VIEW_PAN: m_rect.left = pXyDC->GetRX(TransfromX(m_ptLeft.x)); m_rect.top = pXyDC->GetRY(TransfromY(m_ptLeft.y)); m_rect.right = pXyDC->GetRX(point.x); m_rect.bottom = pXyDC->GetRY(point.y); if (m_rect.IsEmpty())break; double dx = m_rect.left - m_rect.right; double dy = m_rect.top - m_rect.bottom; m_offsetX += dx; m_offsetY += dy; pXyDC->OffsetRect(dx, dy); //GetDrawDoc()->Invalidate(); //GetDrawDoc()->InvalidateAttachView(); //是否进行绑定更新其它视图 break; } } int CItemView::OnMouseMove(CDC *pDC, UINT nFlags, CPoint point) { //if (!bCaptureCursor) return; CXyDC *pXyDC = &m_pDoc->GetDC(); switch (GetType()) { case ID_VIEW_WINDOW: //case ID_VIEW_ENLARGE: if (m_type == ITEM_VIEW_PRINT) { RectangleSolid(pXyDC, &m_rect); m_rect.right = pXyDC->GetRX(point.x); m_rect.bottom = pXyDC->GetRY(point.y); RectangleSolid(pXyDC, &m_rect); } else { CDC* pScreenDC = ((CSigmaView*)GetDrawView())->GetScreenDC(); //显示平滑矩形充填 CRect oldRect = pXyDC->GetScreen(m_rect); oldRect = GetNegativeRect(&oldRect); oldRect.SwapLeftRight(); m_rect.right = pXyDC->GetRX(TransfromX(point.x)); m_rect.bottom = pXyDC->GetRY(TransfromY(point.y)); CRect newRect = pXyDC->GetScreen(m_rect); newRect = GetNegativeRect(&newRect); COLORREF colw = RGB(255, 255, 255); COLORREF m_colBrush = RGB(198, 214, 239); COLORREF m_colPen = RGB(49, 106, 197); CBrush brush; brush.CreateSolidBrush(colw - m_colBrush); oldRect = DeTransfromRect(oldRect); newRect = DeTransfromRect(newRect); pScreenDC->DrawDragRect(&newRect, CSize(1, 1), &oldRect, CSize(1, 1), &brush, &brush); //显示充填矩形 oldRect.NormalizeRect(); newRect.NormalizeRect(); brush.DeleteObject(); brush.CreateSolidBrush(colw - m_colPen); pScreenDC->DrawDragRect(&newRect, CSize(1, 1), &oldRect, CSize(1, 1), &brush, &brush); //显示边界矩形 } break; case ID_VIEW_PAN: { //CBrush* pOldBrush = (CBrush*)pXyDC->GetDC()->SelectStockObject(NULL_BRUSH); //CPen* pOldPen = (CPen*)pXyDC->GetDC()->SelectStockObject(BLACK_PEN); //int old = pXyDC->GetDC()->SetROP2(R2_NOT); MouseMovePan(point); //pXyDC->GetDC()->SelectObject(pOldBrush); //pXyDC->GetDC()->SelectObject(pOldPen); //pXyDC->GetDC()->SetROP2(old); } break; } return 1; } void CItemView::RectangleSolid(CXyDC* pDC, CRect8* pRect) { COLORREF m_colPen=RGB(49,106,197); COLORREF m_colBrush=RGB(198,214,239); COLORREF colw=RGB(255,255,255); CBrush brush; brush.CreateSolidBrush(colw-m_colBrush); CPen pen; pen.CreatePen(PS_SOLID, 1, colw-m_colPen); CBrush *oldBrush = pDC->GetDC()->SelectObject(&brush); CPen *oldPen = pDC->GetDC()->SelectObject(&pen); int oldRop = pDC->GetDC()->SetROP2(R2_MASKPENNOT|R2_MASKNOTPEN); pDC->Rectangle(*pRect); pDC->GetDC()->SetROP2(oldRop); pDC->GetDC()->SelectObject(oldBrush); pDC->GetDC()->SelectObject(oldPen); } void CItemView::LButtonDownPan(CPoint point) { CSigmaView* pView = (CSigmaView*)GetDrawView(); //CXyDC *pXyDC = GetDC(); //CBrush* pOldBrush = (CBrush*)pXyDC->GetDC()->SelectStockObject(NULL_BRUSH); //CPen* pOldPen = (CPen*)pXyDC->GetDC()->SelectStockObject(BLACK_PEN); //int old = pXyDC->GetDC()->SetROP2(R2_NOT); switch (GetPanMode()) { case 0: break; default: case 1: // { // CRect client=GetClientRect(); // pXyDC->GetDC()->Rectangle(client); // } // break; //case 2: if (pView->GetMemDC() == NULL) { CRect rect=pView->GetClientRect(); // TODO:可以优化,避免重绘 pView->CreateMemDC(rect, NULL); pView->OnDrawAll(pView->GetMemDC()); } //{ // CRect client=GetClientRect(); // if( m_MemDC.GetSize().cxGetDC()); // } // CDC* pDC=GetView()->CWnd::GetDC(); // m_MemDC.FromDC(pDC); // GetView()->CWnd::ReleaseDC(pDC); //} break; } //pXyDC->GetDC()->SelectObject(pOldBrush); //pXyDC->GetDC()->SelectObject(pOldPen); //pXyDC->GetDC()->SetROP2(old); } void CItemView::MouseMovePan(CPoint point) { CXyDC *pXyDC = GetDC(); switch (GetPanMode()) { case 0: pXyDC->MoveTo(m_rect.left, m_rect.top); pXyDC->LineTo(m_rect.right, m_rect.bottom); m_rect.right = pXyDC->GetRX(point.x); m_rect.bottom = pXyDC->GetRY(point.y); pXyDC->MoveTo(m_rect.left, m_rect.top); pXyDC->LineTo(m_rect.right, m_rect.bottom); break; default: case 1: // { // CRect client=GetClientRect(); // CPoint pt=pXyDC->GetScreen(m_rect.BottomRight())-pXyDC->GetScreen(m_rect.TopLeft()); // client.OffsetRect(pt); // pXyDC->GetDC()->Rectangle(client); // m_rect.right=pXyDC->GetRX(point.x); // m_rect.bottom=pXyDC->GetRY(point.y); // pt=pXyDC->GetScreen(m_rect.BottomRight())-pXyDC->GetScreen(m_rect.TopLeft()); // GetView()->GetClientRect(&client); // client.OffsetRect(pt); // pXyDC->GetDC()->Rectangle(client); // } // break; //case 2: { CRect client, rt; client = GetClientRect(); m_rect.right = pXyDC->GetRX(point.x); m_rect.bottom = pXyDC->GetRY(point.y); CPoint pt = pXyDC->GetScreen(m_rect.BottomRight()) - pXyDC->GetScreen(m_rect.TopLeft()); //TRACE(_T("CItemView::MouseMovePan:m_rect.left=%lf,m_rect.top=%lf\n"), m_rect.left, m_rect.top); //TRACE(_T("CItemView::MouseMovePan:m_rect.right=%lf,m_rect.bottom=%lf,point.x=%ld,point.y=%ld\n"), //m_rect.right, m_rect.bottom, point.x, point.y); //CDC* pDC= pXyDC->GetDC(); //int od = pXyDC->GetDC()->SetROP2(R2_NOTXORPEN); //pXyDC->MoveTo(point.x, point.y); //pXyDC->LineTo(pt.x, pt.y); //GetDC()->GetDC()->SetROP2(od); CDC* pScreenDC = ((CSigmaView*)GetDrawView())->GetScreenDC(); CDC* pImgDC = ((CSigmaView*)GetDrawView())->GetImgDC(); //SaveAs(pImgDC, L"c:\\tmpCpp.bmp"); pScreenDC->BitBlt(pt.x, pt.y, client.Width(), client.Height() , pImgDC, 0, 0, SRCCOPY); COLORREF clrBack = this->m_BackColor; rt = client; if (pt.x < 0) rt.left = rt.right + pt.x; else rt.right = rt.left + pt.x; pScreenDC->FillSolidRect(rt, clrBack); rt = client; if (pt.y < 0) rt.top = rt.bottom + pt.y; else rt.bottom = rt.top + pt.y; pScreenDC->FillSolidRect(rt, clrBack); } break; } //CString str; str.Format("Length=%.2lf", _hypot(m_rect.left - m_rect.right, m_rect.top - m_rect.bottom)); //GetDrawDoc()->SetStatusBarInfo(0, str); } void CItemView::MouseMovePanForPreviewPrint(CPoint point) { CRect client, rt; client = GetClientRect(); CXyDC * pXyDC = GetDC(); m_rectForPrint.right = pXyDC->GetRX(point.x); m_rectForPrint.bottom = pXyDC->GetRY(point.y); } void CItemView::LButtonUpPan(CPoint point) { } void CItemView::OnRButtonDown(UINT nFlags, CPoint point) { /*if(!IsOldMode()) { if(GetType()==ID_VIEW_WINDOW) { m_bRButtonDown=TRUE; EnablePopupRightMenu(FALSE); OnSetCursor(GetDrawView(),0,0); } else this->SetType(0); } else this->SetType(0); GetDrawDoc()->SetDefaultCursor();*/ } BOOL CItemView::OnRButtonUp(UINT nFlags, CPoint point) { //if(!IsOldMode()) //{ // if(GetType()==ID_VIEW_WINDOW && m_bRButtonDown==TRUE) // { // GetDrawDoc()->PushActionDC(GetType()); // //GetDrawDoc()->PushDC(); // m_bRButtonDown=FALSE; // CXyDC *pXyDC=GetDC(); // Reduce(pXyDC->GetReal(point), 1/::GetPreferences().GetZoomFactor()); // GetDrawDoc()->Invalidate(); // GetDrawDoc()->SetDefaultCursor(); // EnablePopupRightMenu(TRUE); // OnSetCursor(GetDrawView(),0,0); // return FALSE; // } //} return CItemBase::OnRButtonUp(nFlags,point); } void CItemView::OnRButtonDblClk(UINT nFlags, CPoint point) { OnRButtonDown(nFlags,point); } BOOL CItemView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { /*switch(nChar) { case VK_SHIFT: if(GetType()==ID_VIEW_WINDOW) { GetDrawDoc()->GetCursor().SetCursor(GetCursor()); GetDrawDoc()->GetCursor().SetCursor(); } break; case VK_ESCAPE: this->SetType(0); GetDrawDoc()->SetDefaultCursor(); return TRUE; }*/ return FALSE; } BOOL CItemView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { //switch(nChar) //{ //case VK_SHIFT: // if(GetType()==ID_VIEW_WINDOW) // { // GetDrawDoc()->GetCursor().SetCursor(GetCursor()); // GetDrawDoc()->GetCursor().SetCursor(); // } // break; //} return CItemBase::OnKeyUp(nChar, nRepCnt, nFlags); } void CItemView::Extend(int mode) { //将上一个显示状态入栈 GetDrawDoc()->PushActionDC(ID_VIEW_EXTEND); CRect m_window=GetClientRect(); if(m_window.Width()<100)m_window.SetRect(0,0,640,480); CRect8 rect(1e100,-1e100,-1e100,1e100); if (GetViewRange(rect)) { ((CSigmaDoc*) GetDrawDoc())->m_xyDC.Extend(rect, m_window, mode); } //GetDrawDoc()->Invalidate(); } BOOL CItemView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { //GetDrawDoc()->GetCursor().SetCursor(GetCursor()); //return GetDrawDoc()->GetCursor().SetCursor(); return TRUE; } void CItemView::Enlarge(void) { //将上一个显示状态入栈 GetDrawDoc()->PushActionDC(ID_VIEW_ENLARGE); //Reduce(::GetPreferences().GetZoomFactor()); //GetDrawDoc()->Invalidate(); Reduce(1.5); } void CItemView::Reduce() { //将上一个显示状态入栈 GetDrawDoc()->PushActionDC(ID_VIEW_REDUCE); ////GetDrawDoc()->PushDC(); //Reduce(1/::GetPreferences().GetZoomFactor()); //GetDrawDoc()->Invalidate(); Reduce(1.0 / 1.5); } void CItemView::Reduce(double factor) { m_zoomFactor *= factor; //m_nScaleMode放大缩小的原点选择,0=屏幕左上角,1=屏幕中心 //switch(::GetPreferences().Workaround.m_nScaleMode) switch(zoomMode) { case 0: default: ((CSigmaDoc*)GetDrawDoc())->m_xyDC.Reduce(factor); break; case 1: CView* pView=(CView*)GetActiveView(); if(pView) { CRect rt=GetClientRect(); CPoint2D pt1= ((CSigmaDoc*)GetDrawDoc())->m_xyDC.GetReal(rt.CenterPoint()); Reduce(pt1,factor); } else ((CSigmaDoc*)GetDrawDoc())->m_xyDC.Reduce(factor); break; } } void CItemView::Reduce(CPoint2D point, double factor) { // 我们在具体实现的时候,事实上是先放大,再平移,使原来的 point(通常是光标所在点) 保持屏幕位置不变 CXyDC &pXyDC = GetDrawDoc()->m_xyDC; int screenX = pXyDC.GetSX(point.x0); int screenY = pXyDC.GetSY(point.y0); pXyDC.Reduce(factor); int realX = pXyDC.GetRX((long)screenX); int realY = pXyDC.GetRY((long)screenY); pXyDC.OffsetRect(point.x0 - realX, point.y0 - realY); //CRect rt=GetClientRect(); //CPoint2D p8=GetDrawDoc()->GetDC().GetReal(rt.CenterPoint()); //point.x0-=p8.x0; //point.y0-=p8.y0; //GetDrawDoc()->GetDC().OffsetRect(point.x0,point.y0); } void CItemView::ReduceForScreenPoint() { CPoint centerPtScreen = GetClientRect().CenterPoint(); CPoint2D centerPtWorldOld = m_pDoc->GetDC().GetReal(centerPtScreen); Reduce(); centerPtScreen = GetClientRect().CenterPoint(); CPoint2D centerPtWorld = m_pDoc->GetDC().GetReal(centerPtScreen); double offsetX = centerPtWorld.x0 - centerPtWorldOld.x0; double offsetY = centerPtWorld.y0 - centerPtWorldOld.y0; //CPoint centerPtScreenOld = m_pDoc->GetDC().GetScreen(centerPtWorld); //CPoint offset = centerPtScreenOld - centerPtScreen; //double offsetX = m_pDoc->GetDC().GetRX(offset.x); //double offsetY = m_pDoc->GetDC().GetRY(offset.y); m_pDoc->GetDC().OffsetRect(-offsetX, -offsetY); //point.x0-=p8.x0; //point.y0-=p8.y0; //GetDrawDoc()->GetDC().OffsetRect(point.x0,point.y0); } void CItemView::PanTo(CPoint2D point) { CRect rt=GetClientRect(); CPoint2D p8= ((CSigmaDoc*)GetDrawDoc())->m_xyDC.GetReal(rt.CenterPoint()); point.x0-=p8.x0; point.y0-=p8.y0; m_offsetX += point.x0; m_offsetY += point.y0; ((CSigmaDoc*)GetDrawDoc())->m_xyDC.OffsetRect(point.x0,point.y0); } CRect CItemView::GetClientRect(void) { //CRect rt; //rt = ((CSigmaView*)(GetDrawView()))->m_client; //return rt; return m_clientRect; } void CItemView::setClientRect(CRect rect) { m_clientRect = rect; } CView* CItemView::GetActiveView(void) { CView* pView = (CView*)m_pDoc->GetView(); return pView; } BOOL CItemView::IsCaptureCursor(void) { return bCaptureCursor; } int CItemView::GetPanMode(void) { /*return ::GetPreferences().Workaround.m_nMoveIdea;*/ return 1; } void CItemView::SetDisplayRange(void) { CRect rt = GetClientRect(); ((CSigmaDoc*)GetDrawDoc())->m_pXy->m_display=GetDC()->GetReal(rt); ((CSigmaDoc*)GetDrawDoc())->m_pXy->m_display.NormalizeRect(); } int GetEncoderClsid(const wchar_t* format, CLSID* pClsid) { UINT num = 0; UINT size = 0; ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if (size == 0) return -1; pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if (pImageCodecInfo == NULL) return -1; GetImageEncoders(num, size, pImageCodecInfo); for (UINT j = 0; j < num; ++j) { if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; } } free(pImageCodecInfo); return -1; } BOOL SaveAs(CDC* pDC, const wchar_t* lpszFilename) { CBitmap* pBitmap = pDC->GetCurrentBitmap(); BITMAP bmp; pBitmap->GetBitmap(&bmp); CRect rcClient = CRect(0, 0, bmp.bmWidth, bmp.bmHeight); CBitmap screenbitmap; screenbitmap.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); CDC memDC; memDC.CreateCompatibleDC(pDC); CBitmap *pOldBitmap = memDC.SelectObject(&screenbitmap); memDC.SetStretchBltMode(HALFTONE); memDC.StretchBlt(0, 0, rcClient.Width(), rcClient.Height(), pDC, 0, 0, rcClient.Width(), rcClient.Height(), SRCCOPY); memDC.SelectObject(pOldBitmap); Bitmap bitmap((HBITMAP)screenbitmap.GetSafeHandle(), NULL); CLSID picClsid; CString sFileName(lpszFilename); CString sExt = sFileName.Right(3).MakeLower(); if (sExt == "jpg") { ULONG encoderQuality = 80; //压缩比例 EncoderParameters encoderParameters; encoderParameters.Count = 1; encoderParameters.Parameter[0].Guid = EncoderQuality; encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong; encoderParameters.Parameter[0].NumberOfValues = 1; encoderParameters.Parameter[0].Value = &encoderQuality; GetEncoderClsid(L"image/jpeg", &picClsid); bitmap.Save(lpszFilename, &picClsid, &encoderParameters); } else if (sExt == "png") { GetEncoderClsid(L"image/png", &picClsid); bitmap.Save(lpszFilename, &picClsid, NULL); } else if (sExt == "bmp") { GetEncoderClsid(L"image/bmp", &picClsid); bitmap.Save(lpszFilename, &picClsid, NULL); } else { DeleteObject(screenbitmap); memDC.DeleteDC(); return FALSE; } DeleteObject(screenbitmap); memDC.DeleteDC(); return TRUE; } }//namespace