Manipulating Draw Mode Settings and Using GDI+ to Save | CodeGuru

Manipulating Draw Mode Settings and Using GDI+ to Save

Click here for a larger image. Environment: Tested on Windows 2000 A simple demonstration of draw mode settings as well as a demonstration using GDI+ to save to a file. This is my first column. I’ll show you how to set the drawing mode with SetROP2. Parameters R2_NOTXORPEN Pixel are the inverse of the R2_XORPEN […]

Written By
CodeGuru Staff
CodeGuru Staff
Sep 3, 2002
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More



Click here for a larger image.

Environment: Tested on Windows 2000

A simple demonstration of draw mode settings as well as a demonstration using GDI+ to save to a file.

This is my first column. I’ll show you how to set the drawing mode with SetROP2. Parameters R2_NOTXORPEN Pixel are the inverse of the R2_XORPEN color (final pixel = NOT(pen XOR screen pixel)).

LRESULT CMiniProjectView::WindowProc
        (UINT message, WPARAM wParam, LPARAM lParam)
{
  CDC *pDC = NULL;
  CMiniProjectDoc *pDoc = NULL;
  CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd();
  CPen *pOldPen = NULL;
  CDrawObj *pDwObj = NULL;
  CRect rcClient, rcRT, rcSave;
  CPoint ptClientUL, ptClientLR;
  static POINTS ptsBegin;
  static POINTS ptsEnd;
  static POINTS ptsPrevEnd;
  static BOOL bPrevLine = FALSE;
  INT_PTR nNewFH = 0;
  switch (message)
  {
    case WM_SAVE_TO_FILE:
      SaveToFile((BOOL)wParam);
      break;
    case WM_RECT_TRACK:
      pDoc = GetDocument();
      ASSERT(pDoc);
      GetClientRect(&rcClient);
      m_bSelArea = (BOOL)wParam;
      if((INT)lParam == 1)
        rcRT.CopyRect(DEF_RECT1);
      else
        rcRT.CopyRect(DEF_RECT2);
      rcRT.SetRect(0, 0, rcRT.Width() * MULTI,
                         rcRT.Height() * MULTI);
      rcRT.OffsetRect((rcClient.Width()
                       -rcRT.Width()) >> 1, (rcClient.Height()
                       -rcRT.Height()) >> 1);
      pDoc->m_rtSelArea.m_rect.CopyRect(rcRT);
      InvalidateRect(&rcClient, TRUE);
      break;
      case WM_LBUTTONDOWN:
      ptsBegin = MAKEPOINTS(lParam);
      pDoc = GetDocument();
      ASSERT(pDoc);
      if(m_bSelArea)
      {
        pDoc->m_rtSelArea.GetTrueRect(&rcSave);
        if(pDoc->m_rtSelArea.HitTest
          (CPoint(ptsBegin.x, ptsBegin.y)) !=
                  CRectTracker::hitNothing)
        {
          pDoc->m_rtSelArea.Track(this, CPoint
                                 (ptsBegin.x, ptsBegin.y));
          Invalidate(TRUE);
          return 0;
        }
      }
      SetCapture();
      GetClientRect(&rcClient);
      ptClientUL.x = rcClient.left;
      ptClientUL.y = rcClient.top;
      ptClientLR.x = rcClient.right + 1;
      ptClientLR.y = rcClient.bottom + 1;
      ClientToScreen(&ptClientUL);
      ClientToScreen(&ptClientLR);
      SetRect(&rcClient, ptClientUL.x, ptClientUL.y,
                         ptClientLR.x, ptClientLR.y);
      ClipCursor(&rcClient);
      if(pMainFrame->m_eActiveStyle == eFreehandStyle)
      {
        ASSERT(pDoc->m_parrObj);
        pDoc->m_parrObj->Add(new CDrawObj
                         (CRect(ptsBegin.x, ptsBegin.y,
                                ptsEnd.x, ptsEnd.y),
                                pMainFrame->m_eActiveStyle));
      }
      return 0;
      case WM_MOUSEMOVE:
      pDoc = GetDocument();
      if (wParam & MK_LBUTTON)
      {
        pDC = GetDC();
        pDC->SetROP2(R2_NOTXORPEN);
        CPen pen(PS_SOLID, PEN_WIDTH, RGB(0, 0, 0));
        pOldPen = pDC->SelectObject(&pen);
        switch(pMainFrame->m_eActiveStyle)
        {
          case eLineStyle:
            if (bPrevLine)
            {
              pDC->MoveTo(ptsBegin.x, ptsBegin.y);
              pDC->LineTo(ptsPrevEnd.x, ptsPrevEnd.y);
          }
            ptsEnd = MAKEPOINTS(lParam);
            pDC->MoveTo(ptsBegin.x, ptsBegin.y);
            pDC->LineTo(ptsEnd.x, ptsEnd.y);
            bPrevLine = TRUE;
            ptsPrevEnd = ptsEnd;
            break;
          case eSquareStyle:
            if (bPrevLine)
              pDC->Rectangle(ptsBegin.x, ptsBegin.y,
                             ptsPrevEnd.x, ptsPrevEnd.y);
          ptsEnd = MAKEPOINTS(lParam);
          pDC->Rectangle(ptsBegin.x,  ptsBegin.y,
                            ptsEnd.x, ptsEnd.y);
            bPrevLine = TRUE;
            ptsPrevEnd = ptsEnd;
            break;
          case eFreehandStyle:
            ptsEnd = MAKEPOINTS(lParam);
            pDC->MoveTo(ptsBegin.x, ptsBegin.y);
            pDC->LineTo(ptsEnd.x, ptsEnd.y);
            bPrevLine = TRUE;
            ptsPrevEnd = ptsEnd;
            ptsBegin = ptsEnd;
            //save point
            nNewFH = pDoc->m_parrObj->GetCount() – 1;
            if(nNewFH >= 0)
            {
              pDwObj = (CDrawObj *)pDoc->m_parrObj->GetAt(nNewFH);
              if(pDwObj == NULL)
              {TRACE0(“Get NULL of Freehand object\n”);
                break;
              }
              if(pDwObj->m_eStyle == eFreehandStyle)
                pDwObj->m_parrPoint->Add(new CPoint
                                        (ptsEnd.x, ptsEnd.y));
            }
            break;
          case eCircleStyle:
            if (bPrevLine)
              pDC->Ellipse(ptsBegin.x, ptsBegin.y,
                           ptsPrevEnd.x, ptsPrevEnd.y);
            ptsEnd = MAKEPOINTS(lParam);
            if((ptsEnd.x – ptsBegin.x > 0) &&
                          (ptsEnd.x – ptsBegin.x < MIN_SIZE))
              break;
            else if((ptsEnd.x – ptsBegin.x < 0) &&
                    (ptsBegin.x – ptsEnd.x < MIN_SIZE))
              break;
            else
            {
              pDC->Ellipse(ptsBegin.x, ptsBegin.y,
                           ptsEnd.x, ptsEnd.y);
              bPrevLine = TRUE;
              ptsPrevEnd = ptsEnd;
            }
            break;
          default:
            break;
        } //end style
        pDC->SelectObject(pOldPen);
        pDC->ReleaseOutputDC();
      }
            break;
         case WM_LBUTTONUP:
      pDoc = GetDocument();
      bPrevLine = FALSE;
      ClipCursor(NULL);
      ReleaseCapture();
      ASSERT(pDoc->m_parrObj);
      if(pMainFrame->m_eActiveStyle != eFreehandStyle)
      {
        pDoc->m_parrObj->Add(new CDrawObj( CRect
                            (ptsBegin.x, ptsBegin.y,
                             ptsEnd.x, ptsEnd.y),
                             pMainFrame->m_eActiveStyle));
      }
      return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
  }
  return CView::WindowProc(message, wParam, lParam);
}

