// XTPImageEditor.cpp : implementation of the CXTPImageEditorDlg class. // // This file is a part of the XTREME COMMANDBARS MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Resource.h" #include "Common/Resource.h" #include "Common/XTPVC80Helpers.h" #include "Common/XTPResourceManager.h" #include "Common/XTPImageManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPColorManager.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPHookManager.h" #include "XTPCommandBarsDefines.h" #include "XTPCommandBar.h" #include "XTPToolBar.h" #include "XTPImageEditor.h" #include "XTPMouseManager.h" #include "XTPPaintManager.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define UNDO_COUNT 15 #define CLR_TO_RGBQUAD(clr) (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr))) void CXTPImageEditorPicture::CAlphaBitmap::CreateEditorBitmap(int nWidth, int nHeight) { Attach(CXTPImageManager::Create32BPPDIBSection(0, nWidth, nHeight)); } ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorPicture CXTPImageEditorPicture::CXTPImageEditorPicture() { m_pCurrentBitmap = NULL; m_pPictureBitmap = NULL; m_pParentWnd = NULL; m_bTracked = FALSE; m_clrDraw = 0; m_hCursorLine = XTPResourceManager()->LoadCursor(XTP_IDC_COMMANDBARS_LINE); m_hCursorFillColor = XTPResourceManager()->LoadCursor(XTP_IDC_COMMANDBARS_FILLCOLOR); m_hCursorPencil = XTPResourceManager()->LoadCursor(XTP_IDC_COMMANDBARS_PENCIL); m_hCursorPickColor = XTPResourceManager()->LoadCursor(XTP_IDC_COMMANDBARS_PICKCOLOR); } CXTPImageEditorPicture::~CXTPImageEditorPicture() { if (m_pPictureBitmap) { delete m_pPictureBitmap; } if (m_pCurrentBitmap) { delete m_pCurrentBitmap; } while (!m_lstUndo.IsEmpty()) { CBitmap* pBitmap = m_lstUndo.RemoveTail(); if (pBitmap) delete pBitmap; } while (!m_lstRedo.IsEmpty()) { CBitmap* pBitmap = m_lstRedo.RemoveTail(); if (pBitmap) delete pBitmap; } } void CXTPImageEditorPicture::Init(UINT nID, CXTPImageEditorDlg* pParentWnd) { m_pParentWnd = pParentWnd; SubclassDlgItem(nID, pParentWnd); m_szPicture = pParentWnd->m_szPicture; CRect rc; GetWindowRect(rc); m_szItem = CSize (rc.Width() / m_szPicture.cx, rc.Height() / m_szPicture.cy); CSize sz(m_szItem.cx * m_szPicture.cx, m_szItem.cy * m_szPicture.cy); SetWindowPos(&CWnd::wndTop, rc.left, rc.top, sz.cx + 1, sz.cy + 1, SWP_NOMOVE); m_dcPicture.CreateCompatibleDC(NULL); } XTPImageEditorTools CXTPImageEditorPicture::GetSelectedTool() { ASSERT(m_pParentWnd); if (!m_pParentWnd) return xtpToolPencil; return m_pParentWnd->m_toolSelected; } COLORREF CXTPImageEditorPicture::GetSelectedColor() { ASSERT(m_pParentWnd); if (m_pParentWnd && m_pParentWnd->m_pSelected) { return m_pParentWnd->m_pSelected->GetColor(); } return 0; } BEGIN_MESSAGE_MAP(CXTPImageEditorPicture, CStatic) //{{AFX_MSG_MAP(CXTPImageEditorPicture) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_CAPTURECHANGED() ON_WM_LBUTTONUP() ON_WM_SETCURSOR() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorPicture message handlers BOOL CXTPImageEditorPicture::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/) { ::SetCursor( GetSelectedTool() == xtpToolFill ? m_hCursorFillColor : GetSelectedTool() == xtpToolPencil ? m_hCursorPencil : GetSelectedTool() == xtpToolGetColor ? m_hCursorPickColor : m_hCursorLine ); return TRUE; } void CXTPImageEditorPicture::OnPaint() { CPaintDC dcPaint(this); // device context for painting CXTPClientRect rc(this); CXTPBufferDC dc(dcPaint, rc); dc.FillSolidRect(rc, RGB(255, 255, 255)); BOOL bAlpha = m_pPictureBitmap != 0 && m_pPictureBitmap->m_bAlpha; PINT pBits = 0; PBITMAPINFO pbmi = 0; UINT nSize; if (m_pPictureBitmap) { if (!CXTPImageManagerIcon::GetBitmapBits(dc, (HBITMAP)m_pPictureBitmap->GetSafeHandle(), pbmi, (LPVOID&)pBits, nSize)) return; } if (pbmi == NULL || pBits == NULL) { return; } for (int x = 0; x < rc.Width(); x++) for (int y = 0; y < rc.Height(); y++) { CPoint pt = CPoint(m_szPicture.cx * x / rc.Width(), m_szPicture.cy * y / rc.Height()); COLORREF clr; if (bAlpha) { clr = pBits[(pt.y * pbmi->bmiHeader.biWidth + pt.x)]; int nAlpha = (clr & 0xFF000000) >> 24; int nColor = (((x +3) / 4)+ ((y +3)/ 4)) % 2 == 0 ? 255 : 235; clr = RGB(nColor - (nColor - GetBValue(clr)) * nAlpha / 255, nColor - (nColor - GetGValue(clr)) * nAlpha / 255, nColor - (nColor - GetRValue(clr)) * nAlpha / 255); } else { clr = m_pPictureBitmap == NULL ? XTPCOLOR_ERASE : pBits[(pt.y * pbmi->bmiHeader.biWidth + pt.x)]; clr = CLR_TO_RGBQUAD(clr); if (clr == XTPCOLOR_ERASE) clr = (((x +3) / 4)+ ((y +3)/ 4)) % 2 == 0 ? RGB(255, 255, 255) : RGB(235, 235, 235); } dc.SetPixel(x, rc.Height() - y - 1, clr); } free(pBits); free(pbmi); dc.Draw3dRect(rc, 0, 0); } COLORREF CXTPImageEditorPicture::GetPicturePixel(CPoint point) { CAlphaBitmap bmp; bmp.CreateEditorBitmap(m_szPicture.cx, m_szPicture.cy); CBitmap* pOldBitmap = m_dcPicture.SelectObject(&bmp); m_dcPicture.FillSolidRect(0, 0, m_szPicture.cx, m_szPicture.cy, XTPCOLOR_ERASE); if (m_pPictureBitmap) m_dcPicture.DrawState(0, m_szPicture, m_pPictureBitmap, DSS_NORMAL, (CBrush*)NULL); COLORREF clr = m_dcPicture.GetPixel(point); m_dcPicture.SelectObject(pOldBitmap); return clr; } CPoint CXTPImageEditorPicture::ClientToPicture(CPoint pt) { ASSERT(m_szItem.cx > 0 && m_szItem.cy > 0); return CPoint(pt.x / m_szItem.cx, pt.y / m_szItem.cy); } void CXTPImageEditorPicture::CopyBitmap(CAlphaBitmap* pBitmapCopyTo, CAlphaBitmap* pBitmapCopyFrom, CSize sz, CPoint ptOffset, COLORREF clrTransparentFrom, COLORREF clrTransparentTo, CDC* pDC) { CDC dc; dc.CreateCompatibleDC(pDC); pBitmapCopyTo->CreateEditorBitmap(sz.cx, sz.cy); CBitmap* pOldBitmap = dc.SelectObject(pBitmapCopyTo); dc.FillSolidRect(0, 0, sz.cx, sz.cy, XTPCOLOR_ERASE); if (pBitmapCopyFrom) { dc.DrawState(ptOffset, sz, pBitmapCopyFrom, DSS_NORMAL, (CBrush*)NULL); if (clrTransparentFrom != clrTransparentTo && !pBitmapCopyFrom->m_bAlpha) { for (int x = 0; x < sz.cx; x++) { for (int y = 0; y < sz.cy; y++) { if (dc.GetPixel(x, y) == clrTransparentFrom) dc.SetPixel(x, y, clrTransparentTo); } } } } dc.SelectObject(pOldBitmap); pBitmapCopyTo->m_bAlpha = pBitmapCopyFrom ? pBitmapCopyFrom->m_bAlpha : FALSE; } void CXTPImageEditorPicture::OnPictureChanged() { Invalidate(FALSE); m_pParentWnd->OnPictureChanged(); } void CXTPImageEditorPicture::Apply() { while (!m_lstRedo.IsEmpty()) { CBitmap* pBitmap = m_lstRedo.RemoveTail(); if (pBitmap) delete pBitmap; } if (m_lstUndo.GetCount() > UNDO_COUNT) { CBitmap* pBitmap = m_lstUndo.RemoveHead(); if (pBitmap) delete pBitmap; } m_lstUndo.AddTail(m_pCurrentBitmap); m_pCurrentBitmap = NULL; OnPictureChanged(); } void CXTPImageEditorPicture::OnLButtonDown(UINT nFlags, CPoint point) { ASSERT(m_pCurrentBitmap == NULL); switch (GetSelectedTool()) { case xtpToolFill: { m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CopyBitmap(m_pPictureBitmap, m_pCurrentBitmap, m_szPicture); CBitmap* pOldBitmap = m_dcPicture.SelectObject(m_pPictureBitmap); CXTPBrushDC brush(m_dcPicture, GetSelectedColor()); CPoint ptFill(ClientToPicture(point)); m_dcPicture.ExtFloodFill(ptFill.x, ptFill.y, GetPicturePixel(ptFill), FLOODFILLSURFACE); m_dcPicture.SelectObject(pOldBitmap); if (m_pCurrentBitmap && m_pCurrentBitmap->m_bAlpha) FixAlphaLayer(m_pPictureBitmap, m_pCurrentBitmap); Apply(); } break; case xtpToolGetColor: { COLORREF clr = GetPicturePixel(ClientToPicture(point)); m_pParentWnd->m_wndPicker.SetColor(clr); m_pParentWnd->SetSelected(&m_pParentWnd->m_wndPicker); m_pParentWnd->m_toolSelected = m_pParentWnd->m_toolPrevious; } break; case xtpToolPencil: case xtpToolRectangle: case xtpToolCircle: case xtpToolLine: { m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CopyBitmap(m_pPictureBitmap, m_pCurrentBitmap, m_szPicture); m_clrDraw = GetSelectedColor() != GetPicturePixel(ClientToPicture(point)) ? GetSelectedColor() : XTPCOLOR_ERASE; m_bTracked = TRUE; m_ptTracked = point; SetCapture(); OnMouseMove(nFlags, point); } break; default : ASSERT(FALSE); } CStatic::OnLButtonDown(nFlags, point); } void CXTPImageEditorDlg::FixAlphaLayer(LPBYTE pBits, UINT nCount) { if (pBits == 0) return; LPBYTE pBitsI = pBits; for (UINT i = 0; i < nCount; i++) { if (*(LPDWORD)pBitsI == 0) *(LPDWORD)pBitsI = XTPCOLOR_ERASE; int nAlpha = pBitsI[3]; if (nAlpha != 0) { pBitsI[0] = BYTE(pBitsI[0] * 255 / nAlpha); pBitsI[1] = BYTE(pBitsI[1] * 255 / nAlpha); pBitsI[2] = BYTE(pBitsI[2] * 255 / nAlpha); } pBitsI += 4; } } void CXTPImageEditorPicture::FixAlphaLayer(CAlphaBitmap* pDest, CAlphaBitmap* pSrc) { if (pSrc == 0 || pDest == 0) return; CDC dcSrc; dcSrc.CreateCompatibleDC(NULL); PINT pDestBits = 0, pSrcBits = 0; PBITMAPINFO pDestBmi = 0, pSrcBmi = 0; UINT nSize; if (!CXTPImageManagerIcon::GetBitmapBits(dcSrc, (HBITMAP)pDest->GetSafeHandle(), pDestBmi, (LPVOID&)pDestBits, nSize)) return; if (!CXTPImageManagerIcon::GetBitmapBits(dcSrc, (HBITMAP)pSrc->GetSafeHandle(), pSrcBmi, (LPVOID&)pSrcBits, nSize)) { free(pDestBits); free(pDestBmi); return; } PINT pFixedBits = NULL; HBITMAP hBitmapAlpha = CreateDIBSection(dcSrc, pDestBmi, DIB_RGB_COLORS, (void**)&pFixedBits, NULL, 0); if (hBitmapAlpha && pFixedBits) { MEMCPY_S(pFixedBits, pDestBits, nSize); for (UINT i = 0; i < nSize / 4; i++) { if (pDestBits[i] != pSrcBits[i]) { if (pDestBits[i] != XTPCOLOR_ERASE) pFixedBits[i] |= 0xFF000000; } } pDest->DeleteObject(); pDest->Attach(hBitmapAlpha); } free(pDestBits); free(pDestBmi); free(pSrcBits); free(pSrcBmi); } void CXTPImageEditorPicture::OnMouseMove(UINT nFlags, CPoint point) { if (m_bTracked) { if (GetSelectedTool() == xtpToolPencil) { CAlphaBitmap* pBitmap = new CAlphaBitmap(); CopyBitmap(pBitmap, m_pPictureBitmap, m_szPicture); CBitmap* pOldBitmap = m_dcPicture.SelectObject(pBitmap); m_dcPicture.SetPixel(ClientToPicture(point), m_clrDraw); m_dcPicture.SelectObject(pOldBitmap); if (m_pPictureBitmap->m_bAlpha) FixAlphaLayer(pBitmap, m_pPictureBitmap); if (m_pPictureBitmap) delete m_pPictureBitmap; m_pPictureBitmap = pBitmap; Invalidate(FALSE); OnPictureChanged(); } else { CAlphaBitmap* pBitmap = new CAlphaBitmap(); CopyBitmap(pBitmap, m_pCurrentBitmap, m_szPicture); CBitmap* pOldBitmap = m_dcPicture.SelectObject(pBitmap); CRect rcReftangle(ClientToPicture(m_ptTracked), ClientToPicture(point)); rcReftangle.NormalizeRect(); if (GetSelectedTool() == xtpToolRectangle) { m_dcPicture.Draw3dRect(rcReftangle, GetSelectedColor(), GetSelectedColor()); } if (GetSelectedTool() == xtpToolCircle) { CXTPPenDC pen(m_dcPicture, GetSelectedColor()); CXTPBrushDC brush(m_dcPicture, XTPCOLOR_ERASE); m_dcPicture.Ellipse(rcReftangle); } if (GetSelectedTool() == xtpToolLine) { CXTPPenDC pen(m_dcPicture, GetSelectedColor()); m_dcPicture.MoveTo(ClientToPicture(m_ptTracked)); m_dcPicture.LineTo(ClientToPicture(point)); } m_dcPicture.SelectObject(pOldBitmap); if (m_pPictureBitmap->m_bAlpha) FixAlphaLayer(pBitmap, m_pCurrentBitmap); if (m_pPictureBitmap) delete m_pPictureBitmap; m_pPictureBitmap = pBitmap; Invalidate(FALSE); OnPictureChanged(); } } CStatic::OnMouseMove(nFlags, point); } void CXTPImageEditorPicture::OnLButtonUp(UINT nFlags, CPoint point) { m_bTracked = FALSE; ReleaseCapture(); CStatic::OnLButtonUp(nFlags, point); } void CXTPImageEditorPicture::OnCaptureChanged(CWnd* pWnd) { m_bTracked = FALSE; Apply(); CStatic::OnCaptureChanged(pWnd); } void CXTPImageEditorPicture::Undo() { if (!m_lstUndo.IsEmpty()) { CAlphaBitmap* pBitmap = m_lstUndo.RemoveTail(); m_lstRedo.AddTail(m_pPictureBitmap); m_pPictureBitmap = pBitmap; OnPictureChanged(); } } void CXTPImageEditorPicture::Redo() { if (!m_lstRedo.IsEmpty()) { CAlphaBitmap* pBitmap = m_lstRedo.RemoveTail(); m_lstUndo.AddTail(m_pPictureBitmap); m_pPictureBitmap = pBitmap; OnPictureChanged(); } } void CXTPImageEditorPicture::Clear() { m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = NULL; Apply(); } void CXTPImageEditorPicture::MovePicture(CPoint ptOffset) { m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CopyBitmap(m_pPictureBitmap, m_pCurrentBitmap, m_szPicture, ptOffset); Apply(); } void CXTPImageEditorPicture::Copy() { if (!OpenClipboard ()) { return; } if (!::EmptyClipboard ()) { ::CloseClipboard (); return; } CAlphaBitmap bitmapCopy; CopyBitmap(&bitmapCopy, m_pPictureBitmap, m_szPicture, 0, XTPCOLOR_ERASE, GetXtremeColor(COLOR_3DFACE)); HANDLE hclipData = ::SetClipboardData (CF_BITMAP, bitmapCopy.Detach ()); if (hclipData == NULL) { TRACE (_T ("CXTPImageEditorPicture::Copy() error. Error code = %x\n"), GetLastError ()); } if (bitmapCopy.m_bAlpha) { SetClipboardData(XTPImageManager()->m_nAlphaClipFormat, GlobalAlloc(GMEM_MOVEABLE, 1)); } ::CloseClipboard (); } void CXTPImageEditorPicture::Paste() { COleDataObject data; if (!data.AttachClipboard ()) { return; } if (!data.IsDataAvailable (CF_BITMAP)) { return; } tagSTGMEDIUM dataMedium; if (!data.GetData (CF_BITMAP, &dataMedium)) { return; } if (!dataMedium.hBitmap) return; CAlphaBitmap bmpClip; BOOL bAlpha = FALSE; FORMATETC fetc; static TCHAR sz[256] ; data.BeginEnumFormats(); while (data.GetNextFormat(&fetc)) { if (GetClipboardFormatName((UINT)fetc.cfFormat, sz, 254)) { CString str(sz); if (str.Find(_T("DIB32")) > 0) { bAlpha = TRUE; break; } } } bmpClip.m_bAlpha = bAlpha ? bAlpha : data.IsDataAvailable(XTPImageManager()->m_nAlphaClipFormat); bmpClip.Attach(dataMedium.hBitmap); m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CopyBitmap(m_pPictureBitmap, &bmpClip, m_szPicture, 0, GetXtremeColor(COLOR_3DFACE), XTPCOLOR_ERASE); bmpClip.Detach(); Apply(); } void CXTPImageEditorPicture::Load() { CString strFilter; CXTPResourceManager::AssertValid(XTPResourceManager()->LoadString(&strFilter, XTP_IDS_IMAGEEDITOR_FILTER)); CFileDialog fd(TRUE, NULL, NULL, OFN_HIDEREADONLY, strFilter); if (fd.DoModal() == IDOK) { CString strExtension = fd.GetFileExt(); strExtension.MakeLower(); if (strExtension == _T("ico")) { HBITMAP hBitmap = CXTPImageManagerIcon::LoadAlphaIcon(fd.GetPathName(), m_szPicture.cx); if (!hBitmap) { HICON hIcon = (HICON)LoadImage(0, fd.GetPathName(), IMAGE_ICON, m_szPicture.cx, m_szPicture.cy, LR_CREATEDIBSECTION | LR_LOADFROMFILE); if (!hIcon) return; m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CDC dc; dc.CreateCompatibleDC(NULL); m_pPictureBitmap->CreateEditorBitmap(m_szPicture.cx, m_szPicture.cy); CBitmap* pOldBitmap = dc.SelectObject(m_pPictureBitmap); dc.FillSolidRect(0, 0, m_szPicture.cx, m_szPicture.cy, XTPCOLOR_ERASE); dc.DrawState(0, CSize(0, 0), hIcon, DSS_NORMAL, (CBrush*)NULL); dc.SelectObject(pOldBitmap); DestroyIcon(hIcon); } else { m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CAlphaBitmap bmpFile(TRUE); bmpFile.Attach(hBitmap); CopyBitmap(m_pPictureBitmap, &bmpFile, m_szPicture); } Apply(); } else if (strExtension == _T("bmp") || strExtension == _T("png")) { BOOL bAlphaBitmap = FALSE; HBITMAP hBmp = CXTPImageManagerIcon::LoadBitmapFromFile(fd.GetPathName(), &bAlphaBitmap); if (!hBmp) return; CAlphaBitmap bmpFile(bAlphaBitmap); bmpFile.Attach(hBmp); m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CopyBitmap(m_pPictureBitmap, &bmpFile, m_szPicture); Apply(); } else { LPPICTURE pPict = NULL; if (OleLoadPicturePath((LPOLESTR)XTP_CT2CW(fd.GetPathName()), NULL, 0, 0, IID_IPicture, (LPVOID*)&pPict) == S_OK) { m_pCurrentBitmap = m_pPictureBitmap; m_pPictureBitmap = new CAlphaBitmap(); CDC dc; dc.CreateCompatibleDC(NULL); m_pPictureBitmap->CreateEditorBitmap(m_szPicture.cx, m_szPicture.cy); CBitmap* pOldBitmap = dc.SelectObject(m_pPictureBitmap); dc.FillSolidRect(0, 0, m_szPicture.cx, m_szPicture.cy, XTPCOLOR_ERASE); long hmWidth; long hmHeight; pPict->get_Width(&hmWidth); pPict->get_Height(&hmHeight); pPict->Render(dc, 0, 0, m_szPicture.cx, m_szPicture.cy, 0, hmHeight-1, hmWidth, -hmHeight, 0); dc.SelectObject(pOldBitmap); Apply(); pPict->Release(); } } } } ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorPicker IMPLEMENT_DYNAMIC(CXTPImageEditorPicker, CStatic) CXTPImageEditorPicker::CXTPImageEditorPicker() { m_clr = 0; m_bSelected = FALSE; } void CXTPImageEditorPicker::SetColor(COLORREF clr) { m_clr = clr; if (m_hWnd) Invalidate(FALSE); } COLORREF CXTPImageEditorPicker::GetColor() { return m_clr; } void CXTPImageEditorPicker::SetSelected(BOOL bSelected) { m_bSelected = bSelected; if (m_hWnd) Invalidate(FALSE); } BEGIN_MESSAGE_MAP(CXTPImageEditorPicker, CStatic) //{{AFX_MSG_MAP(CXTPImageEditorPicker) ON_WM_PAINT() ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorPicker message handlers void CXTPImageEditorPicker::OnPaint() { CPaintDC dcPaint(this); // device context for painting CXTPClientRect rc(this); CXTPBufferDC dc(dcPaint, rc); if (m_clr != XTPCOLOR_ERASE) { dc.FillSolidRect(rc, m_clr); } else { CRect rcItem(rc); dc.FillSolidRect(rc, RGB(0xFF, 0xFF, 0xFF)); dc.FillSolidRect(rcItem.left, rcItem.top, rcItem.Width() / 2, rcItem.Height() / 2, RGB(235, 235, 235)); dc.FillSolidRect(rcItem.left + rcItem.Width() / 2, rcItem.top + rcItem.Height() / 2, rcItem.Width() - (rcItem.Width() / 2), rcItem.Height() - (rcItem.Height() / 2), RGB(235, 235, 235)); } if (!m_bSelected) { dc.Draw3dRect(rc, GetXtremeColor(COLOR_3DDKSHADOW), GetXtremeColor(COLOR_3DDKSHADOW)); } else { dc.Draw3dRect(rc, 0, 0); rc.DeflateRect(1, 1); dc.Draw3dRect(rc, RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)); rc.DeflateRect(1, 1); dc.Draw3dRect(rc, 0, 0); } } void CXTPImageEditorPicker::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) { NMHDR mHDR; mHDR.hwndFrom = m_hWnd; mHDR.code = NM_CLICK; mHDR.idFrom = GetDlgCtrlID(); GetParent()->SendMessage(WM_NOTIFY, (WPARAM)mHDR.idFrom, (LPARAM)&mHDR); } ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorPreview CXTPImageEditorPreview::CXTPImageEditorPreview() { m_pParentWnd = 0; } void CXTPImageEditorPreview::Init(UINT nID, CXTPImageEditorDlg* pParentWnd) { m_pParentWnd = pParentWnd; SubclassDlgItem(nID, pParentWnd); m_szPicture = pParentWnd->m_szPicture; ModifyStyleEx(WS_EX_STATICEDGE, 0); } BEGIN_MESSAGE_MAP(CXTPImageEditorPreview, CStatic) //{{AFX_MSG_MAP(CXTPImageEditorPreview) ON_WM_PAINT() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorPreview message handlers void CXTPImageEditorPreview::OnPaint() { CPaintDC dcPaint(this); // device context for painting CXTPClientRect rc(this); CXTPBufferDC dc(dcPaint, rc); dc.FillSolidRect(rc, GetXtremeColor(COLOR_3DFACE)); CRect rcButton (10, (rc.Height() - m_szPicture.cy) / 2, 10 + m_szPicture.cx, (rc.Height() - m_szPicture.cy) / 2 + m_szPicture.cy); CRect rcFrame(rcButton); rcFrame.InflateRect(3, 3); dc.Draw3dRect(rcFrame, RGB(0xFF, 0xFF, 0xFF), GetXtremeColor(COLOR_3DSHADOW)); rcFrame.InflateRect(1, 1); dc.Draw3dRect(rcFrame, GetXtremeColor(COLOR_3DFACE), GetXtremeColor(COLOR_3DDKSHADOW)); ASSERT(m_pParentWnd); if (!m_pParentWnd) return; CXTPImageEditorPicture::CAlphaBitmap* pBitmap = m_pParentWnd->m_wndPicture.m_pPictureBitmap; if (pBitmap) { if (pBitmap->m_bAlpha) { HBITMAP hBitmap = CXTPImageManagerIcon::PreMultiplyAlphaBitmap((HBITMAP)pBitmap->GetSafeHandle()); if (hBitmap) { CXTPImageManagerIcon::DrawAlphaBitmap(&dc, hBitmap, rcButton.TopLeft(), m_szPicture); DeleteObject(hBitmap); } } else { CXTPImageEditorPicture::CAlphaBitmap bmpClient; CXTPImageEditorPicture::CopyBitmap(&bmpClient, pBitmap, m_szPicture, 0, XTPCOLOR_ERASE, GetXtremeColor(COLOR_3DFACE), &dc); dc.DrawState(rcButton.TopLeft(), m_szPicture, &bmpClient, DSS_NORMAL, (CBrush*)NULL); } } } ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorDlg dialog CXTPImageEditorDlg::CXTPImageEditorDlg(CWnd* pParent /*= NULL*/, BOOL bCommandBarsEditor) : m_bCommandBarsEditor(bCommandBarsEditor) { InitModalIndirect(XTPResourceManager()->LoadDialogTemplate(XTP_IDD_IMAGEEDITOR_DIALOG), pParent); m_toolSelected = xtpToolPencil; m_pSelected = NULL; m_szPicture = CSize(16, 16); m_toolPrevious = XTPImageEditorTools(-1); } void CXTPImageEditorDlg::GetIcon(CXTPImageManagerIconHandle* pHandle) { ASSERT(pHandle); if (!pHandle) return; if (m_wndPicture.m_pPictureBitmap) { if (m_wndPicture.m_pPictureBitmap->m_bAlpha) { pHandle->CopyHandle((HBITMAP)m_wndPicture.m_pPictureBitmap->GetSafeHandle()); } else { CImageList imgList; imgList.Create(m_szPicture.cx, m_szPicture.cy, ILC_COLOR24 | ILC_MASK, 0, 1); imgList.Add(m_wndPicture.m_pPictureBitmap, XTPCOLOR_ERASE); if (imgList.GetImageCount() != 1) return; *pHandle = imgList.ExtractIcon(0); } } } void CXTPImageEditorDlg::SetIconSize(CSize szIcon) { m_szPicture = szIcon; } void CXTPImageEditorDlg::SetIcon(CXTPImageManagerIconHandle& icon) { if (icon.IsEmpty()) return; ASSERT(m_wndPicture.m_pPictureBitmap == NULL); m_szPicture = icon.GetExtent(); CXTPImageManagerIconHandle iconHandle; iconHandle.CopyHandle(icon); if (iconHandle.IsAlpha()) { iconHandle.PreMultiply(); CXTPImageEditorPicture::CAlphaBitmap* pBitmap = new CXTPImageEditorPicture::CAlphaBitmap(TRUE); LPBYTE lpBits; pBitmap->Attach(CXTPImageManagerIcon::CopyAlphaBitmap(iconHandle.GetBitmap(), &lpBits)); FixAlphaLayer(lpBits, m_szPicture.cx * m_szPicture.cy); m_wndPicture.m_pPictureBitmap = pBitmap; } else { CXTPImageEditorPicture::CAlphaBitmap* pBitmap = new CXTPImageEditorPicture::CAlphaBitmap(); CDC dc; dc.CreateCompatibleDC(NULL); pBitmap->CreateEditorBitmap(m_szPicture.cx, m_szPicture.cy); CBitmap* pOldBitmap = dc.SelectObject(pBitmap); dc.FillSolidRect(0, 0, m_szPicture.cx, m_szPicture.cy, XTPCOLOR_ERASE); dc.DrawState(0, CSize(0, 0), iconHandle.GetIcon(), DSS_NORMAL, (CBrush*)NULL); dc.SelectObject(pOldBitmap); m_wndPicture.m_pPictureBitmap = pBitmap; } } void CXTPImageEditorDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CXTPImageEditorDlg) DDX_Control(pDX, XTP_IDC_STATIC_TOOLS, m_gboxTools); DDX_Control(pDX, XTP_IDC_STATIC_MOVE, m_gboxMove); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CXTPImageEditorDlg, CDialog) //{{AFX_MSG_MAP(CXTPImageEditorDlg) ON_MESSAGE(WM_KICKIDLE, OnKickIdle) ON_WM_DESTROY() ON_NOTIFY(NM_CLICK, XTP_IDC_CLR_PICKER, OnPickerClick) ON_NOTIFY_RANGE(NM_CLICK, XTP_IDS_CLR_BLACK, XTP_IDS_CLR_FUCHSIA, OnSelectorClick) ON_NOTIFY(NM_CLICK, XTP_IDC_CLR_ERASE, OnEraseClick) ON_UPDATE_COMMAND_UI_RANGE(XTP_ID_BUTTON_PENCIL, XTP_ID_BUTTON_CIRCLE, OnUpdateButtonTool) ON_COMMAND_RANGE(XTP_ID_BUTTON_PENCIL, XTP_ID_BUTTON_CIRCLE, OnButtonTool) ON_UPDATE_COMMAND_UI(XTP_ID_BUTTON_UNDO, OnUpdateButtonUndo) ON_COMMAND(XTP_ID_BUTTON_UNDO, OnButtonUndo) ON_UPDATE_COMMAND_UI(XTP_ID_BUTTON_REDO, OnUpdateButtonRedo) ON_COMMAND(XTP_ID_BUTTON_REDO, OnButtonRedo) ON_COMMAND(XTP_ID_BUTTON_CLEAR, OnButtonClear) ON_COMMAND(XTP_ID_BUTTON_COPY, OnButtonCopy) ON_COMMAND(XTP_ID_BUTTON_PASTE, OnButtonPaste) ON_COMMAND(XTP_ID_BUTTON_OPEN, OnButtonOpen) ON_COMMAND_RANGE(XTP_IDC_BUTTON_LEFT, XTP_IDC_BUTTON_RIGHT, OnMoveButton) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPImageEditorDlg message handlers BOOL CXTPImageEditorDlg::OnInitDialog() { UINT nButtons[] = { XTP_ID_BUTTON_PENCIL, XTP_ID_BUTTON_FILL, XTP_ID_BUTTON_UNDO, XTP_ID_BUTTON_REDO, XTP_ID_BUTTON_GETCOLOR, XTP_ID_BUTTON_LINE, XTP_ID_BUTTON_COPY, XTP_ID_BUTTON_PASTE, XTP_ID_BUTTON_RECTANGLE, XTP_ID_BUTTON_CIRCLE, XTP_ID_BUTTON_CLEAR, XTP_ID_BUTTON_OPEN, XTP_IDC_BUTTON_LEFT, XTP_IDC_BUTTON_DOWN, XTP_IDC_BUTTON_UP, XTP_IDC_BUTTON_RIGHT }; UINT* nButtonsTools = nButtons; UINT* nButtonsMove = nButtons + 12; const struct { COLORREF clr; UINT nID; POINT ptOffset; } colors[] = { RGB(0x00, 0x00, 0x00), XTP_IDS_CLR_BLACK , {0, 0}, RGB(0x80, 0x00, 0x00), XTP_IDS_CLR_DARK_RED , {2, 0}, RGB(0x80, 0x80, 0x00), XTP_IDS_CLR_DARK_YELLOW , {3, 0}, RGB(0x00, 0x00, 0x80), XTP_IDS_CLR_DARK_BLUE , {6, 0}, RGB(0x00, 0x80, 0x00), XTP_IDS_CLR_GREEN , {4, 0}, RGB(0x00, 0x80, 0x80), XTP_IDS_CLR_TEAL , {5, 0}, RGB(0x00, 0x00, 0xFF), XTP_IDS_CLR_BLUE , {6, 1}, RGB(0x80, 0x80, 0x80), XTP_IDS_CLR_GRAY50 , {1, 0}, RGB(0xFF, 0x00, 0x00), XTP_IDS_CLR_RED , {2, 1}, RGB(0x80, 0x00, 0x80), XTP_IDS_CLR_VIOLET , {7, 0}, RGB(0xFF, 0x00, 0xFF), XTP_IDS_CLR_PINK , {7, 1}, RGB(0xFF, 0xFF, 0x00), XTP_IDS_CLR_YELLOW , {3, 1}, RGB(0x00, 0xFF, 0x00), XTP_IDS_CLR_BRIGHT_GREEN , {4, 1}, RGB(0x00, 0xFF, 0xFF), XTP_IDS_CLR_TURQUOISE , {5, 1}, RGB(0xC0, 0xC0, 0xC0), XTP_IDS_CLR_GRAY25 , {1, 1}, RGB(0xFF, 0xFF, 0xFF), XTP_IDS_CLR_WHITE , {0, 1} }; CDialog::OnInitDialog(); CXTPResourceManager::CManageState manageState; // Switch to Toolkit resources // Set Icons CXTPImageManager* pImageManager = new CXTPImageManager(); pImageManager->InternalAddRef(); pImageManager->SetIcons(XTP_IDB_TOOLBAR_TOOLS, nButtons, 12 + 4, CSize(0, 0)); CXTPPaintManager* pPaintManager = CXTPPaintManager::CreateTheme(xtpThemeOfficeXP); pPaintManager->InternalAddRef(); pPaintManager->GetIconsInfo()->bUseFadedIcons = FALSE; pPaintManager->GetIconsInfo()->bIconsWithShadow = FALSE; pPaintManager->m_bFlatToolBar = TRUE; CRect rcTools; m_gboxTools.GetWindowRect(&rcTools); ScreenToClient(rcTools); m_wndToolbarTools.SetPaintManager(pPaintManager); m_wndToolbarTools.SetImageManager(pImageManager); m_wndToolbarTools.CreateToolBar(WS_CHILD | WS_VISIBLE | CBRS_TOOLTIPS, this); m_wndToolbarTools.SetButtons(nButtonsTools, 12); CSize sz = m_wndToolbarTools.CalcDockingLayout(23 * 4 + 4, LM_HORZDOCK | LM_HORZ | LM_COMMIT); m_wndToolbarTools.SetWindowPos(&CWnd::wndTop, rcTools.left - 7, rcTools.top - 4, sz.cx, sz.cy, 0); CRect rcMove; m_gboxMove.GetWindowRect(&rcMove); ScreenToClient(rcMove); m_wndToolbarMove.SetPaintManager(pPaintManager); m_wndToolbarMove.SetImageManager(pImageManager); m_wndToolbarMove.CreateToolBar(WS_CHILD | WS_VISIBLE | CBRS_TOOLTIPS, this); m_wndToolbarMove.SetButtons(nButtonsMove, 4); sz = m_wndToolbarMove.CalcDockingLayout(23 * 4 + 4, LM_HORZDOCK | LM_HORZ | LM_COMMIT); m_wndToolbarMove.SetWindowPos(&CWnd::wndTop, rcMove.left - 7, rcMove.top - 4, sz.cx, sz.cy, 0); CRect rcColors; GetDlgItem(XTP_IDC_STATIC_COLORS)->GetWindowRect(&rcColors); ScreenToClient(rcColors); for (int i = 0; i < _countof(colors); i++) { CRect rcItem(CPoint(rcColors.left, rcColors.top - 4), CSize(11, 11)); rcItem.OffsetRect(colors[i].ptOffset.x * 13 , colors[i].ptOffset.y * 13); m_wndSelector[i].Create(NULL, WS_CHILD | WS_VISIBLE | SS_NOTIFY, rcItem, this, colors[i].nID); m_wndSelector[i].SetColor(colors[i].clr); } SetSelected(&m_wndSelector[0]); m_wndSelectorErase.SubclassDlgItem(XTP_IDC_CLR_ERASE, this); m_wndSelectorErase.SetColor(XTPCOLOR_ERASE); m_wndPicker.SubclassDlgItem(XTP_IDC_CLR_PICKER, this); m_wndPicture.Init(XTP_IDC_STATIC_PICTURE, this); m_wndPreview.Init(XTP_IDC_STATIC_PREVIEW, this); if (m_bCommandBarsEditor) { XTPMouseManager()->AddTrustedWindow(m_hWnd); } return TRUE; // return TRUE unless you set the focus to a control } void CXTPImageEditorDlg::OnDestroy() { if (m_bCommandBarsEditor) { XTPMouseManager()->RemoveTrustedWindow(m_hWnd); } CDialog::OnDestroy(); } LRESULT CXTPImageEditorDlg::OnKickIdle(WPARAM, LPARAM) { SendMessageToDescendants(WM_IDLEUPDATECMDUI); return 0; } void CXTPImageEditorDlg::SetSelected(CXTPImageEditorPicker* pPicker) { if (m_pSelected != NULL) m_pSelected->SetSelected(FALSE); if (pPicker) pPicker->SetSelected(TRUE); m_pSelected = pPicker; } void CXTPImageEditorDlg::OnPickerClick(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) { CColorDialog cd(m_wndPicker.GetColor(), 0, this); if (cd.DoModal()) { m_wndPicker.SetColor(cd.GetColor()); SetSelected(&m_wndPicker); } } void CXTPImageEditorDlg::OnEraseClick(NMHDR* pNMHDR, LRESULT* /*pResult*/) { CXTPImageEditorPicker* pWnd = DYNAMIC_DOWNCAST(CXTPImageEditorPicker, CWnd::FromHandlePermanent(pNMHDR->hwndFrom)); ASSERT(pWnd); SetSelected(pWnd); } void CXTPImageEditorDlg::OnSelectorClick(UINT /*id*/, NMHDR* pNMHDR, LRESULT* /*pResult*/) { CXTPImageEditorPicker* pWnd = DYNAMIC_DOWNCAST(CXTPImageEditorPicker, CWnd::FromHandlePermanent(pNMHDR->hwndFrom)); ASSERT(pWnd); SetSelected(pWnd); } void CXTPImageEditorDlg::OnUpdateButtonTool(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_toolSelected == (int)pCmdUI->m_nID - XTP_ID_BUTTON_PENCIL); } void CXTPImageEditorDlg::OnButtonTool(UINT nID) { m_toolPrevious = m_toolSelected == xtpToolGetColor ? m_toolPrevious : m_toolSelected; m_toolSelected = (XTPImageEditorTools)(nID - XTP_ID_BUTTON_PENCIL); } void CXTPImageEditorDlg::OnPictureChanged() { m_wndPreview.Invalidate(FALSE); } void CXTPImageEditorDlg::OnUpdateButtonUndo(CCmdUI* pCmdUI) { pCmdUI->Enable(!m_wndPicture.m_lstUndo.IsEmpty()); } void CXTPImageEditorDlg::OnButtonUndo() { m_wndPicture.Undo(); } void CXTPImageEditorDlg::OnUpdateButtonRedo(CCmdUI* pCmdUI) { pCmdUI->Enable(!m_wndPicture.m_lstRedo.IsEmpty()); } void CXTPImageEditorDlg::OnButtonRedo() { m_wndPicture.Redo(); } void CXTPImageEditorDlg::OnButtonClear() { m_wndPicture.Clear(); } void CXTPImageEditorDlg::OnButtonCopy() { m_wndPicture.Copy(); } void CXTPImageEditorDlg::OnButtonPaste() { m_wndPicture.Paste(); } void CXTPImageEditorDlg::OnButtonOpen() { m_wndPicture.Load(); } void CXTPImageEditorDlg::OnMoveButton(UINT nID) { m_wndPicture.MovePicture( nID == XTP_IDC_BUTTON_LEFT ? CPoint(-1, 0) : nID == XTP_IDC_BUTTON_RIGHT ? CPoint(+1, 0) : nID == XTP_IDC_BUTTON_UP ? CPoint(0, -1) : CPoint(0, +1)); } BOOL CXTPImageEditorDlg::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult) { ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW); // need to handle both ANSI and UNICODE versions of the message TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR; TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR; TCHAR szFullText[256]; CString strTipText; UINT nID = (UINT)pNMHDR->idFrom; if (nID != 0) // will be zero on a separator { // don't handle the message if no string resource found if (AfxLoadString(nID, szFullText) == 0) return FALSE; // this is the command id, not the button index AfxExtractSubString(strTipText, szFullText, 1, '\n'); } #ifndef _UNICODE if (pNMHDR->code == TTN_NEEDTEXTA) lstrcpyn(pTTTA->szText, strTipText, _countof(pTTTA->szText)); else _mbstowcsz(pTTTW->szText, strTipText, _countof(pTTTW->szText)); #else if (pNMHDR->code == TTN_NEEDTEXTA) _wcstombsz(pTTTA->szText, strTipText, _countof(pTTTA->szText)); else lstrcpyn(pTTTW->szText, strTipText, _countof(pTTTW->szText)); #endif *pResult = 0; // bring the tooltip window above other popup windows ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOOWNERZORDER); return TRUE; // message was handled }