Manipulating Draw Mode Settings and Using GDI+ to Save

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

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read