For saving to a file, I showed you how to use GDI+. Before using GDI+, you must initialize GDI+ with GdiplusStartup(…) and override GetEncoderClsid(…) to get the encode class identified for the target image type.

int CMiniProjectView::GetEncoderClsid
                      (const WCHAR* format, CLSID* pClsid)
{
  UINT  num = 0;          // number of image encoders
  UINT  size = 0;         // size of the image encoder array
                          // in bytes
  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;  // Success
    }
  }
  free(pImageCodecInfo);
  return -1;
}
  GdiplusStartupInput gdiplusStartupInput;
  ULONG_PTR gdiplusToken;
  GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
  Bitmap *pBitmap = Bitmap::FromHBITMAP(
                    (HBITMAP)bmp.GetSafeHandle(),
                    (HPALETTE)pPalette->GetSafeHandle());
  //get encoder CLSID
  CLSID Clsid;
  if(fileDlg.GetFileExt().MakeUpper() == _T(“BMP”))
    GetEncoderClsid(L”image/bmp”, &Clsid);
  else if(fileDlg.GetFileExt().MakeUpper() == _T(“GIF”))
    GetEncoderClsid(L”image/gif”, &Clsid);
  else if(fileDlg.GetFileExt().MakeUpper() == _T(“JPG”))
    GetEncoderClsid(L”image/jpeg”, &Clsid);
  //save to file with current color
  BSTR bstrFileName = fileDlg.GetPathName().AllocSysString();
  pBitmap->Save(bstrFileName, &Clsid, NULL);
  //clear and shutdown GDI+
  SysFreeString(bstrFileName);
  GdiplusShutdown(gdiplusToken);

You must initialize an array of EncoderParameters if you want to set parameters for encoding.

  long nCompress = 0;
  EncoderParameters encoderParameters[2];
  encoderParameters[0].Count = 2;
  encoderParameters[0].Parameter[0].Guid = EncoderQuality;
  encoderParameters[0].Parameter[0].NumberOfValues = 1;
  encoderParameters[0].Parameter[0].Type =
                       EncoderParameterValueTypeLong;
  encoderParameters[0].Parameter[0].Value = &nCompress;
  int nDep = 1;
  encoderParameters[1].Parameter[0].Guid = EncoderColorDepth;
  encoderParameters[1].Parameter[0].NumberOfValues = 1;
  encoderParameters[1].Parameter[0].Type =
                       EncoderParameterValueTypeLong;
  encoderParameters[1].Parameter[0].Value = &nDep;
  //save to file with current color
  BSTR bstrFileName =  fileDlg.GetPathName().AllocSysString();
  pBitmap->Save(bstrFileName, &Clsid, encoderParameters);

Downloads


Download demo project – 44 Kb


Download source – 202 Kb

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.