/** * @file XTPImageEditor.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "CommandBars/Resource.h" #include "Common/Resource.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPGdiObjects.h" #include "Common/XTPVC80Helpers.h" #include "Common/XTPResourceManager.h" #include "Common/XTPImageManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPColorManager.h" #include "Common/XTPHookManager.h" #include "CommandBars/XTPCommandBarsDefines.h" #include "CommandBars/XTPPaintManager.h" #include "CommandBars/XTPCommandBar.h" #include "CommandBars/XTPToolBar.h" #include "CommandBars/XTPImageEditor.h" #include "CommandBars/XTPMouseManager.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.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 + XTP_DPI_X(1), sz.cy + XTP_DPI_Y(1), SWP_NOMOVE); m_dcPicture.CreateCompatibleDC(NULL); } XTPImageEditorTools CXTPImageEditorPicture::GetSelectedTool() { _ASSERTE(m_pParentWnd); if (!m_pParentWnd) return xtpToolPencil; return m_pParentWnd->m_toolSelected; } COLORREF CXTPImageEditorPicture::GetSelectedColor() { _ASSERTE(m_pParentWnd); if (m_pParentWnd && m_pParentWnd->m_pSelected) { return m_pParentWnd->m_pSelected->GetColor(); } return 0; } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" 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() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" ///////////////////////////////////////////////////////////////////////////// // 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); COLORREF* pBits = NULL; PBITMAPINFO pbmi = NULL; 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)]; DWORD nAlpha = (clr & 0xFF000000) >> 24; DWORD nColor = XTPToDWORD((((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) { _ASSERTE(m_szItem.cx > 0 && m_szItem.cy > 0); return CPoint(pt.x / m_szItem.cx, pt.y / m_szItem.cy); } void AFX_CDECL 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) { _ASSERTE(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: _ASSERTE(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); XTP_BEGIN_PARALLEL_FOR(int, i, 0, XTPToIntChecked(nSize) / 4, 1) { if (pDestBits[i] != pSrcBits[i]) { if (pDestBits[i] != XTPCOLOR_ERASE) pFixedBits[i] |= 0xFF000000; } } XTP_END_PARALLEL_FOR 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); } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPImageEditorPicker, CStatic) //{{AFX_MSG_MAP(CXTPImageEditorPicker) ON_WM_PAINT() ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" ///////////////////////////////////////////////////////////////////////////// // 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 = XTPToUIntPtr(GetDlgCtrlID()); GetParent()->SendMessage(WM_NOTIFY, XTPToWPARAM(mHDR.idFrom), XTPToLPARAM(&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(XTP_DPI_X(10), (rc.Height() - m_szPicture.cy) / 2, XTP_DPI_X(10) + m_szPicture.cx, (rc.Height() - m_szPicture.cy) / 2 + m_szPicture.cy); CRect rcFrame(rcButton); rcFrame.InflateRect(XTP_DPI_X(3), XTP_DPI_Y(3)); dc.Draw3dRect(rcFrame, RGB(0xFF, 0xFF, 0xFF), GetXtremeColor(COLOR_3DSHADOW)); rcFrame.InflateRect(1, 1); dc.Draw3dRect(rcFrame, GetXtremeColor(COLOR_3DFACE), GetXtremeColor(COLOR_3DDKSHADOW)); _ASSERTE(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::CDlgToolBar::CDlgToolBar() { SetIconSize(XTP_DPI(CSize(16, 16))); SetButtonSize(XTP_DPI(CSize(23, 23))); } 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 = XTP_DPI(CSize(16, 16)); m_toolPrevious = XTPImageEditorTools(-1); } void CXTPImageEditorDlg::GetIcon(CXTPImageManagerIconHandle* pHandle) { _ASSERTE(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->Attach(imgList.ExtractIcon(0), FALSE); } } } void CXTPImageEditorDlg::SetIconSize(CSize szIcon) { m_szPicture = szIcon; } void CXTPImageEditorDlg::SetIcon(CXTPImageManagerIconHandle& icon) { if (icon.IsEmpty()) return; _ASSERTE(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, XTPToUIntChecked(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 } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" 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() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" ///////////////////////////////////////////////////////////////////////////// // 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(XTP_DPI_X(23) * 4 + XTP_DPI_X(7), LM_HORZDOCK | LM_HORZ | LM_COMMIT); m_wndToolbarTools.SetWindowPos(&CWnd::wndTop, rcTools.left - XTP_DPI_X(7), rcTools.top - XTP_DPI_Y(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(XTP_DPI_X(23) * 4 + XTP_DPI_X(7), LM_HORZDOCK | LM_HORZ | LM_COMMIT); m_wndToolbarMove.SetWindowPos(&CWnd::wndTop, rcMove.left - XTP_DPI_X(7), rcMove.top - XTP_DPI_Y(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 - XTP_DPI_Y(4)), XTP_DPI(CSize(11, 11))); rcItem.OffsetRect(colors[i].ptOffset.x * XTP_DPI_X(13), colors[i].ptOffset.y * XTP_DPI_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)); _ASSERTE(pWnd); SetSelected(pWnd); } void CXTPImageEditorDlg::OnSelectorClick(UINT /*id*/, NMHDR* pNMHDR, LRESULT* /*pResult*/) { CXTPImageEditorPicker* pWnd = DYNAMIC_DOWNCAST(CXTPImageEditorPicker, CWnd::FromHandlePermanent(pNMHDR->hwndFrom)); _ASSERTE(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) { _ASSERTE(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 }