mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +00:00
[MSPAINT] Establish Undo/Redo management (#5347)
- Painting the canvas is done by overlaying the multiple layers. - Drawing each overlay is implemented as polymorphism of OOP. - Refine the Undo/Redo mechanism. - Some adjustments. CORE-17969
This commit is contained in:
parent
b7071f67a8
commit
e8c7e30030
25 changed files with 721 additions and 504 deletions
|
@ -17,15 +17,17 @@ CCanvasWindow::CCanvasWindow()
|
|||
, m_hitSelection(HIT_NONE)
|
||||
, m_whereHit(HIT_NONE)
|
||||
, m_ptOrig { -1, -1 }
|
||||
, m_hbmCached(NULL)
|
||||
{
|
||||
m_ahbmCached[0] = m_ahbmCached[1] = NULL;
|
||||
::SetRectEmpty(&m_rcNew);
|
||||
}
|
||||
|
||||
CCanvasWindow::~CCanvasWindow()
|
||||
{
|
||||
if (m_hbmCached)
|
||||
::DeleteObject(m_hbmCached);
|
||||
if (m_ahbmCached[0])
|
||||
::DeleteObject(m_ahbmCached[0]);
|
||||
if (m_ahbmCached[1])
|
||||
::DeleteObject(m_ahbmCached[1]);
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::drawZoomFrame(INT mouseX, INT mouseY)
|
||||
|
@ -101,78 +103,80 @@ CANVAS_HITTEST CCanvasWindow::CanvasHitTest(POINT pt)
|
|||
VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
|
||||
{
|
||||
// We use a memory bitmap to reduce flickering
|
||||
HDC hdcMem = ::CreateCompatibleDC(hDC);
|
||||
m_hbmCached = CachedBufferDIB(m_hbmCached, rcClient.right, rcClient.bottom);
|
||||
HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmCached);
|
||||
HDC hdcMem0 = ::CreateCompatibleDC(hDC);
|
||||
m_ahbmCached[0] = CachedBufferDIB(m_ahbmCached[0], rcClient.right, rcClient.bottom);
|
||||
HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, m_ahbmCached[0]);
|
||||
|
||||
// Fill the background
|
||||
::FillRect(hdcMem, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1));
|
||||
// Fill the background on hdcMem0
|
||||
::FillRect(hdcMem0, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1));
|
||||
|
||||
// Draw the sizeboxes if necessary
|
||||
RECT rcBase = GetBaseRect();
|
||||
if (!selectionModel.m_bShow)
|
||||
drawSizeBoxes(hdcMem, &rcBase, FALSE, &rcPaint);
|
||||
drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcPaint);
|
||||
|
||||
// Draw the image
|
||||
// Calculate image size
|
||||
CRect rcImage;
|
||||
GetImageRect(rcImage);
|
||||
ImageToCanvas(rcImage);
|
||||
SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
|
||||
StretchBlt(hdcMem, rcImage.left, rcImage.top, rcImage.Width(), rcImage.Height(),
|
||||
imageModel.GetDC(), 0, 0, sizeImage.cx, sizeImage.cy, SRCCOPY);
|
||||
|
||||
// Draw the grid
|
||||
if (showGrid && toolsModel.GetZoom() >= 4000)
|
||||
// hdcMem1 <-- imageModel
|
||||
HDC hdcMem1 = ::CreateCompatibleDC(hDC);
|
||||
m_ahbmCached[1] = CachedBufferDIB(m_ahbmCached[1], sizeImage.cx, sizeImage.cy);
|
||||
HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, m_ahbmCached[1]);
|
||||
BitBlt(hdcMem1, 0, 0, sizeImage.cx, sizeImage.cy, imageModel.GetDC(), 0, 0, SRCCOPY);
|
||||
|
||||
// Draw overlay #1 on hdcMem1
|
||||
toolsModel.OnDrawOverlayOnImage(hdcMem1);
|
||||
|
||||
// Transfer the bits with stretch (hdcMem0 <-- hdcMem1)
|
||||
ImageToCanvas(rcImage);
|
||||
::StretchBlt(hdcMem0, rcImage.left, rcImage.top, rcImage.Width(), rcImage.Height(),
|
||||
hdcMem1, 0, 0, sizeImage.cx, sizeImage.cy, SRCCOPY);
|
||||
|
||||
// Clean up hdcMem1
|
||||
::SelectObject(hdcMem1, hbm1Old);
|
||||
::DeleteDC(hdcMem1);
|
||||
|
||||
// Draw the grid on hdcMem0
|
||||
if (g_showGrid && toolsModel.GetZoom() >= 4000)
|
||||
{
|
||||
HPEN oldPen = (HPEN) SelectObject(hdcMem, CreatePen(PS_SOLID, 1, RGB(160, 160, 160)));
|
||||
HPEN oldPen = (HPEN) ::SelectObject(hdcMem0, ::CreatePen(PS_SOLID, 1, RGB(160, 160, 160)));
|
||||
for (INT counter = 0; counter < sizeImage.cy; counter++)
|
||||
{
|
||||
POINT pt0 = { 0, counter }, pt1 = { sizeImage.cx, counter };
|
||||
ImageToCanvas(pt0);
|
||||
ImageToCanvas(pt1);
|
||||
::MoveToEx(hdcMem, pt0.x, pt0.y, NULL);
|
||||
::LineTo(hdcMem, pt1.x, pt1.y);
|
||||
::MoveToEx(hdcMem0, pt0.x, pt0.y, NULL);
|
||||
::LineTo(hdcMem0, pt1.x, pt1.y);
|
||||
}
|
||||
for (INT counter = 0; counter < sizeImage.cx; counter++)
|
||||
{
|
||||
POINT pt0 = { counter, 0 }, pt1 = { counter, sizeImage.cy };
|
||||
ImageToCanvas(pt0);
|
||||
ImageToCanvas(pt1);
|
||||
::MoveToEx(hdcMem, pt0.x, pt0.y, NULL);
|
||||
::LineTo(hdcMem, pt1.x, pt1.y);
|
||||
::MoveToEx(hdcMem0, pt0.x, pt0.y, NULL);
|
||||
::LineTo(hdcMem0, pt1.x, pt1.y);
|
||||
}
|
||||
::DeleteObject(::SelectObject(hdcMem, oldPen));
|
||||
::DeleteObject(::SelectObject(hdcMem0, oldPen));
|
||||
}
|
||||
|
||||
// Draw selection
|
||||
if (selectionModel.m_bShow)
|
||||
{
|
||||
RECT rcSelection = selectionModel.m_rc;
|
||||
ImageToCanvas(rcSelection);
|
||||
// Draw overlay #2 on hdcMem0
|
||||
toolsModel.OnDrawOverlayOnCanvas(hdcMem0);
|
||||
|
||||
::InflateRect(&rcSelection, GRIP_SIZE, GRIP_SIZE);
|
||||
drawSizeBoxes(hdcMem, &rcSelection, TRUE, &rcPaint);
|
||||
::InflateRect(&rcSelection, -GRIP_SIZE, -GRIP_SIZE);
|
||||
|
||||
INT iSaveDC = ::SaveDC(hdcMem);
|
||||
::IntersectClipRect(hdcMem, rcImage.left, rcImage.top, rcImage.right, rcImage.bottom);
|
||||
selectionModel.DrawSelection(hdcMem, &rcSelection, paletteModel.GetBgColor(),
|
||||
toolsModel.IsBackgroundTransparent());
|
||||
::RestoreDC(hdcMem, iSaveDC);
|
||||
}
|
||||
|
||||
// Draw new frame if any
|
||||
// Draw new frame on hdcMem0 if any
|
||||
if (m_whereHit != HIT_NONE && !::IsRectEmpty(&m_rcNew))
|
||||
DrawXorRect(hdcMem, &m_rcNew);
|
||||
DrawXorRect(hdcMem0, &m_rcNew);
|
||||
|
||||
// Transfer the bits
|
||||
// Transfer the bits (hDC <-- hdcMem0)
|
||||
::BitBlt(hDC,
|
||||
rcPaint.left, rcPaint.top,
|
||||
rcPaint.right - rcPaint.left, rcPaint.bottom - rcPaint.top,
|
||||
hdcMem, rcPaint.left, rcPaint.top, SRCCOPY);
|
||||
hdcMem0, rcPaint.left, rcPaint.top, SRCCOPY);
|
||||
|
||||
::SelectObject(hdcMem, hbmOld);
|
||||
::DeleteDC(hdcMem);
|
||||
// Clean up hdcMem0
|
||||
::SelectObject(hdcMem0, hbm0Old);
|
||||
::DeleteDC(hdcMem0);
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::Update(HWND hwndFrom)
|
||||
|
@ -383,15 +387,15 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
|||
{
|
||||
CString strCoord;
|
||||
strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
|
||||
SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
|
||||
::SendMessage(g_hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_drawing)
|
||||
{
|
||||
// values displayed in statusbar
|
||||
LONG xRel = pt.x - start.x;
|
||||
LONG yRel = pt.y - start.y;
|
||||
LONG xRel = pt.x - g_ptStart.x;
|
||||
LONG yRel = pt.y - g_ptStart.y;
|
||||
|
||||
switch (toolsModel.GetActiveTool())
|
||||
{
|
||||
|
@ -400,13 +404,13 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
|||
case TOOL_RECTSEL:
|
||||
case TOOL_TEXT:
|
||||
if (xRel < 0)
|
||||
xRel = (pt.x < 0) ? -start.x : xRel;
|
||||
xRel = (pt.x < 0) ? -g_ptStart.x : xRel;
|
||||
else if (pt.x > imageModel.GetWidth())
|
||||
xRel = imageModel.GetWidth() - start.x;
|
||||
xRel = imageModel.GetWidth() - g_ptStart.x;
|
||||
if (yRel < 0)
|
||||
yRel = (pt.y < 0) ? -start.y : yRel;
|
||||
yRel = (pt.y < 0) ? -g_ptStart.y : yRel;
|
||||
else if (pt.y > imageModel.GetHeight())
|
||||
yRel = imageModel.GetHeight() - start.y;
|
||||
yRel = imageModel.GetHeight() - g_ptStart.y;
|
||||
break;
|
||||
|
||||
// while drawing, update cursor coordinates only for tools 3, 7, 8, 9, 14
|
||||
|
@ -418,7 +422,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
|||
{
|
||||
CString strCoord;
|
||||
strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
|
||||
SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
|
||||
::SendMessage(g_hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -444,7 +448,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
|||
if ((toolsModel.GetActiveTool() >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
|
||||
yRel = xRel;
|
||||
strSize.Format(_T("%ld x %ld"), xRel, yRel);
|
||||
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
|
||||
::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,7 +462,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
|||
if ((toolsModel.GetActiveTool() >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
|
||||
yRel = xRel;
|
||||
strSize.Format(_T("%ld x %ld"), xRel, yRel);
|
||||
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
|
||||
::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -514,7 +518,7 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
|||
// Display new size
|
||||
CString strSize;
|
||||
strSize.Format(_T("%d x %d"), cxImage, cyImage);
|
||||
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
|
||||
::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
|
||||
|
||||
CRect rc = { 0, 0, cxImage, cyImage };
|
||||
switch (m_whereHit)
|
||||
|
@ -556,7 +560,7 @@ LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam,
|
|||
m_drawing = FALSE;
|
||||
toolsModel.OnButtonUp(bLeftButton, pt.x, pt.y);
|
||||
Invalidate(FALSE);
|
||||
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
|
||||
::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM)_T(""));
|
||||
return 0;
|
||||
}
|
||||
else if (m_hitSelection != HIT_NONE && bLeftButton)
|
||||
|
@ -603,7 +607,7 @@ LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam,
|
|||
}
|
||||
::SetRectEmpty(&m_rcNew);
|
||||
|
||||
imageSaved = FALSE;
|
||||
g_imageSaved = FALSE;
|
||||
|
||||
m_whereHit = HIT_NONE;
|
||||
toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
|
||||
|
@ -654,19 +658,19 @@ LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
|
|||
switch (toolsModel.GetActiveTool())
|
||||
{
|
||||
case TOOL_FILL:
|
||||
::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_FILL)));
|
||||
::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_FILL)));
|
||||
break;
|
||||
case TOOL_COLOR:
|
||||
::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_COLOR)));
|
||||
::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_COLOR)));
|
||||
break;
|
||||
case TOOL_ZOOM:
|
||||
::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_ZOOM)));
|
||||
::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_ZOOM)));
|
||||
break;
|
||||
case TOOL_PEN:
|
||||
::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_PEN)));
|
||||
::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_PEN)));
|
||||
break;
|
||||
case TOOL_AIRBRUSH:
|
||||
::SetCursor(::LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_AIRBRUSH)));
|
||||
::SetCursor(::LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDC_AIRBRUSH)));
|
||||
break;
|
||||
default:
|
||||
::SetCursor(::LoadCursor(NULL, IDC_CROSS));
|
||||
|
@ -710,7 +714,7 @@ LRESULT CCanvasWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
|
|||
|
||||
LRESULT CCanvasWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM)_T(""));
|
||||
::SendMessage(g_hStatusBar, SB_SETTEXT, 2, (LPARAM)_T(""));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -800,3 +804,9 @@ LRESULT CCanvasWindow::OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, B
|
|||
SetBkMode((HDC)wParam, TRANSPARENT);
|
||||
return (LRESULT)GetStockObject(NULL_BRUSH);
|
||||
}
|
||||
|
||||
LRESULT CCanvasWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
imageModel.NotifyImageChanged();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode)
|
||||
MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
|
||||
MESSAGE_HANDLER(WM_CTLCOLOREDIT, OnCtlColorEdit)
|
||||
MESSAGE_HANDLER(WM_PALETTEMODELCOLORCHANGED, OnPaletteModelColorChanged)
|
||||
END_MSG_MAP()
|
||||
|
||||
CCanvasWindow();
|
||||
|
@ -55,7 +56,7 @@ protected:
|
|||
CANVAS_HITTEST m_hitSelection;
|
||||
CANVAS_HITTEST m_whereHit;
|
||||
POINT m_ptOrig; // The origin of drag start
|
||||
HBITMAP m_hbmCached; // The cached buffer bitmap
|
||||
HBITMAP m_ahbmCached[2]; // The cached buffer bitmaps
|
||||
CRect m_rcNew;
|
||||
|
||||
CANVAS_HITTEST CanvasHitTest(POINT pt);
|
||||
|
@ -87,6 +88,7 @@ protected:
|
|||
LRESULT OnCancelMode(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
|
||||
LRESULT OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnLRButtonDblClk(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#define WM_TOOLSMODELSETTINGSCHANGED (WM_APP + 1)
|
||||
#define WM_TOOLSMODELZOOMCHANGED (WM_APP + 2)
|
||||
#define WM_PALETTEMODELCOLORCHANGED (WM_APP + 3)
|
||||
#define WM_PALETTEMODELPALETTECHANGED (WM_APP + 4)
|
||||
|
||||
/* this simplifies checking and unchecking menu items */
|
||||
#define CHECKED_IF(a) ((a) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND))
|
||||
|
|
|
@ -83,16 +83,16 @@ LRESULT CAttributesDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam,
|
|||
SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE);
|
||||
SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE);
|
||||
|
||||
if (isAFile)
|
||||
if (g_isAFile)
|
||||
{
|
||||
TCHAR date[100];
|
||||
TCHAR temp[100];
|
||||
GetDateFormat(LOCALE_USER_DEFAULT, 0, &fileTime, NULL, date, _countof(date));
|
||||
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &fileTime, NULL, temp, _countof(temp));
|
||||
GetDateFormat(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, date, _countof(date));
|
||||
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, temp, _countof(temp));
|
||||
_tcscat(date, _T(" "));
|
||||
_tcscat(date, temp);
|
||||
CString strSize;
|
||||
strSize.Format(IDS_FILESIZE, fileSize);
|
||||
strSize.Format(IDS_FILESIZE, g_fileSize);
|
||||
SetDlgItemText(IDD_ATTRIBUTESTEXT6, date);
|
||||
SetDlgItemText(IDD_ATTRIBUTESTEXT7, strSize);
|
||||
}
|
||||
|
@ -240,9 +240,9 @@ LRESULT CStretchSkewDialog::OnOk(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL&
|
|||
CString strrcAngle;
|
||||
BOOL tr1, tr2, tr3, tr4;
|
||||
|
||||
strrcIntNumbers.LoadString(hProgInstance, IDS_INTNUMBERS);
|
||||
strrcPercentage.LoadString(hProgInstance, IDS_PERCENTAGE);
|
||||
strrcAngle.LoadString(hProgInstance, IDS_ANGLE);
|
||||
strrcIntNumbers.LoadString(g_hinstExe, IDS_INTNUMBERS);
|
||||
strrcPercentage.LoadString(g_hinstExe, IDS_PERCENTAGE);
|
||||
strrcAngle.LoadString(g_hinstExe, IDS_ANGLE);
|
||||
|
||||
percentage.x = GetDlgItemInt(IDD_STRETCHSKEWEDITHSTRETCH, &tr1, FALSE);
|
||||
percentage.y = GetDlgItemInt(IDD_STRETCHSKEWEDITVSTRETCH, &tr2, FALSE);
|
||||
|
@ -347,11 +347,11 @@ void CFontsDialog::InitToolbar()
|
|||
SendMessage(hwndToolbar, TB_SETBUTTONWIDTH, 0, MAKELPARAM(20, 20));
|
||||
|
||||
TBADDBITMAP AddBitmap;
|
||||
AddBitmap.hInst = hProgInstance;
|
||||
AddBitmap.hInst = g_hinstExe;
|
||||
AddBitmap.nID = IDB_FONTSTOOLBAR;
|
||||
SendMessage(hwndToolbar, TB_ADDBITMAP, 4, (LPARAM)&AddBitmap);
|
||||
|
||||
HIMAGELIST himl = ImageList_LoadImage(hProgInstance, MAKEINTRESOURCE(IDB_FONTSTOOLBAR),
|
||||
HIMAGELIST himl = ImageList_LoadImage(g_hinstExe, MAKEINTRESOURCE(IDB_FONTSTOOLBAR),
|
||||
16, 8, RGB(255, 0, 255), IMAGE_BITMAP,
|
||||
LR_CREATEDIBSECTION);
|
||||
SendMessage(hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl);
|
||||
|
@ -511,7 +511,7 @@ LRESULT CFontsDialog::OnNotify(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
if (pnmhdr->code == TTN_NEEDTEXT)
|
||||
{
|
||||
LPTOOLTIPTEXT pToolTip = reinterpret_cast<LPTOOLTIPTEXT>(lParam);
|
||||
pToolTip->hinst = hProgInstance;
|
||||
pToolTip->hinst = g_hinstExe;
|
||||
switch (pnmhdr->idFrom)
|
||||
{
|
||||
case IDM_BOLD: pToolTip->lpszText = MAKEINTRESOURCE(IDS_BOLD); break;
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
#include "precomp.h"
|
||||
#include <math.h>
|
||||
|
||||
INT fileSize = 0;
|
||||
INT g_fileSize = 0;
|
||||
float g_xDpi = 96;
|
||||
float g_yDpi = 96;
|
||||
SYSTEMTIME fileTime;
|
||||
SYSTEMTIME g_fileTime;
|
||||
|
||||
/* FUNCTIONS ********************************************************/
|
||||
|
||||
|
@ -114,15 +114,15 @@ BOOL SaveDIBToFile(HBITMAP hBitmap, LPCTSTR FileName, HDC hDC)
|
|||
// update time and size
|
||||
FILETIME ft;
|
||||
FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft);
|
||||
FileTimeToSystemTime(&ft, &fileTime);
|
||||
fileSize = find.nFileSizeLow;
|
||||
FileTimeToSystemTime(&ft, &g_fileTime);
|
||||
g_fileSize = find.nFileSizeLow;
|
||||
|
||||
// TODO: update hRes and vRes
|
||||
|
||||
registrySettings.SetMostRecentFile(FileName);
|
||||
|
||||
isAFile = TRUE;
|
||||
imageSaved = TRUE;
|
||||
g_isAFile = TRUE;
|
||||
g_imageSaved = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -150,33 +150,33 @@ HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL i
|
|||
g_yDpi = GetDeviceCaps(hScreenDC, LOGPIXELSY);
|
||||
ReleaseDC(NULL, hScreenDC);
|
||||
|
||||
ZeroMemory(&fileTime, sizeof(fileTime));
|
||||
ZeroMemory(&g_fileTime, sizeof(g_fileTime));
|
||||
}
|
||||
|
||||
// update image
|
||||
imageModel.PushImageForUndo(hBitmap);
|
||||
imageModel.ClearHistory();
|
||||
|
||||
// update fileSize
|
||||
fileSize = dwFileSize;
|
||||
// update g_fileSize
|
||||
g_fileSize = dwFileSize;
|
||||
|
||||
// update filepathname
|
||||
// update g_szFileName
|
||||
if (name && name[0])
|
||||
GetFullPathName(name, _countof(filepathname), filepathname, NULL);
|
||||
GetFullPathName(name, _countof(g_szFileName), g_szFileName, NULL);
|
||||
else
|
||||
LoadString(hProgInstance, IDS_DEFAULTFILENAME, filepathname, _countof(filepathname));
|
||||
LoadString(g_hinstExe, IDS_DEFAULTFILENAME, g_szFileName, _countof(g_szFileName));
|
||||
|
||||
// set title
|
||||
CString strTitle;
|
||||
strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname));
|
||||
strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName));
|
||||
mainWindow.SetWindowText(strTitle);
|
||||
|
||||
// update file info and recent
|
||||
isAFile = isFile;
|
||||
if (isAFile)
|
||||
registrySettings.SetMostRecentFile(filepathname);
|
||||
g_isAFile = isFile;
|
||||
if (g_isAFile)
|
||||
registrySettings.SetMostRecentFile(g_szFileName);
|
||||
|
||||
imageSaved = TRUE;
|
||||
g_imageSaved = TRUE;
|
||||
|
||||
return hBitmap;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile)
|
|||
{
|
||||
FILETIME ft;
|
||||
FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft);
|
||||
FileTimeToSystemTime(&ft, &fileTime);
|
||||
FileTimeToSystemTime(&ft, &g_fileTime);
|
||||
return SetBitmapAndInfo(NULL, name, dwFileSize, TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile)
|
|||
{
|
||||
FILETIME ft;
|
||||
FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft);
|
||||
FileTimeToSystemTime(&ft, &fileTime);
|
||||
FileTimeToSystemTime(&ft, &g_fileTime);
|
||||
SetBitmapAndInfo(hBitmap, name, dwFileSize, TRUE);
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r)
|
|||
{
|
||||
for (LONG dx = -r; dx <= r; dx++)
|
||||
{
|
||||
if ((dx * dx + dy * dy <= r * r) && (rand() % 4 == 0))
|
||||
if ((dx * dx + dy * dy <= r * r) && (rand() % r == 0))
|
||||
::SetPixelV(hdc, x + dx, y + dy, color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ HWND CFullscreenWindow::DoCreate()
|
|||
|
||||
LRESULT CFullscreenWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,18 +10,16 @@
|
|||
|
||||
/* VARIABLES declared in main.cpp ***********************************/
|
||||
|
||||
extern BOOL askBeforeEnlarging;
|
||||
extern BOOL g_askBeforeEnlarging;
|
||||
|
||||
extern POINT start;
|
||||
extern POINT last;
|
||||
extern POINT g_ptStart, g_ptEnd;
|
||||
|
||||
extern HINSTANCE hProgInstance;
|
||||
extern HINSTANCE g_hinstExe;
|
||||
|
||||
extern TCHAR filepathname[MAX_LONG_PATH];
|
||||
extern BOOL isAFile;
|
||||
extern BOOL imageSaved;
|
||||
|
||||
extern BOOL showGrid;
|
||||
extern TCHAR g_szFileName[MAX_LONG_PATH];
|
||||
extern BOOL g_isAFile;
|
||||
extern BOOL g_imageSaved;
|
||||
extern BOOL g_showGrid;
|
||||
|
||||
extern CMainWindow mainWindow;
|
||||
|
||||
|
@ -40,11 +38,11 @@ extern ToolsModel toolsModel;
|
|||
extern SelectionModel selectionModel;
|
||||
extern PaletteModel paletteModel;
|
||||
|
||||
extern HWND hStatusBar;
|
||||
extern HWND g_hStatusBar;
|
||||
extern float g_xDpi;
|
||||
extern float g_yDpi;
|
||||
extern INT fileSize;
|
||||
extern SYSTEMTIME fileTime;
|
||||
extern INT g_fileSize;
|
||||
extern SYSTEMTIME g_fileTime;
|
||||
|
||||
extern CFullscreenWindow fullscreenWindow;
|
||||
extern CMiniatureWindow miniature;
|
||||
|
|
|
@ -22,103 +22,103 @@ void ImageModel::NotifyImageChanged()
|
|||
}
|
||||
|
||||
ImageModel::ImageModel()
|
||||
: hDrawingDC(::CreateCompatibleDC(NULL))
|
||||
, currInd(0)
|
||||
, undoSteps(0)
|
||||
, redoSteps(0)
|
||||
: m_hDrawingDC(::CreateCompatibleDC(NULL))
|
||||
, m_currInd(0)
|
||||
, m_undoSteps(0)
|
||||
, m_redoSteps(0)
|
||||
{
|
||||
ZeroMemory(hBms, sizeof(hBms));
|
||||
ZeroMemory(m_hBms, sizeof(m_hBms));
|
||||
|
||||
hBms[0] = CreateDIBWithProperties(1, 1);
|
||||
::SelectObject(hDrawingDC, hBms[0]);
|
||||
m_hBms[0] = CreateColorDIB(1, 1, RGB(255, 255, 255));
|
||||
m_hbmOld = ::SelectObject(m_hDrawingDC, m_hBms[0]);
|
||||
|
||||
imageSaved = TRUE;
|
||||
g_imageSaved = TRUE;
|
||||
}
|
||||
|
||||
ImageModel::~ImageModel()
|
||||
{
|
||||
::DeleteDC(hDrawingDC);
|
||||
::DeleteDC(m_hDrawingDC);
|
||||
|
||||
for (size_t i = 0; i < HISTORYSIZE; ++i)
|
||||
{
|
||||
if (hBms[i])
|
||||
::DeleteObject(hBms[i]);
|
||||
if (m_hBms[i])
|
||||
::DeleteObject(m_hBms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageModel::Undo(BOOL bClearRedo)
|
||||
{
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, undoSteps);
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, m_undoSteps);
|
||||
if (!CanUndo())
|
||||
return;
|
||||
|
||||
selectionModel.m_bShow = FALSE;
|
||||
selectionModel.HideSelection();
|
||||
|
||||
// Select previous item
|
||||
currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE;
|
||||
::SelectObject(hDrawingDC, hBms[currInd]);
|
||||
m_currInd = (m_currInd + HISTORYSIZE - 1) % HISTORYSIZE;
|
||||
::SelectObject(m_hDrawingDC, m_hBms[m_currInd]);
|
||||
|
||||
undoSteps--;
|
||||
m_undoSteps--;
|
||||
if (bClearRedo)
|
||||
redoSteps = 0;
|
||||
else if (redoSteps < HISTORYSIZE - 1)
|
||||
redoSteps++;
|
||||
m_redoSteps = 0;
|
||||
else if (m_redoSteps < HISTORYSIZE - 1)
|
||||
m_redoSteps++;
|
||||
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
||||
void ImageModel::Redo()
|
||||
{
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, redoSteps);
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, m_redoSteps);
|
||||
if (!CanRedo())
|
||||
return;
|
||||
|
||||
selectionModel.m_bShow = FALSE;
|
||||
selectionModel.HideSelection();
|
||||
|
||||
// Select next item
|
||||
currInd = (currInd + 1) % HISTORYSIZE;
|
||||
::SelectObject(hDrawingDC, hBms[currInd]);
|
||||
m_currInd = (m_currInd + 1) % HISTORYSIZE;
|
||||
::SelectObject(m_hDrawingDC, m_hBms[m_currInd]);
|
||||
|
||||
redoSteps--;
|
||||
if (undoSteps < HISTORYSIZE - 1)
|
||||
undoSteps++;
|
||||
m_redoSteps--;
|
||||
if (m_undoSteps < HISTORYSIZE - 1)
|
||||
m_undoSteps++;
|
||||
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
||||
void ImageModel::ResetToPrevious()
|
||||
{
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, currInd);
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
|
||||
|
||||
// Revert current item with previous item
|
||||
::DeleteObject(hBms[currInd]);
|
||||
hBms[currInd] = CopyDIBImage(hBms[(currInd + HISTORYSIZE - 1) % HISTORYSIZE]);
|
||||
::SelectObject(hDrawingDC, hBms[currInd]);
|
||||
::DeleteObject(m_hBms[m_currInd]);
|
||||
m_hBms[m_currInd] = CopyDIBImage(m_hBms[(m_currInd + HISTORYSIZE - 1) % HISTORYSIZE]);
|
||||
::SelectObject(m_hDrawingDC, m_hBms[m_currInd]);
|
||||
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
||||
void ImageModel::ClearHistory()
|
||||
{
|
||||
undoSteps = 0;
|
||||
redoSteps = 0;
|
||||
m_undoSteps = 0;
|
||||
m_redoSteps = 0;
|
||||
}
|
||||
|
||||
void ImageModel::PushImageForUndo(HBITMAP hbm)
|
||||
{
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, currInd);
|
||||
ATLTRACE("%s: %d\n", __FUNCTION__, m_currInd);
|
||||
|
||||
// Go to the next item with an HBITMAP or current item
|
||||
::DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
|
||||
hBms[(currInd + 1) % HISTORYSIZE] = (hbm ? hbm : CopyDIBImage(hBms[currInd]));
|
||||
currInd = (currInd + 1) % HISTORYSIZE;
|
||||
::SelectObject(hDrawingDC, hBms[currInd]);
|
||||
::DeleteObject(m_hBms[(m_currInd + 1) % HISTORYSIZE]);
|
||||
m_hBms[(m_currInd + 1) % HISTORYSIZE] = (hbm ? hbm : CopyDIBImage(m_hBms[m_currInd]));
|
||||
m_currInd = (m_currInd + 1) % HISTORYSIZE;
|
||||
::SelectObject(m_hDrawingDC, m_hBms[m_currInd]);
|
||||
|
||||
if (undoSteps < HISTORYSIZE - 1)
|
||||
undoSteps++;
|
||||
redoSteps = 0;
|
||||
if (m_undoSteps < HISTORYSIZE - 1)
|
||||
m_undoSteps++;
|
||||
m_redoSteps = 0;
|
||||
|
||||
imageSaved = FALSE;
|
||||
g_imageSaved = FALSE;
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
|
|||
return;
|
||||
|
||||
// Select the HBITMAP by memory DC
|
||||
HDC hdcMem = ::CreateCompatibleDC(hDrawingDC);
|
||||
HDC hdcMem = ::CreateCompatibleDC(m_hDrawingDC);
|
||||
HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmCropped);
|
||||
|
||||
// Fill background of the HBITMAP
|
||||
|
@ -146,7 +146,7 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
|
|||
::DeleteObject(hbrBack);
|
||||
|
||||
// Copy the old content
|
||||
::BitBlt(hdcMem, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), hDrawingDC, 0, 0, SRCCOPY);
|
||||
::BitBlt(hdcMem, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), m_hDrawingDC, 0, 0, SRCCOPY);
|
||||
|
||||
// Clean up
|
||||
::SelectObject(hdcMem, hbmOld);
|
||||
|
@ -160,12 +160,12 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
|
|||
|
||||
void ImageModel::SaveImage(LPCTSTR lpFileName)
|
||||
{
|
||||
SaveDIBToFile(hBms[currInd], lpFileName, hDrawingDC);
|
||||
SaveDIBToFile(m_hBms[m_currInd], lpFileName, m_hDrawingDC);
|
||||
}
|
||||
|
||||
BOOL ImageModel::IsImageSaved() const
|
||||
{
|
||||
return imageSaved;
|
||||
return g_imageSaved;
|
||||
}
|
||||
|
||||
void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
|
||||
|
@ -176,17 +176,17 @@ void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSk
|
|||
INT newHeight = oldHeight * nStretchPercentY / 100;
|
||||
if (oldWidth != newWidth || oldHeight != newHeight)
|
||||
{
|
||||
HBITMAP hbm0 = CopyDIBImage(hBms[currInd], newWidth, newHeight);
|
||||
HBITMAP hbm0 = CopyDIBImage(m_hBms[m_currInd], newWidth, newHeight);
|
||||
PushImageForUndo(hbm0);
|
||||
}
|
||||
if (nSkewDegX)
|
||||
{
|
||||
HBITMAP hbm1 = SkewDIB(hDrawingDC, hBms[currInd], nSkewDegX, FALSE);
|
||||
HBITMAP hbm1 = SkewDIB(m_hDrawingDC, m_hBms[m_currInd], nSkewDegX, FALSE);
|
||||
PushImageForUndo(hbm1);
|
||||
}
|
||||
if (nSkewDegY)
|
||||
{
|
||||
HBITMAP hbm2 = SkewDIB(hDrawingDC, hBms[currInd], nSkewDegY, TRUE);
|
||||
HBITMAP hbm2 = SkewDIB(m_hDrawingDC, m_hBms[m_currInd], nSkewDegY, TRUE);
|
||||
PushImageForUndo(hbm2);
|
||||
}
|
||||
NotifyImageChanged();
|
||||
|
@ -194,31 +194,31 @@ void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSk
|
|||
|
||||
int ImageModel::GetWidth() const
|
||||
{
|
||||
return GetDIBWidth(hBms[currInd]);
|
||||
return GetDIBWidth(m_hBms[m_currInd]);
|
||||
}
|
||||
|
||||
int ImageModel::GetHeight() const
|
||||
{
|
||||
return GetDIBHeight(hBms[currInd]);
|
||||
return GetDIBHeight(m_hBms[m_currInd]);
|
||||
}
|
||||
|
||||
void ImageModel::InvertColors()
|
||||
{
|
||||
RECT rect = {0, 0, GetWidth(), GetHeight()};
|
||||
PushImageForUndo();
|
||||
InvertRect(hDrawingDC, &rect);
|
||||
InvertRect(m_hDrawingDC, &rect);
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
||||
HDC ImageModel::GetDC()
|
||||
{
|
||||
return hDrawingDC;
|
||||
return m_hDrawingDC;
|
||||
}
|
||||
|
||||
void ImageModel::FlipHorizontally()
|
||||
{
|
||||
PushImageForUndo();
|
||||
StretchBlt(hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
|
||||
StretchBlt(m_hDrawingDC, GetWidth() - 1, 0, -GetWidth(), GetHeight(), GetDC(), 0, 0,
|
||||
GetWidth(), GetHeight(), SRCCOPY);
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ void ImageModel::FlipHorizontally()
|
|||
void ImageModel::FlipVertically()
|
||||
{
|
||||
PushImageForUndo();
|
||||
StretchBlt(hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
|
||||
StretchBlt(m_hDrawingDC, 0, GetHeight() - 1, GetWidth(), -GetHeight(), GetDC(), 0, 0,
|
||||
GetWidth(), GetHeight(), SRCCOPY);
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ void ImageModel::RotateNTimes90Degrees(int iN)
|
|||
case 1:
|
||||
case 3:
|
||||
{
|
||||
HBITMAP hbm = Rotate90DegreeBlt(hDrawingDC, GetWidth(), GetHeight(), iN == 1, FALSE);
|
||||
HBITMAP hbm = Rotate90DegreeBlt(m_hDrawingDC, GetWidth(), GetHeight(), iN == 1, FALSE);
|
||||
if (hbm)
|
||||
PushImageForUndo(hbm);
|
||||
break;
|
||||
|
@ -246,28 +246,25 @@ void ImageModel::RotateNTimes90Degrees(int iN)
|
|||
case 2:
|
||||
{
|
||||
PushImageForUndo();
|
||||
StretchBlt(hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(),
|
||||
hDrawingDC, 0, 0, GetWidth(), GetHeight(), SRCCOPY);
|
||||
StretchBlt(m_hDrawingDC, GetWidth() - 1, GetHeight() - 1, -GetWidth(), -GetHeight(),
|
||||
m_hDrawingDC, 0, 0, GetWidth(), GetHeight(), SRCCOPY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
||||
void ImageModel::DeleteSelection()
|
||||
{
|
||||
if (!selectionModel.m_bShow)
|
||||
return;
|
||||
|
||||
selectionModel.TakeOff();
|
||||
selectionModel.m_bShow = FALSE;
|
||||
selectionModel.ClearColor();
|
||||
selectionModel.ClearMask();
|
||||
NotifyImageChanged();
|
||||
}
|
||||
|
||||
void ImageModel::Bound(POINT& pt) const
|
||||
{
|
||||
pt.x = max(0, min(pt.x, GetWidth()));
|
||||
pt.y = max(0, min(pt.y, GetHeight()));
|
||||
}
|
||||
|
||||
HBITMAP ImageModel::CopyBitmap()
|
||||
{
|
||||
// NOTE: An app cannot select a bitmap into more than one device context at a time.
|
||||
::SelectObject(m_hDrawingDC, m_hbmOld); // De-select
|
||||
HBITMAP ret = CopyDIBImage(m_hBms[m_currInd]);
|
||||
m_hbmOld = ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); // Re-select
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
virtual ~ImageModel();
|
||||
|
||||
HDC GetDC();
|
||||
BOOL CanUndo() const { return undoSteps > 0; }
|
||||
BOOL CanRedo() const { return redoSteps > 0; }
|
||||
BOOL CanUndo() const { return m_undoSteps > 0; }
|
||||
BOOL CanRedo() const { return m_redoSteps > 0; }
|
||||
void PushImageForUndo(HBITMAP hbm = NULL);
|
||||
void ResetToPrevious(void);
|
||||
void Undo(BOOL bClearRedo = FALSE);
|
||||
|
@ -31,18 +31,19 @@ public:
|
|||
void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX = 0, int nSkewDegY = 0);
|
||||
int GetWidth() const;
|
||||
int GetHeight() const;
|
||||
HBITMAP CopyBitmap();
|
||||
void InvertColors();
|
||||
void FlipHorizontally();
|
||||
void FlipVertically();
|
||||
void RotateNTimes90Degrees(int iN);
|
||||
void DeleteSelection();
|
||||
void Bound(POINT& pt) const;
|
||||
void NotifyImageChanged();
|
||||
|
||||
protected:
|
||||
HDC hDrawingDC; // The device context for this class
|
||||
int currInd; // The current index
|
||||
int undoSteps; // The undo-able count
|
||||
int redoSteps; // The redo-able count
|
||||
HBITMAP hBms[HISTORYSIZE]; // A rotation buffer of HBITMAPs
|
||||
HDC m_hDrawingDC; // The device context for this class
|
||||
int m_currInd; // The current index in m_hBms
|
||||
int m_undoSteps; // The undo-able count
|
||||
int m_redoSteps; // The redo-able count
|
||||
HBITMAP m_hBms[HISTORYSIZE]; // A rotation buffer of HBITMAPs
|
||||
HGDIOBJ m_hbmOld;
|
||||
};
|
||||
|
|
|
@ -8,15 +8,13 @@
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
POINT start;
|
||||
POINT last;
|
||||
|
||||
BOOL askBeforeEnlarging = FALSE; // TODO: initialize from registry
|
||||
HINSTANCE hProgInstance = NULL;
|
||||
TCHAR filepathname[MAX_LONG_PATH] = { 0 };
|
||||
BOOL isAFile = FALSE;
|
||||
BOOL imageSaved = FALSE;
|
||||
BOOL showGrid = FALSE;
|
||||
POINT g_ptStart, g_ptEnd;
|
||||
BOOL g_askBeforeEnlarging = FALSE; // TODO: initialize from registry
|
||||
HINSTANCE g_hinstExe = NULL;
|
||||
TCHAR g_szFileName[MAX_LONG_PATH] = { 0 };
|
||||
BOOL g_isAFile = FALSE;
|
||||
BOOL g_imageSaved = FALSE;
|
||||
BOOL g_showGrid = FALSE;
|
||||
|
||||
CMainWindow mainWindow;
|
||||
|
||||
|
@ -81,7 +79,7 @@ BOOL CMainWindow::GetOpenFileName(IN OUT LPTSTR pszFile, INT cchMaxFile)
|
|||
{
|
||||
// The "All Files" item text
|
||||
CString strAllPictureFiles;
|
||||
strAllPictureFiles.LoadString(hProgInstance, IDS_ALLPICTUREFILES);
|
||||
strAllPictureFiles.LoadString(g_hinstExe, IDS_ALLPICTUREFILES);
|
||||
|
||||
// Get the import filter
|
||||
CSimpleArray<GUID> aguidFileTypesI;
|
||||
|
@ -92,7 +90,7 @@ BOOL CMainWindow::GetOpenFileName(IN OUT LPTSTR pszFile, INT cchMaxFile)
|
|||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = m_hWnd;
|
||||
ofn.hInstance = hProgInstance;
|
||||
ofn.hInstance = g_hinstExe;
|
||||
ofn.lpstrFilter = strFilter;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
|
||||
ofn.lpstrDefExt = L"png";
|
||||
|
@ -119,7 +117,7 @@ BOOL CMainWindow::GetSaveFileName(IN OUT LPTSTR pszFile, INT cchMaxFile)
|
|||
ZeroMemory(&sfn, sizeof(sfn));
|
||||
sfn.lStructSize = sizeof(sfn);
|
||||
sfn.hwndOwner = m_hWnd;
|
||||
sfn.hInstance = hProgInstance;
|
||||
sfn.hInstance = g_hinstExe;
|
||||
sfn.lpstrFilter = strFilter;
|
||||
sfn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK;
|
||||
sfn.lpfnHook = OFNHookProc;
|
||||
|
@ -170,10 +168,10 @@ BOOL CMainWindow::ChooseColor(IN OUT COLORREF *prgbColor)
|
|||
|
||||
HWND CMainWindow::DoCreate()
|
||||
{
|
||||
::LoadString(hProgInstance, IDS_DEFAULTFILENAME, filepathname, _countof(filepathname));
|
||||
::LoadString(g_hinstExe, IDS_DEFAULTFILENAME, g_szFileName, _countof(g_szFileName));
|
||||
|
||||
CString strTitle;
|
||||
strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname));
|
||||
strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName));
|
||||
|
||||
RECT& rc = registrySettings.WindowPlacement.rcNormalPosition;
|
||||
return Create(HWND_DESKTOP, rc, strTitle, WS_OVERLAPPEDWINDOW, WS_EX_ACCEPTFILES);
|
||||
|
@ -188,7 +186,7 @@ _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, INT nC
|
|||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||
#endif
|
||||
|
||||
hProgInstance = hInstance;
|
||||
g_hinstExe = hInstance;
|
||||
|
||||
// Initialize common controls library
|
||||
INITCOMMONCONTROLSEX iccx;
|
||||
|
|
|
@ -38,7 +38,7 @@ HWND CMiniatureWindow::DoCreate(HWND hwndParent)
|
|||
};
|
||||
|
||||
TCHAR strTitle[100];
|
||||
::LoadString(hProgInstance, IDS_MINIATURETITLE, strTitle, _countof(strTitle));
|
||||
::LoadString(g_hinstExe, IDS_MINIATURETITLE, strTitle, _countof(strTitle));
|
||||
|
||||
DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
|
||||
return Create(hwndParent, rc, strTitle, style, WS_EX_PALETTEWINDOW);
|
||||
|
|
|
@ -53,25 +53,25 @@ BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1)
|
|||
|
||||
void updateStartAndLast(LONG x, LONG y)
|
||||
{
|
||||
start.x = last.x = x;
|
||||
start.y = last.y = y;
|
||||
g_ptStart.x = g_ptEnd.x = x;
|
||||
g_ptStart.y = g_ptEnd.y = y;
|
||||
}
|
||||
|
||||
void updateLast(LONG x, LONG y)
|
||||
{
|
||||
last.x = x;
|
||||
last.y = y;
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
}
|
||||
|
||||
void ToolBase::reset()
|
||||
{
|
||||
pointSP = 0;
|
||||
start.x = start.y = last.x = last.y = -1;
|
||||
g_ptStart.x = g_ptStart.y = g_ptEnd.x = g_ptEnd.y = -1;
|
||||
selectionModel.ResetPtStack();
|
||||
if (selectionModel.m_bShow)
|
||||
{
|
||||
selectionModel.Landing();
|
||||
selectionModel.m_bShow = FALSE;
|
||||
selectionModel.HideSelection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,24 +99,54 @@ void ToolBase::endEvent()
|
|||
m_hdc = NULL;
|
||||
}
|
||||
|
||||
void ToolBase::OnDrawSelectionOnCanvas(HDC hdc)
|
||||
{
|
||||
if (!selectionModel.m_bShow)
|
||||
return;
|
||||
|
||||
RECT rcSelection = selectionModel.m_rc;
|
||||
canvasWindow.ImageToCanvas(rcSelection);
|
||||
|
||||
::InflateRect(&rcSelection, GRIP_SIZE, GRIP_SIZE);
|
||||
drawSizeBoxes(hdc, &rcSelection, TRUE);
|
||||
}
|
||||
|
||||
/* TOOLS ********************************************************/
|
||||
|
||||
// TOOL_FREESEL
|
||||
struct FreeSelTool : ToolBase
|
||||
{
|
||||
BOOL m_bLeftButton;
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
|
||||
FreeSelTool() : ToolBase(TOOL_FREESEL), m_bLeftButton(FALSE)
|
||||
FreeSelTool() : ToolBase(TOOL_FREESEL)
|
||||
{
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
if (!selectionModel.IsLanded())
|
||||
{
|
||||
selectionModel.DrawBackgroundPoly(hdc, selectionModel.m_rgbBack);
|
||||
selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
|
||||
}
|
||||
|
||||
if (canvasWindow.m_drawing)
|
||||
{
|
||||
selectionModel.DrawFramePoly(hdc);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnCanvas(HDC hdc) override
|
||||
{
|
||||
OnDrawSelectionOnCanvas(hdc);
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
selectionModel.Landing();
|
||||
if (bLeftButton)
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
selectionModel.m_bShow = FALSE;
|
||||
selectionModel.HideSelection();
|
||||
selectionModel.ResetPtStack();
|
||||
POINT pt = { x, y };
|
||||
selectionModel.PushToPtStack(pt);
|
||||
|
@ -131,8 +161,7 @@ struct FreeSelTool : ToolBase
|
|||
POINT pt = { x, y };
|
||||
imageModel.Bound(pt);
|
||||
selectionModel.PushToPtStack(pt);
|
||||
imageModel.ResetToPrevious();
|
||||
selectionModel.DrawFramePoly(m_hdc);
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,16 +169,13 @@ struct FreeSelTool : ToolBase
|
|||
{
|
||||
if (bLeftButton)
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
if (selectionModel.PtStackSize() > 2)
|
||||
{
|
||||
selectionModel.BuildMaskFromPtStack();
|
||||
selectionModel.TakeOff();
|
||||
selectionModel.m_bShow = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageModel.Undo(TRUE);
|
||||
selectionModel.ResetPtStack();
|
||||
selectionModel.m_bShow = FALSE;
|
||||
}
|
||||
|
@ -159,15 +185,13 @@ struct FreeSelTool : ToolBase
|
|||
|
||||
void OnFinishDraw() override
|
||||
{
|
||||
m_bLeftButton = FALSE;
|
||||
selectionModel.Landing();
|
||||
ToolBase::OnFinishDraw();
|
||||
}
|
||||
|
||||
void OnCancelDraw() override
|
||||
{
|
||||
if (m_bLeftButton)
|
||||
imageModel.Undo(TRUE);
|
||||
m_bLeftButton = FALSE;
|
||||
selectionModel.HideSelection();
|
||||
ToolBase::OnCancelDraw();
|
||||
}
|
||||
};
|
||||
|
@ -175,20 +199,39 @@ struct FreeSelTool : ToolBase
|
|||
// TOOL_RECTSEL
|
||||
struct RectSelTool : ToolBase
|
||||
{
|
||||
BOOL m_bLeftButton;
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
|
||||
RectSelTool() : ToolBase(TOOL_RECTSEL), m_bLeftButton(FALSE)
|
||||
RectSelTool() : ToolBase(TOOL_RECTSEL)
|
||||
{
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
if (!selectionModel.IsLanded())
|
||||
{
|
||||
selectionModel.DrawBackgroundRect(hdc, selectionModel.m_rgbBack);
|
||||
selectionModel.DrawSelection(hdc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
|
||||
}
|
||||
|
||||
if (canvasWindow.m_drawing)
|
||||
{
|
||||
RECT rc = selectionModel.m_rc;
|
||||
if (!::IsRectEmpty(&rc))
|
||||
RectSel(hdc, rc.left, rc.top, rc.right, rc.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnCanvas(HDC hdc) override
|
||||
{
|
||||
OnDrawSelectionOnCanvas(hdc);
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
selectionModel.Landing();
|
||||
if (bLeftButton)
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
selectionModel.m_bShow = FALSE;
|
||||
::SetRectEmpty(&selectionModel.m_rc);
|
||||
selectionModel.HideSelection();
|
||||
}
|
||||
m_bLeftButton = bLeftButton;
|
||||
}
|
||||
|
@ -197,11 +240,10 @@ struct RectSelTool : ToolBase
|
|||
{
|
||||
if (bLeftButton)
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
POINT pt = { x, y };
|
||||
imageModel.Bound(pt);
|
||||
selectionModel.SetRectFromPoints(start, pt);
|
||||
RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
|
||||
selectionModel.SetRectFromPoints(g_ptStart, pt);
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,9 +251,9 @@ struct RectSelTool : ToolBase
|
|||
{
|
||||
if (bLeftButton)
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
if (start.x == x && start.y == y)
|
||||
imageModel.Undo(TRUE);
|
||||
POINT pt = { x, y };
|
||||
imageModel.Bound(pt);
|
||||
selectionModel.SetRectFromPoints(g_ptStart, pt);
|
||||
selectionModel.m_bShow = !selectionModel.m_rc.IsRectEmpty();
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
@ -219,22 +261,68 @@ struct RectSelTool : ToolBase
|
|||
|
||||
void OnFinishDraw() override
|
||||
{
|
||||
m_bLeftButton = FALSE;
|
||||
selectionModel.Landing();
|
||||
ToolBase::OnFinishDraw();
|
||||
}
|
||||
|
||||
void OnCancelDraw() override
|
||||
{
|
||||
if (m_bLeftButton)
|
||||
imageModel.Undo(TRUE);
|
||||
m_bLeftButton = FALSE;
|
||||
selectionModel.HideSelection();
|
||||
ToolBase::OnCancelDraw();
|
||||
}
|
||||
};
|
||||
|
||||
struct GenericDrawTool : ToolBase
|
||||
struct TwoPointDrawTool : ToolBase
|
||||
{
|
||||
GenericDrawTool(TOOLTYPE type) : ToolBase(type)
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
BOOL m_bDrawing = FALSE;
|
||||
|
||||
TwoPointDrawTool(TOOLTYPE type) : ToolBase(type)
|
||||
{
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
m_bLeftButton = bLeftButton;
|
||||
m_bDrawing = TRUE;
|
||||
g_ptStart.x = g_ptEnd.x = x;
|
||||
g_ptStart.y = g_ptEnd.y = y;
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
imageModel.PushImageForUndo();
|
||||
OnDrawOverlayOnImage(m_hdc);
|
||||
m_bDrawing = FALSE;
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnFinishDraw() override
|
||||
{
|
||||
m_bDrawing = FALSE;
|
||||
ToolBase::OnFinishDraw();
|
||||
}
|
||||
|
||||
void OnCancelDraw() override
|
||||
{
|
||||
m_bDrawing = FALSE;
|
||||
ToolBase::OnCancelDraw();
|
||||
}
|
||||
};
|
||||
|
||||
struct SmoothDrawTool : ToolBase
|
||||
{
|
||||
SmoothDrawTool(TOOLTYPE type) : ToolBase(type)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -243,7 +331,9 @@ struct GenericDrawTool : ToolBase
|
|||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
draw(bLeftButton, x, y);
|
||||
g_ptStart.x = g_ptEnd.x = x;
|
||||
g_ptStart.y = g_ptEnd.y = y;
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
|
||||
|
@ -255,7 +345,12 @@ struct GenericDrawTool : ToolBase
|
|||
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
draw(bLeftButton, x, y);
|
||||
imageModel.NotifyImageChanged();
|
||||
OnFinishDraw();
|
||||
}
|
||||
|
||||
void OnFinishDraw() override
|
||||
{
|
||||
ToolBase::OnFinishDraw();
|
||||
}
|
||||
|
||||
void OnCancelDraw() override
|
||||
|
@ -267,18 +362,20 @@ struct GenericDrawTool : ToolBase
|
|||
};
|
||||
|
||||
// TOOL_RUBBER
|
||||
struct RubberTool : GenericDrawTool
|
||||
struct RubberTool : SmoothDrawTool
|
||||
{
|
||||
RubberTool() : GenericDrawTool(TOOL_RUBBER)
|
||||
RubberTool() : SmoothDrawTool(TOOL_RUBBER)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
if (bLeftButton)
|
||||
Erase(m_hdc, last.x, last.y, x, y, m_bg, toolsModel.GetRubberRadius());
|
||||
Erase(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_bg, toolsModel.GetRubberRadius());
|
||||
else
|
||||
Replace(m_hdc, last.x, last.y, x, y, m_fg, m_bg, toolsModel.GetRubberRadius());
|
||||
Replace(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, m_fg, m_bg, toolsModel.GetRubberRadius());
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -354,38 +451,42 @@ struct ZoomTool : ToolBase
|
|||
};
|
||||
|
||||
// TOOL_PEN
|
||||
struct PenTool : GenericDrawTool
|
||||
struct PenTool : SmoothDrawTool
|
||||
{
|
||||
PenTool() : GenericDrawTool(TOOL_PEN)
|
||||
PenTool() : SmoothDrawTool(TOOL_PEN)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
COLORREF rgb = bLeftButton ? m_fg : m_bg;
|
||||
Line(m_hdc, last.x, last.y, x, y, rgb, 1);
|
||||
Line(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, 1);
|
||||
::SetPixelV(m_hdc, x, y, rgb);
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_BRUSH
|
||||
struct BrushTool : GenericDrawTool
|
||||
struct BrushTool : SmoothDrawTool
|
||||
{
|
||||
BrushTool() : GenericDrawTool(TOOL_BRUSH)
|
||||
BrushTool() : SmoothDrawTool(TOOL_BRUSH)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
COLORREF rgb = bLeftButton ? m_fg : m_bg;
|
||||
Brush(m_hdc, last.x, last.y, x, y, rgb, toolsModel.GetBrushStyle());
|
||||
Brush(m_hdc, g_ptEnd.x, g_ptEnd.y, x, y, rgb, toolsModel.GetBrushStyle());
|
||||
g_ptEnd.x = x;
|
||||
g_ptEnd.y = y;
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_AIRBRUSH
|
||||
struct AirBrushTool : GenericDrawTool
|
||||
struct AirBrushTool : SmoothDrawTool
|
||||
{
|
||||
AirBrushTool() : GenericDrawTool(TOOL_AIRBRUSH)
|
||||
AirBrushTool() : SmoothDrawTool(TOOL_AIRBRUSH)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -403,13 +504,22 @@ struct TextTool : ToolBase
|
|||
{
|
||||
}
|
||||
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
if (canvasWindow.m_drawing)
|
||||
{
|
||||
RECT rc = selectionModel.m_rc;
|
||||
if (!::IsRectEmpty(&rc))
|
||||
RectSel(hdc, rc.left, rc.top, rc.right, rc.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePoint(LONG x, LONG y)
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
POINT pt = { x, y };
|
||||
imageModel.Bound(pt);
|
||||
selectionModel.SetRectFromPoints(start, pt);
|
||||
RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
|
||||
selectionModel.SetRectFromPoints(g_ptStart, pt);
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
|
@ -417,7 +527,6 @@ struct TextTool : ToolBase
|
|||
if (!textEditWindow.IsWindow())
|
||||
textEditWindow.Create(canvasWindow);
|
||||
|
||||
imageModel.PushImageForUndo();
|
||||
UpdatePoint(x, y);
|
||||
}
|
||||
|
||||
|
@ -426,30 +535,40 @@ struct TextTool : ToolBase
|
|||
UpdatePoint(x, y);
|
||||
}
|
||||
|
||||
void draw(HDC hdc)
|
||||
{
|
||||
CString szText;
|
||||
textEditWindow.GetWindowText(szText);
|
||||
|
||||
RECT rc;
|
||||
textEditWindow.InvalidateEditRect();
|
||||
textEditWindow.GetEditRect(&rc);
|
||||
::InflateRect(&rc, -GRIP_SIZE / 2, -GRIP_SIZE / 2);
|
||||
|
||||
// Draw the text
|
||||
INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1);
|
||||
imageModel.PushImageForUndo();
|
||||
Text(hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText,
|
||||
textEditWindow.GetFont(), style);
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
if (textEditWindow.IsWindow())
|
||||
textEditWindow.ShowWindow(SW_HIDE);
|
||||
selectionModel.HideSelection();
|
||||
}
|
||||
|
||||
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
imageModel.Undo(TRUE);
|
||||
|
||||
POINT pt = { x, y };
|
||||
imageModel.Bound(pt);
|
||||
selectionModel.SetRectFromPoints(start, pt);
|
||||
selectionModel.SetRectFromPoints(g_ptStart, pt);
|
||||
|
||||
BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow);
|
||||
if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0)
|
||||
{
|
||||
CString szText;
|
||||
textEditWindow.GetWindowText(szText);
|
||||
|
||||
RECT rc;
|
||||
textEditWindow.InvalidateEditRect();
|
||||
textEditWindow.GetEditRect(&rc);
|
||||
::InflateRect(&rc, -GRIP_SIZE / 2, -GRIP_SIZE / 2);
|
||||
|
||||
// Draw the text
|
||||
INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1);
|
||||
imageModel.PushImageForUndo();
|
||||
Text(m_hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText,
|
||||
textEditWindow.GetFont(), style);
|
||||
draw(m_hdc);
|
||||
|
||||
if (selectionModel.m_rc.IsRectEmpty())
|
||||
{
|
||||
|
@ -494,201 +613,224 @@ struct TextTool : ToolBase
|
|||
|
||||
void OnFinishDraw() override
|
||||
{
|
||||
toolsModel.OnButtonDown(TRUE, -1, -1, TRUE);
|
||||
toolsModel.OnButtonUp(TRUE, -1, -1);
|
||||
draw(m_hdc);
|
||||
quit();
|
||||
ToolBase::OnFinishDraw();
|
||||
}
|
||||
|
||||
void OnCancelDraw() override
|
||||
{
|
||||
quit();
|
||||
ToolBase::OnCancelDraw();
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_LINE
|
||||
struct LineTool : GenericDrawTool
|
||||
struct LineTool : TwoPointDrawTool
|
||||
{
|
||||
LineTool() : GenericDrawTool(TOOL_LINE)
|
||||
LineTool() : TwoPointDrawTool(TOOL_LINE)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
if (!m_bDrawing)
|
||||
return;
|
||||
if (GetAsyncKeyState(VK_SHIFT) < 0)
|
||||
roundTo8Directions(start.x, start.y, x, y);
|
||||
COLORREF rgb = bLeftButton ? m_fg : m_bg;
|
||||
Line(m_hdc, start.x, start.y, x, y, rgb, toolsModel.GetLineWidth());
|
||||
roundTo8Directions(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
|
||||
COLORREF rgb = m_bLeftButton ? m_fg : m_bg;
|
||||
Line(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, rgb, toolsModel.GetLineWidth());
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_BEZIER
|
||||
struct BezierTool : ToolBase
|
||||
{
|
||||
BOOL m_bLeftButton;
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
BOOL m_bDrawing = FALSE;
|
||||
|
||||
BezierTool() : ToolBase(TOOL_BEZIER), m_bLeftButton(FALSE)
|
||||
BezierTool() : ToolBase(TOOL_BEZIER)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton)
|
||||
void OnDrawOverlayOnImage(HDC hdc)
|
||||
{
|
||||
COLORREF rgb = (bLeftButton ? m_fg : m_bg);
|
||||
if (!m_bDrawing)
|
||||
return;
|
||||
|
||||
COLORREF rgb = (m_bLeftButton ? m_fg : m_bg);
|
||||
switch (pointSP)
|
||||
{
|
||||
case 1:
|
||||
Line(m_hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, rgb,
|
||||
Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, rgb,
|
||||
toolsModel.GetLineWidth());
|
||||
break;
|
||||
case 2:
|
||||
Bezier(m_hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], rgb, toolsModel.GetLineWidth());
|
||||
Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], rgb, toolsModel.GetLineWidth());
|
||||
break;
|
||||
case 3:
|
||||
Bezier(m_hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], rgb, toolsModel.GetLineWidth());
|
||||
Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], rgb, toolsModel.GetLineWidth());
|
||||
break;
|
||||
}
|
||||
m_bLeftButton = bLeftButton;
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
m_bLeftButton = bLeftButton;
|
||||
|
||||
if (pointSP == 0)
|
||||
if (!m_bDrawing)
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
pointSP++;
|
||||
m_bDrawing = TRUE;
|
||||
pointStack[pointSP].x = pointStack[pointSP + 1].x = x;
|
||||
pointStack[pointSP].y = pointStack[pointSP + 1].y = y;
|
||||
++pointSP;
|
||||
}
|
||||
else
|
||||
{
|
||||
++pointSP;
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
}
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
draw(bLeftButton);
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
draw(bLeftButton);
|
||||
pointSP++;
|
||||
if (pointSP == 4)
|
||||
pointSP = 0;
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
if (pointSP >= 3)
|
||||
{
|
||||
OnFinishDraw();
|
||||
return;
|
||||
}
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnCancelDraw() override
|
||||
{
|
||||
OnButtonUp(FALSE, 0, 0);
|
||||
imageModel.Undo(TRUE);
|
||||
m_bDrawing = FALSE;
|
||||
ToolBase::OnCancelDraw();
|
||||
}
|
||||
|
||||
void OnFinishDraw() override
|
||||
{
|
||||
if (pointSP)
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
--pointSP;
|
||||
draw(m_bLeftButton);
|
||||
}
|
||||
imageModel.PushImageForUndo();
|
||||
OnDrawOverlayOnImage(m_hdc);
|
||||
m_bDrawing = FALSE;
|
||||
ToolBase::OnFinishDraw();
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_RECT
|
||||
struct RectTool : GenericDrawTool
|
||||
struct RectTool : TwoPointDrawTool
|
||||
{
|
||||
RectTool() : GenericDrawTool(TOOL_RECT)
|
||||
RectTool() : TwoPointDrawTool(TOOL_RECT)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
if (!m_bDrawing)
|
||||
return;
|
||||
if (GetAsyncKeyState(VK_SHIFT) < 0)
|
||||
regularize(start.x, start.y, x, y);
|
||||
if (bLeftButton)
|
||||
Rect(m_hdc, start.x, start.y, x, y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
|
||||
if (m_bLeftButton)
|
||||
Rect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
else
|
||||
Rect(m_hdc, start.x, start.y, x, y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
Rect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_SHAPE
|
||||
struct ShapeTool : ToolBase
|
||||
{
|
||||
BOOL m_bLeftButton;
|
||||
BOOL m_bLeftButton = FALSE;
|
||||
BOOL m_bClosed = FALSE;
|
||||
|
||||
ShapeTool() : ToolBase(TOOL_SHAPE), m_bLeftButton(FALSE)
|
||||
ShapeTool() : ToolBase(TOOL_SHAPE)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y, BOOL bClosed = FALSE)
|
||||
void OnDrawOverlayOnImage(HDC hdc)
|
||||
{
|
||||
if (pointSP + 1 >= 2)
|
||||
{
|
||||
if (bLeftButton)
|
||||
Poly(m_hdc, pointStack, pointSP + 1, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), bClosed, FALSE);
|
||||
else
|
||||
Poly(m_hdc, pointStack, pointSP + 1, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), bClosed, FALSE);
|
||||
}
|
||||
m_bLeftButton = bLeftButton;
|
||||
if (pointSP <= 0)
|
||||
return;
|
||||
|
||||
if (m_bLeftButton)
|
||||
Poly(hdc, pointStack, pointSP + 1, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
|
||||
else
|
||||
Poly(hdc, pointStack, pointSP + 1, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), m_bClosed, FALSE);
|
||||
}
|
||||
|
||||
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
|
||||
{
|
||||
m_bLeftButton = bLeftButton;
|
||||
m_bClosed = FALSE;
|
||||
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
|
||||
if (pointSP == 0 && !bDoubleClick)
|
||||
if (pointSP && bDoubleClick)
|
||||
{
|
||||
OnFinishDraw();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pointSP == 0)
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
draw(bLeftButton, x, y);
|
||||
pointSP++;
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
draw(bLeftButton, x, y, bDoubleClick);
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
|
||||
if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
|
||||
roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, x, y);
|
||||
draw(bLeftButton, x, y, FALSE);
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
|
||||
roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y, x, y);
|
||||
|
||||
m_bClosed = FALSE;
|
||||
if (nearlyEqualPoints(x, y, pointStack[0].x, pointStack[0].y))
|
||||
{
|
||||
pointSP--;
|
||||
draw(bLeftButton, x, y, TRUE);
|
||||
pointSP = 0;
|
||||
OnFinishDraw();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointSP++;
|
||||
pointStack[pointSP].x = x;
|
||||
pointStack[pointSP].y = y;
|
||||
draw(bLeftButton, x, y, FALSE);
|
||||
}
|
||||
|
||||
if (pointSP == _countof(pointStack))
|
||||
pointSP--;
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void OnCancelDraw() override
|
||||
{
|
||||
imageModel.Undo(TRUE);
|
||||
ToolBase::OnCancelDraw();
|
||||
}
|
||||
|
||||
|
@ -696,49 +838,57 @@ struct ShapeTool : ToolBase
|
|||
{
|
||||
if (pointSP)
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
--pointSP;
|
||||
draw(m_bLeftButton, -1, -1, TRUE);
|
||||
m_bClosed = TRUE;
|
||||
|
||||
imageModel.PushImageForUndo();
|
||||
OnDrawOverlayOnImage(m_hdc);
|
||||
}
|
||||
|
||||
m_bClosed = FALSE;
|
||||
pointSP = 0;
|
||||
|
||||
ToolBase::OnFinishDraw();
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_ELLIPSE
|
||||
struct EllipseTool : GenericDrawTool
|
||||
struct EllipseTool : TwoPointDrawTool
|
||||
{
|
||||
EllipseTool() : GenericDrawTool(TOOL_ELLIPSE)
|
||||
EllipseTool() : TwoPointDrawTool(TOOL_ELLIPSE)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
if (!m_bDrawing)
|
||||
return;
|
||||
if (GetAsyncKeyState(VK_SHIFT) < 0)
|
||||
regularize(start.x, start.y, x, y);
|
||||
if (bLeftButton)
|
||||
Ellp(m_hdc, start.x, start.y, x, y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
|
||||
if (m_bLeftButton)
|
||||
Ellp(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
else
|
||||
Ellp(m_hdc, start.x, start.y, x, y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
Ellp(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
}
|
||||
};
|
||||
|
||||
// TOOL_RRECT
|
||||
struct RRectTool : GenericDrawTool
|
||||
struct RRectTool : TwoPointDrawTool
|
||||
{
|
||||
RRectTool() : GenericDrawTool(TOOL_RRECT)
|
||||
RRectTool() : TwoPointDrawTool(TOOL_RRECT)
|
||||
{
|
||||
}
|
||||
|
||||
void draw(BOOL bLeftButton, LONG x, LONG y) override
|
||||
void OnDrawOverlayOnImage(HDC hdc) override
|
||||
{
|
||||
imageModel.ResetToPrevious();
|
||||
if (!m_bDrawing)
|
||||
return;
|
||||
if (GetAsyncKeyState(VK_SHIFT) < 0)
|
||||
regularize(start.x, start.y, x, y);
|
||||
if (bLeftButton)
|
||||
RRect(m_hdc, start.x, start.y, x, y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
regularize(g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y);
|
||||
if (m_bLeftButton)
|
||||
RRect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_fg, m_bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
else
|
||||
RRect(m_hdc, start.x, start.y, x, y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
RRect(hdc, g_ptStart.x, g_ptStart.y, g_ptEnd.x, g_ptEnd.y, m_bg, m_fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -181,13 +181,7 @@ LRESULT CPaletteWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam,
|
|||
|
||||
LRESULT CPaletteWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
InvalidateRect(NULL, FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CPaletteWindow::OnPaletteModelPaletteChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
InvalidateRect(NULL, FALSE);
|
||||
Invalidate(FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ public:
|
|||
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
|
||||
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
|
||||
MESSAGE_HANDLER(WM_PALETTEMODELCOLORCHANGED, OnPaletteModelColorChanged)
|
||||
MESSAGE_HANDLER(WM_PALETTEMODELPALETTECHANGED, OnPaletteModelPaletteChanged)
|
||||
END_MSG_MAP()
|
||||
|
||||
CPaletteWindow();
|
||||
|
@ -45,7 +44,6 @@ protected:
|
|||
LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnPaletteModelPaletteChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
|
||||
protected:
|
||||
INT DoHitTest(INT xPos, INT yPos) const;
|
||||
|
|
|
@ -106,5 +106,5 @@ void PaletteModel::NotifyColorChanged()
|
|||
void PaletteModel::NotifyPaletteChanged()
|
||||
{
|
||||
if (paletteWindow.IsWindow())
|
||||
paletteWindow.SendMessage(WM_PALETTEMODELPALETTECHANGED);
|
||||
paletteWindow.Invalidate(FALSE);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ SelectionModel::SelectionModel()
|
|||
, m_bShow(FALSE)
|
||||
{
|
||||
::SetRectEmpty(&m_rc);
|
||||
::SetRectEmpty(&m_rcOld);
|
||||
m_ptHit.x = m_ptHit.y = -1;
|
||||
}
|
||||
|
||||
|
@ -57,25 +58,13 @@ void SelectionModel::PushToPtStack(POINT pt)
|
|||
#undef GROW_COUNT
|
||||
}
|
||||
|
||||
void SelectionModel::ShiftPtStack(BOOL bPlus)
|
||||
void SelectionModel::ShiftPtStack(INT dx, INT dy)
|
||||
{
|
||||
if (bPlus)
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
POINT& pt = m_ptStack[i];
|
||||
pt.x += m_rc.left;
|
||||
pt.y += m_rc.top;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (INT i = 0; i < m_iPtSP; ++i)
|
||||
{
|
||||
POINT& pt = m_ptStack[i];
|
||||
pt.x -= m_rc.left;
|
||||
pt.y -= m_rc.top;
|
||||
}
|
||||
POINT& pt = m_ptStack[i];
|
||||
pt.x += dx;
|
||||
pt.y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,16 +82,16 @@ void SelectionModel::BuildMaskFromPtStack()
|
|||
rc.right += 1;
|
||||
rc.bottom += 1;
|
||||
|
||||
m_rc = rc;
|
||||
|
||||
ShiftPtStack(FALSE);
|
||||
m_rc = m_rcOld = rc;
|
||||
|
||||
ClearMask();
|
||||
|
||||
ShiftPtStack(-m_rcOld.left, -m_rcOld.top);
|
||||
|
||||
HDC hdcMem = ::CreateCompatibleDC(NULL);
|
||||
m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
|
||||
HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
|
||||
FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
|
||||
::FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
|
||||
HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
|
||||
HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
|
||||
::Polygon(hdcMem, m_ptStack, m_iPtSP);
|
||||
|
@ -110,34 +99,39 @@ void SelectionModel::BuildMaskFromPtStack()
|
|||
::SelectObject(hdcMem, hPenOld);
|
||||
::SelectObject(hdcMem, hbmOld);
|
||||
::DeleteDC(hdcMem);
|
||||
|
||||
ShiftPtStack(+m_rcOld.left, +m_rcOld.top);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
|
||||
{
|
||||
ShiftPtStack(TRUE);
|
||||
if (::IsRectEmpty(&m_rcOld))
|
||||
return;
|
||||
|
||||
HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN));
|
||||
HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg));
|
||||
::Polygon(hDCImage, m_ptStack, m_iPtSP);
|
||||
::DeleteObject(::SelectObject(hDCImage, hbrOld));
|
||||
::SelectObject(hDCImage, hPenOld);
|
||||
|
||||
ShiftPtStack(FALSE);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
|
||||
{
|
||||
Rect(hDCImage, m_rc.left, m_rc.top, m_rc.right, m_rc.bottom, crBg, crBg, 0, 1);
|
||||
if (::IsRectEmpty(&m_rcOld))
|
||||
return;
|
||||
|
||||
Rect(hDCImage, m_rcOld.left, m_rcOld.top, m_rcOld.right, m_rcOld.bottom, crBg, crBg, 0, 1);
|
||||
}
|
||||
|
||||
void SelectionModel::DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg, BOOL bBgTransparent)
|
||||
void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
|
||||
{
|
||||
CRect rc = *prc;
|
||||
CRect rc = m_rc;
|
||||
if (::IsRectEmpty(&rc))
|
||||
return;
|
||||
|
||||
BITMAP bm;
|
||||
GetObject(m_hbmColor, sizeof(BITMAP), &bm);
|
||||
if (!GetObject(m_hbmColor, sizeof(BITMAP), &bm))
|
||||
return;
|
||||
|
||||
COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID);
|
||||
|
||||
|
@ -161,23 +155,23 @@ void SelectionModel::GetSelectionContents(HDC hDCImage)
|
|||
::DeleteDC(hMemDC);
|
||||
}
|
||||
|
||||
BOOL SelectionModel::IsLanded() const
|
||||
{
|
||||
return !m_hbmColor;
|
||||
}
|
||||
|
||||
BOOL SelectionModel::TakeOff()
|
||||
{
|
||||
if (m_hbmColor || ::IsRectEmpty(&m_rc))
|
||||
if (!IsLanded() || ::IsRectEmpty(&m_rc))
|
||||
return FALSE;
|
||||
|
||||
HDC hDCImage = imageModel.GetDC();
|
||||
GetSelectionContents(hDCImage);
|
||||
m_rgbBack = paletteModel.GetBgColor();
|
||||
GetSelectionContents(imageModel.GetDC());
|
||||
|
||||
if (toolsModel.GetActiveTool() == TOOL_FREESEL)
|
||||
{
|
||||
DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
|
||||
ClearMask();
|
||||
DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
|
||||
}
|
||||
|
||||
m_rcOld = m_rc;
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
return TRUE;
|
||||
|
@ -185,16 +179,23 @@ BOOL SelectionModel::TakeOff()
|
|||
|
||||
void SelectionModel::Landing()
|
||||
{
|
||||
if (!m_hbmColor)
|
||||
if (IsLanded() && !m_bShow)
|
||||
{
|
||||
imageModel.NotifyImageChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
DrawSelection(imageModel.GetDC(), &m_rc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
|
||||
m_bShow = FALSE;
|
||||
|
||||
::SetRectEmpty(&m_rc);
|
||||
ClearMask();
|
||||
ClearColor();
|
||||
if (!::EqualRect(m_rc, m_rcOld) && !::IsRectEmpty(m_rc) && !::IsRectEmpty(m_rcOld))
|
||||
{
|
||||
imageModel.PushImageForUndo();
|
||||
|
||||
imageModel.PushImageForUndo();
|
||||
canvasWindow.m_drawing = FALSE;
|
||||
toolsModel.OnDrawOverlayOnImage(imageModel.GetDC());
|
||||
}
|
||||
|
||||
HideSelection();
|
||||
}
|
||||
|
||||
void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
|
||||
|
@ -349,11 +350,11 @@ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int
|
|||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
HBITMAP SelectionModel::GetBitmap()
|
||||
HBITMAP SelectionModel::CopyBitmap()
|
||||
{
|
||||
if (m_hbmColor == NULL)
|
||||
GetSelectionContents(imageModel.GetDC());
|
||||
return m_hbmColor;
|
||||
return CopyDIBImage(m_hbmColor);
|
||||
}
|
||||
|
||||
int SelectionModel::PtStackSize() const
|
||||
|
@ -435,15 +436,29 @@ void SelectionModel::ClearColor()
|
|||
}
|
||||
}
|
||||
|
||||
void SelectionModel::CancelSelection()
|
||||
void SelectionModel::HideSelection()
|
||||
{
|
||||
m_bShow = FALSE;
|
||||
ClearColor();
|
||||
ClearMask();
|
||||
::SetRectEmpty(&m_rc);
|
||||
::SetRectEmpty(&m_rcOld);
|
||||
|
||||
imageModel.NotifyImageChanged();
|
||||
}
|
||||
|
||||
void SelectionModel::DeleteSelection()
|
||||
{
|
||||
if (!m_bShow)
|
||||
return;
|
||||
|
||||
imageModel.PushImageForUndo();
|
||||
if (m_bShow)
|
||||
imageModel.Undo(TRUE);
|
||||
TakeOff();
|
||||
|
||||
m_bShow = FALSE;
|
||||
imageModel.NotifyImageChanged();
|
||||
imageModel.PushImageForUndo();
|
||||
if (toolsModel.GetActiveTool() == TOOL_FREESEL)
|
||||
DrawBackgroundPoly(imageModel.GetDC(), paletteModel.GetBgColor());
|
||||
else
|
||||
DrawBackgroundRect(imageModel.GetDC(), paletteModel.GetBgColor());
|
||||
|
||||
HideSelection();
|
||||
}
|
||||
|
|
|
@ -18,9 +18,11 @@ private:
|
|||
int m_iPtSP;
|
||||
|
||||
public:
|
||||
COLORREF m_rgbBack = RGB(255, 255, 255);
|
||||
BOOL m_bShow;
|
||||
CRect m_rc; // in image pixel coordinates
|
||||
POINT m_ptHit; // in image pixel coordinates
|
||||
CRect m_rcOld; // in image pixel coordinates
|
||||
|
||||
SelectionModel();
|
||||
~SelectionModel();
|
||||
|
@ -33,13 +35,16 @@ public:
|
|||
|
||||
BOOL TakeOff();
|
||||
void Landing();
|
||||
BOOL IsLanded() const;
|
||||
void HideSelection();
|
||||
void DeleteSelection();
|
||||
|
||||
HBITMAP GetBitmap();
|
||||
HBITMAP CopyBitmap();
|
||||
void GetSelectionContents(HDC hDCImage);
|
||||
void DrawFramePoly(HDC hDCImage);
|
||||
void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg);
|
||||
void DrawBackgroundRect(HDC hDCImage, COLORREF crBg);
|
||||
void DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
|
||||
void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
|
||||
void InsertFromHBITMAP(HBITMAP hBm, INT x = 0, INT y = 0);
|
||||
|
||||
// operation
|
||||
|
@ -48,7 +53,6 @@ public:
|
|||
void RotateNTimes90Degrees(int iN);
|
||||
void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY);
|
||||
|
||||
void CancelSelection();
|
||||
void Dragging(CANVAS_HITTEST hit, POINT pt);
|
||||
void ClearMask();
|
||||
void ClearColor();
|
||||
|
@ -57,5 +61,5 @@ private:
|
|||
SelectionModel(const SelectionModel&);
|
||||
SelectionModel& operator=(const SelectionModel&);
|
||||
|
||||
void ShiftPtStack(BOOL bPlus);
|
||||
void ShiftPtStack(INT dx, INT dy);
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ void CTextEditWindow::FixEditPos(LPCTSTR pszOldText)
|
|||
SelectObject(hDC, m_hFontZoomed);
|
||||
TEXTMETRIC tm;
|
||||
GetTextMetrics(hDC, &tm);
|
||||
szText += TEXT("x"); // This is a trick to enable the last newlines
|
||||
szText += TEXT("x"); // This is a trick to enable the g_ptEnd newlines
|
||||
const UINT uFormat = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP |
|
||||
DT_EXPANDTABS | DT_WORDBREAK;
|
||||
DrawText(hDC, szText, -1, &rcText, uFormat | DT_CALCRECT);
|
||||
|
@ -235,7 +235,7 @@ HWND CTextEditWindow::Create(HWND hwndParent)
|
|||
const DWORD style = ES_LEFT | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL |
|
||||
WS_CHILD | WS_THICKFRAME;
|
||||
HWND hwnd = ::CreateWindowEx(0, WC_EDIT, NULL, style, 0, 0, 0, 0,
|
||||
hwndParent, NULL, hProgInstance, NULL);
|
||||
hwndParent, NULL, g_hinstExe, NULL);
|
||||
if (hwnd)
|
||||
{
|
||||
#undef SubclassWindow // Don't use this macro
|
||||
|
|
|
@ -13,6 +13,20 @@ CToolBox toolBoxContainer;
|
|||
|
||||
/* FUNCTIONS ********************************************************/
|
||||
|
||||
LRESULT CALLBACK
|
||||
CPaintToolBar::ToolBarWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
WNDPROC oldWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if (uMsg == WM_LBUTTONUP)
|
||||
{
|
||||
// We have to detect clicking on toolbar even if no change of pressed button
|
||||
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
|
||||
INT id = (INT)SendMessage(hwnd, TB_HITTEST, 0, (LPARAM)&pt);
|
||||
::PostMessage(::GetParent(hwnd), WM_TOOLBARHIT, id, 0);
|
||||
}
|
||||
return ::CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
BOOL CPaintToolBar::DoCreate(HWND hwndParent)
|
||||
{
|
||||
// NOTE: The horizontal line above the toolbar is hidden by CCS_NODIVIDER style.
|
||||
|
@ -25,7 +39,7 @@ BOOL CPaintToolBar::DoCreate(HWND hwndParent)
|
|||
HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 16, 0);
|
||||
SendMessage(TB_SETIMAGELIST, 0, (LPARAM)hImageList);
|
||||
|
||||
HBITMAP hbmIcons = (HBITMAP)::LoadImage(hProgInstance, MAKEINTRESOURCE(IDB_TOOLBARICONS),
|
||||
HBITMAP hbmIcons = (HBITMAP)::LoadImage(g_hinstExe, MAKEINTRESOURCE(IDB_TOOLBARICONS),
|
||||
IMAGE_BITMAP, 256, 16, 0);
|
||||
ImageList_AddMasked(hImageList, hbmIcons, RGB(255, 0, 255));
|
||||
::DeleteObject(hbmIcons);
|
||||
|
@ -38,7 +52,7 @@ BOOL CPaintToolBar::DoCreate(HWND hwndParent)
|
|||
tbbutton.fsStyle = TBSTYLE_CHECKGROUP;
|
||||
for (INT i = 0; i < NUM_TOOLS; i++)
|
||||
{
|
||||
::LoadString(hProgInstance, IDS_TOOLTIP1 + i, szToolTip, _countof(szToolTip));
|
||||
::LoadString(g_hinstExe, IDS_TOOLTIP1 + i, szToolTip, _countof(szToolTip));
|
||||
tbbutton.iString = (INT_PTR)szToolTip;
|
||||
tbbutton.fsState = TBSTATE_ENABLED | ((i % 2 == 1) ? TBSTATE_WRAP : 0);
|
||||
tbbutton.idCommand = ID_FREESEL + i;
|
||||
|
@ -49,6 +63,8 @@ BOOL CPaintToolBar::DoCreate(HWND hwndParent)
|
|||
SendMessage(TB_CHECKBUTTON, ID_PEN, MAKELPARAM(TRUE, 0));
|
||||
SendMessage(TB_SETMAXTEXTROWS, 0, 0);
|
||||
SendMessage(TB_SETBUTTONSIZE, 0, MAKELPARAM(CXY_TB_BUTTON, CXY_TB_BUTTON));
|
||||
|
||||
SetWindowLongPtr(GWLP_USERDATA, SetWindowLongPtr(GWLP_WNDPROC, (LONG_PTR)ToolBarWndProc));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -114,7 +130,7 @@ LRESULT CToolBox::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHand
|
|||
|
||||
LRESULT CToolBox::OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
selectionModel.m_bShow = FALSE;
|
||||
selectionModel.HideSelection();
|
||||
toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
|
||||
|
||||
// Check the toolbar button
|
||||
|
@ -168,3 +184,10 @@ LRESULT CToolBox::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa
|
|||
::ReleaseCapture();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CToolBox::OnToolBarHit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
// See also: CPaintToolBar::ToolBarWndProc
|
||||
selectionModel.Landing();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
#define CX_TOOLBAR (TOOLBAR_COLUMNS * CXY_TB_BUTTON)
|
||||
#define CY_TOOLBAR (TOOLBAR_ROWS * CXY_TB_BUTTON)
|
||||
|
||||
#define WM_TOOLBARHIT (WM_APP + 1)
|
||||
|
||||
class CPaintToolBar : public CWindow
|
||||
{
|
||||
public:
|
||||
BOOL DoCreate(HWND hwndParent);
|
||||
static LRESULT CALLBACK ToolBarWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
};
|
||||
|
||||
class CToolBox : public CWindowImpl<CToolBox>
|
||||
|
@ -34,6 +37,7 @@ public:
|
|||
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
|
||||
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
|
||||
MESSAGE_HANDLER(WM_TOOLSMODELTOOLCHANGED, OnToolsModelToolChanged)
|
||||
MESSAGE_HANDLER(WM_TOOLBARHIT, OnToolBarHit)
|
||||
END_MSG_MAP()
|
||||
|
||||
BOOL DoCreate(HWND hwndParent);
|
||||
|
@ -48,4 +52,5 @@ private:
|
|||
LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnToolBarHit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
};
|
||||
|
|
|
@ -200,11 +200,14 @@ VOID CToolSettingsWindow::drawAirBrush(HDC hdc, LPCRECT prc)
|
|||
if (bHigh)
|
||||
{
|
||||
::FillRect(hdc, &rc, ::GetSysColorBrush(COLOR_HIGHLIGHT));
|
||||
Airbrush(hdc, x, y, ::GetSysColor(COLOR_HIGHLIGHTTEXT), s_AirRadius[i]);
|
||||
|
||||
for (int k = 0; k < 3; ++k)
|
||||
Airbrush(hdc, x, y, ::GetSysColor(COLOR_HIGHLIGHTTEXT), s_AirRadius[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Airbrush(hdc, x, y, ::GetSysColor(COLOR_WINDOWTEXT), s_AirRadius[i]);
|
||||
for (int k = 0; k < 3; ++k)
|
||||
Airbrush(hdc, x, y, ::GetSysColor(COLOR_WINDOWTEXT), s_AirRadius[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,9 +261,9 @@ VOID CToolSettingsWindow::drawBox(HDC hdc, LPCRECT prc)
|
|||
LRESULT CToolSettingsWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, WINBOOL& bHandled)
|
||||
{
|
||||
/* preloading the draw transparent/nontransparent icons for later use */
|
||||
m_hNontranspIcon = (HICON)LoadImage(hProgInstance, MAKEINTRESOURCE(IDI_NONTRANSPARENT),
|
||||
m_hNontranspIcon = (HICON)LoadImage(g_hinstExe, MAKEINTRESOURCE(IDI_NONTRANSPARENT),
|
||||
IMAGE_ICON, CX_TRANS_ICON, CY_TRANS_ICON, LR_DEFAULTCOLOR);
|
||||
m_hTranspIcon = (HICON)LoadImage(hProgInstance, MAKEINTRESOURCE(IDI_TRANSPARENT),
|
||||
m_hTranspIcon = (HICON)LoadImage(g_hinstExe, MAKEINTRESOURCE(IDI_TRANSPARENT),
|
||||
IMAGE_ICON, CX_TRANS_ICON, CY_TRANS_ICON, LR_DEFAULTCOLOR);
|
||||
|
||||
RECT trackbarZoomPos = {1, 1, 1 + 40, 1 + 64};
|
||||
|
|
|
@ -28,7 +28,7 @@ ToolsModel::ToolsModel()
|
|||
|
||||
ToolsModel::~ToolsModel()
|
||||
{
|
||||
for (size_t i = 0; i < TOOL_MAX + 1; ++i)
|
||||
for (size_t i = 0; i < _countof(m_tools); ++i)
|
||||
delete m_tools[i];
|
||||
}
|
||||
|
||||
|
@ -87,9 +87,6 @@ void ToolsModel::SetActiveTool(TOOLTYPE nActiveTool)
|
|||
{
|
||||
OnFinishDraw();
|
||||
|
||||
if (m_activeTool == nActiveTool)
|
||||
return;
|
||||
|
||||
switch (m_activeTool)
|
||||
{
|
||||
case TOOL_FREESEL:
|
||||
|
@ -225,6 +222,16 @@ void ToolsModel::OnFinishDraw()
|
|||
m_pToolObject->endEvent();
|
||||
}
|
||||
|
||||
void ToolsModel::OnDrawOverlayOnImage(HDC hdc)
|
||||
{
|
||||
m_pToolObject->OnDrawOverlayOnImage(hdc);
|
||||
}
|
||||
|
||||
void ToolsModel::OnDrawOverlayOnCanvas(HDC hdc)
|
||||
{
|
||||
m_pToolObject->OnDrawOverlayOnCanvas(hdc);
|
||||
}
|
||||
|
||||
void ToolsModel::resetTool()
|
||||
{
|
||||
m_pToolObject->reset();
|
||||
|
|
|
@ -39,34 +39,27 @@ struct ToolBase
|
|||
static INT pointSP;
|
||||
static POINT pointStack[256];
|
||||
|
||||
ToolBase(TOOLTYPE tool) : m_tool(tool), m_hdc(NULL)
|
||||
{
|
||||
}
|
||||
ToolBase(TOOLTYPE tool) : m_tool(tool), m_hdc(NULL) { }
|
||||
virtual ~ToolBase() { }
|
||||
|
||||
virtual ~ToolBase()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnMouseMove(BOOL bLeftButton, LONG x, LONG y)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnButtonUp(BOOL bLeftButton, LONG x, LONG y)
|
||||
{
|
||||
}
|
||||
virtual void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) { }
|
||||
virtual void OnMouseMove(BOOL bLeftButton, LONG x, LONG y) { }
|
||||
virtual void OnButtonUp(BOOL bLeftButton, LONG x, LONG y) { }
|
||||
|
||||
virtual void OnCancelDraw();
|
||||
virtual void OnFinishDraw();
|
||||
|
||||
virtual void OnDrawOverlayOnImage(HDC hdc) { }
|
||||
virtual void OnDrawOverlayOnCanvas(HDC hdc) { }
|
||||
|
||||
void beginEvent();
|
||||
void endEvent();
|
||||
void reset();
|
||||
|
||||
static ToolBase* createToolObject(TOOLTYPE type);
|
||||
|
||||
protected:
|
||||
void OnDrawSelectionOnCanvas(HDC hdc);
|
||||
};
|
||||
|
||||
class ToolsModel
|
||||
|
@ -112,6 +105,8 @@ public:
|
|||
void OnButtonUp(BOOL bLeftButton, LONG x, LONG y);
|
||||
void OnCancelDraw();
|
||||
void OnFinishDraw();
|
||||
void OnDrawOverlayOnImage(HDC hdc);
|
||||
void OnDrawOverlayOnCanvas(HDC hdc);
|
||||
|
||||
void resetTool();
|
||||
void selectAll();
|
||||
|
|
|
@ -17,7 +17,7 @@ typedef HWND (WINAPI *FN_HtmlHelpW)(HWND, LPCWSTR, UINT, DWORD_PTR);
|
|||
static HINSTANCE s_hHHCTRL_OCX = NULL; // HtmlHelpW needs "hhctrl.ocx"
|
||||
static FN_HtmlHelpW s_pHtmlHelpW = NULL;
|
||||
|
||||
HWND hStatusBar = NULL;
|
||||
HWND g_hStatusBar = NULL;
|
||||
|
||||
/* FUNCTIONS ********************************************************/
|
||||
|
||||
|
@ -79,9 +79,9 @@ void CMainWindow::alignChildrenToMainWindow()
|
|||
GetClientRect(&clientRect);
|
||||
RECT rcSpace = clientRect;
|
||||
|
||||
if (::IsWindowVisible(hStatusBar))
|
||||
if (::IsWindowVisible(g_hStatusBar))
|
||||
{
|
||||
::GetWindowRect(hStatusBar, &rc);
|
||||
::GetWindowRect(g_hStatusBar, &rc);
|
||||
rcSpace.bottom -= rc.bottom - rc.top;
|
||||
}
|
||||
|
||||
|
@ -142,18 +142,18 @@ void CMainWindow::saveImage(BOOL overwrite)
|
|||
{
|
||||
canvasWindow.finishDrawing();
|
||||
|
||||
if (isAFile && overwrite)
|
||||
if (g_isAFile && overwrite)
|
||||
{
|
||||
imageModel.SaveImage(filepathname);
|
||||
imageModel.SaveImage(g_szFileName);
|
||||
}
|
||||
else if (GetSaveFileName(filepathname, _countof(filepathname)))
|
||||
else if (GetSaveFileName(g_szFileName, _countof(g_szFileName)))
|
||||
{
|
||||
imageModel.SaveImage(filepathname);
|
||||
imageModel.SaveImage(g_szFileName);
|
||||
|
||||
CString strTitle;
|
||||
strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname));
|
||||
strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName));
|
||||
SetWindowText(strTitle);
|
||||
isAFile = TRUE;
|
||||
g_isAFile = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,13 +168,13 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window)
|
|||
{
|
||||
BOOL shouldEnlarge = TRUE;
|
||||
|
||||
if (askBeforeEnlarging)
|
||||
if (g_askBeforeEnlarging)
|
||||
{
|
||||
TCHAR programname[20];
|
||||
TCHAR shouldEnlargePromptText[100];
|
||||
|
||||
LoadString(hProgInstance, IDS_PROGRAMNAME, programname, _countof(programname));
|
||||
LoadString(hProgInstance, IDS_ENLARGEPROMPTTEXT, shouldEnlargePromptText, _countof(shouldEnlargePromptText));
|
||||
LoadString(g_hinstExe, IDS_PROGRAMNAME, programname, _countof(programname));
|
||||
LoadString(g_hinstExe, IDS_ENLARGEPROMPTTEXT, shouldEnlargePromptText, _countof(shouldEnlargePromptText));
|
||||
|
||||
switch (MessageBox(shouldEnlargePromptText, programname, MB_YESNOCANCEL | MB_ICONQUESTION))
|
||||
{
|
||||
|
@ -276,14 +276,14 @@ LRESULT CMainWindow::OnDropFiles(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
|
|||
LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
// Loading and setting the window menu from resource
|
||||
m_hMenu = ::LoadMenu(hProgInstance, MAKEINTRESOURCE(ID_MENU));
|
||||
m_hMenu = ::LoadMenu(g_hinstExe, MAKEINTRESOURCE(ID_MENU));
|
||||
SetMenu(m_hMenu);
|
||||
|
||||
// Create the status bar
|
||||
DWORD style = SBARS_SIZEGRIP | WS_CHILD | (registrySettings.ShowStatusBar ? WS_VISIBLE : 0);
|
||||
hStatusBar = ::CreateWindowEx(0, STATUSCLASSNAME, NULL, style, 0, 0, 0, 0, m_hWnd,
|
||||
NULL, hProgInstance, NULL);
|
||||
::SendMessage(hStatusBar, SB_SETMINHEIGHT, 21, 0);
|
||||
g_hStatusBar = ::CreateWindowEx(0, STATUSCLASSNAME, NULL, style, 0, 0, 0, 0, m_hWnd,
|
||||
NULL, g_hinstExe, NULL);
|
||||
::SendMessage(g_hStatusBar, SB_SETMINHEIGHT, 21, 0);
|
||||
|
||||
// Create the tool box
|
||||
toolBoxContainer.DoCreate(m_hWnd);
|
||||
|
@ -305,8 +305,8 @@ LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa
|
|||
}
|
||||
|
||||
// Set icon
|
||||
SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ BOOL CMainWindow::ConfirmSave()
|
|||
strProgramName.LoadString(IDS_PROGRAMNAME);
|
||||
|
||||
CString strSavePromptText;
|
||||
strSavePromptText.Format(IDS_SAVEPROMPTTEXT, PathFindFileName(filepathname));
|
||||
strSavePromptText.Format(IDS_SAVEPROMPTTEXT, PathFindFileName(g_szFileName));
|
||||
|
||||
switch (MessageBox(strSavePromptText, strProgramName, MB_YESNOCANCEL | MB_ICONQUESTION))
|
||||
{
|
||||
|
@ -374,7 +374,7 @@ LRESULT CMainWindow::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHan
|
|||
|
||||
void CMainWindow::ProcessFileMenu(HMENU hPopupMenu)
|
||||
{
|
||||
LPCTSTR dotext = PathFindExtensionW(filepathname);
|
||||
LPCTSTR dotext = PathFindExtensionW(g_szFileName);
|
||||
BOOL isBMP = FALSE;
|
||||
if (_tcsicmp(dotext, _T(".bmp")) == 0 ||
|
||||
_tcsicmp(dotext, _T(".dib")) == 0 ||
|
||||
|
@ -383,9 +383,9 @@ void CMainWindow::ProcessFileMenu(HMENU hPopupMenu)
|
|||
isBMP = TRUE;
|
||||
}
|
||||
|
||||
EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERPLANE, ENABLED_IF(isAFile && isBMP));
|
||||
EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERCENTERED, ENABLED_IF(isAFile && isBMP));
|
||||
EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERSTRETCHED, ENABLED_IF(isAFile && isBMP));
|
||||
EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERPLANE, ENABLED_IF(g_isAFile && isBMP));
|
||||
EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERCENTERED, ENABLED_IF(g_isAFile && isBMP));
|
||||
EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERSTRETCHED, ENABLED_IF(g_isAFile && isBMP));
|
||||
|
||||
for (INT iItem = 0; iItem < MAX_RECENT_FILES; ++iItem)
|
||||
RemoveMenu(hPopupMenu, IDM_FILE1 + iItem, MF_BYCOMMAND);
|
||||
|
@ -445,11 +445,11 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
|
|||
case 2: /* View menu */
|
||||
CheckMenuItem(menu, IDM_VIEWTOOLBOX, CHECKED_IF(::IsWindowVisible(toolBoxContainer)));
|
||||
CheckMenuItem(menu, IDM_VIEWCOLORPALETTE, CHECKED_IF(::IsWindowVisible(paletteWindow)));
|
||||
CheckMenuItem(menu, IDM_VIEWSTATUSBAR, CHECKED_IF(::IsWindowVisible(hStatusBar)));
|
||||
CheckMenuItem(menu, IDM_VIEWSTATUSBAR, CHECKED_IF(::IsWindowVisible(g_hStatusBar)));
|
||||
CheckMenuItem(menu, IDM_FORMATICONBAR, CHECKED_IF(::IsWindowVisible(fontsDialog)));
|
||||
EnableMenuItem(menu, IDM_FORMATICONBAR, ENABLED_IF(toolsModel.GetActiveTool() == TOOL_TEXT));
|
||||
|
||||
CheckMenuItem(menu, IDM_VIEWSHOWGRID, CHECKED_IF(showGrid));
|
||||
CheckMenuItem(menu, IDM_VIEWSHOWGRID, CHECKED_IF(g_showGrid));
|
||||
CheckMenuItem(menu, IDM_VIEWSHOWMINIATURE, CHECKED_IF(registrySettings.ShowThumbnail));
|
||||
break;
|
||||
case 3: /* Image menu */
|
||||
|
@ -474,10 +474,10 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
|
|||
LRESULT CMainWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
int test[] = { LOWORD(lParam) - 260, LOWORD(lParam) - 140, LOWORD(lParam) - 20 };
|
||||
if (::IsWindow(hStatusBar))
|
||||
if (::IsWindow(g_hStatusBar))
|
||||
{
|
||||
::SendMessage(hStatusBar, WM_SIZE, 0, 0);
|
||||
::SendMessage(hStatusBar, SB_SETPARTS, 3, (LPARAM)&test);
|
||||
::SendMessage(g_hStatusBar, WM_SIZE, 0, 0);
|
||||
::SendMessage(g_hStatusBar, SB_SETPARTS, 3, (LPARAM)&test);
|
||||
}
|
||||
alignChildrenToMainWindow();
|
||||
return 0;
|
||||
|
@ -508,9 +508,11 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
}
|
||||
else if (selectionModel.m_bShow)
|
||||
{
|
||||
selectionModel.Landing();
|
||||
selectionModel.m_bShow = FALSE;
|
||||
imageModel.NotifyImageChanged();
|
||||
selectionModel.HideSelection();
|
||||
}
|
||||
else
|
||||
{
|
||||
canvasWindow.cancelDrawing();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -551,11 +553,11 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
{
|
||||
case IDM_HELPINFO:
|
||||
{
|
||||
HICON paintIcon = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON));
|
||||
HICON paintIcon = LoadIcon(g_hinstExe, MAKEINTRESOURCE(IDI_APPICON));
|
||||
TCHAR infotitle[100];
|
||||
TCHAR infotext[200];
|
||||
LoadString(hProgInstance, IDS_INFOTITLE, infotitle, _countof(infotitle));
|
||||
LoadString(hProgInstance, IDS_INFOTEXT, infotext, _countof(infotext));
|
||||
LoadString(g_hinstExe, IDS_INFOTITLE, infotitle, _countof(infotitle));
|
||||
LoadString(g_hinstExe, IDS_INFOTEXT, infotext, _countof(infotext));
|
||||
ShellAbout(m_hWnd, infotitle, infotext, paintIcon);
|
||||
DeleteObject(paintIcon);
|
||||
break;
|
||||
|
@ -620,13 +622,13 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
GlobalFree(pd.hDevNames);
|
||||
break;
|
||||
case IDM_FILEASWALLPAPERPLANE:
|
||||
RegistrySettings::SetWallpaper(filepathname, RegistrySettings::TILED);
|
||||
RegistrySettings::SetWallpaper(g_szFileName, RegistrySettings::TILED);
|
||||
break;
|
||||
case IDM_FILEASWALLPAPERCENTERED:
|
||||
RegistrySettings::SetWallpaper(filepathname, RegistrySettings::CENTERED);
|
||||
RegistrySettings::SetWallpaper(g_szFileName, RegistrySettings::CENTERED);
|
||||
break;
|
||||
case IDM_FILEASWALLPAPERSTRETCHED:
|
||||
RegistrySettings::SetWallpaper(filepathname, RegistrySettings::STRETCHED);
|
||||
RegistrySettings::SetWallpaper(g_szFileName, RegistrySettings::STRETCHED);
|
||||
break;
|
||||
case IDM_FILE1:
|
||||
case IDM_FILE2:
|
||||
|
@ -640,7 +642,10 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
}
|
||||
case IDM_EDITUNDO:
|
||||
if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
|
||||
{
|
||||
textEditWindow.PostMessage(WM_UNDO, 0, 0);
|
||||
break;
|
||||
}
|
||||
if (selectionModel.m_bShow)
|
||||
{
|
||||
if (toolsModel.GetActiveTool() == TOOL_RECTSEL ||
|
||||
|
@ -668,10 +673,19 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
imageModel.Redo();
|
||||
break;
|
||||
case IDM_EDITCOPY:
|
||||
// FIXME: We should use CF_DIB in the future
|
||||
if (OpenClipboard())
|
||||
{
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_BITMAP, CopyDIBImage(selectionModel.GetBitmap()));
|
||||
if (selectionModel.m_bShow)
|
||||
{
|
||||
selectionModel.TakeOff();
|
||||
SetClipboardData(CF_BITMAP, selectionModel.CopyBitmap());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetClipboardData(CF_BITMAP, imageModel.CopyBitmap());
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
break;
|
||||
|
@ -695,7 +709,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
{
|
||||
case TOOL_FREESEL:
|
||||
case TOOL_RECTSEL:
|
||||
imageModel.DeleteSelection();
|
||||
selectionModel.DeleteSelection();
|
||||
break;
|
||||
|
||||
case TOOL_TEXT:
|
||||
|
@ -723,7 +737,11 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
{
|
||||
TCHAR szFileName[MAX_LONG_PATH] = _T("");
|
||||
if (GetSaveFileName(szFileName, _countof(szFileName)))
|
||||
SaveDIBToFile(selectionModel.GetBitmap(), szFileName, imageModel.GetDC());
|
||||
{
|
||||
HBITMAP hbm = selectionModel.CopyBitmap();
|
||||
SaveDIBToFile(hbm, szFileName, imageModel.GetDC());
|
||||
::DeleteObject(hbm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDM_EDITPASTEFROM:
|
||||
|
@ -827,8 +845,8 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
toolsModel.SetBackgroundTransparent(!toolsModel.IsBackgroundTransparent());
|
||||
break;
|
||||
case IDM_IMAGECROP:
|
||||
imageModel.PushImageForUndo(CopyDIBImage(selectionModel.GetBitmap()));
|
||||
imageModel.DeleteSelection();
|
||||
imageModel.PushImageForUndo(selectionModel.CopyBitmap());
|
||||
selectionModel.HideSelection();
|
||||
break;
|
||||
|
||||
case IDM_VIEWTOOLBOX:
|
||||
|
@ -842,8 +860,8 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
alignChildrenToMainWindow();
|
||||
break;
|
||||
case IDM_VIEWSTATUSBAR:
|
||||
registrySettings.ShowStatusBar = !::IsWindowVisible(hStatusBar);
|
||||
::ShowWindow(hStatusBar, (registrySettings.ShowStatusBar ? SW_SHOWNOACTIVATE : SW_HIDE));
|
||||
registrySettings.ShowStatusBar = !::IsWindowVisible(g_hStatusBar);
|
||||
::ShowWindow(g_hStatusBar, (registrySettings.ShowStatusBar ? SW_SHOWNOACTIVATE : SW_HIDE));
|
||||
alignChildrenToMainWindow();
|
||||
break;
|
||||
case IDM_FORMATICONBAR:
|
||||
|
@ -859,7 +877,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
}
|
||||
break;
|
||||
case IDM_VIEWSHOWGRID:
|
||||
showGrid = !showGrid;
|
||||
g_showGrid = !g_showGrid;
|
||||
canvasWindow.Invalidate(FALSE);
|
||||
break;
|
||||
case IDM_VIEWSHOWMINIATURE:
|
||||
|
|
Loading…
Reference in a new issue