[MSPAINT] Use CF_DIB instead of CF_BITMAP (#5349)

CF_BITMAP is not recommended format for copying. In fact, Win10 won't accept it.
- Use CF_DIB clipboard format instead of CF_BITMAP in copying.
- Use CF_ENHMETAFILE, CF_DIB, or CF_BITMAP in pasting.
- Add BitmapToClipboardDIB, BitmapFromClipboardDIB, and BitmapFromHEMF helper functions to dib.cpp.
- Re-enable paste by fixing the bug that is embugged in the previous commit.
- Enable Cut, Copy, Paste, and Delete on text editing box by modifying OnInitMenuPopup.
- Add IDS_CANTPASTE resource string to show message on paste failure.
CORE-18867
This commit is contained in:
Katayama Hirofumi MZ 2023-06-18 19:48:20 +09:00 committed by GitHub
parent aaa0cb6724
commit 9f56e67bc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 320 additions and 45 deletions

View file

@ -333,3 +333,135 @@ HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical)
DeleteDC(hDC2);
return hbmNew;
}
struct BITMAPINFODX : BITMAPINFO
{
RGBQUAD bmiColorsAdditional[256 - 1];
};
HGLOBAL BitmapToClipboardDIB(HBITMAP hBitmap)
{
BITMAP bm;
if (!GetObject(hBitmap, sizeof(BITMAP), &bm))
return NULL;
BITMAPINFODX bmi;
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bm.bmWidth;
bmi.bmiHeader.biHeight = bm.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = bm.bmBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = bm.bmWidthBytes * bm.bmHeight;
INT cColors;
if (bm.bmBitsPixel < 16)
cColors = 1 << bm.bmBitsPixel;
else
cColors = 0;
HDC hDC = CreateCompatibleDC(NULL);
if (cColors)
{
HGDIOBJ hbmOld = SelectObject(hDC, hBitmap);
cColors = GetDIBColorTable(hDC, 0, cColors, bmi.bmiColors);
SelectObject(hDC, hbmOld);
}
DWORD cbColors = cColors * sizeof(RGBQUAD);
DWORD dwSize = sizeof(BITMAPINFOHEADER) + cbColors + bmi.bmiHeader.biSizeImage;
HGLOBAL hGlobal = GlobalAlloc(GHND | GMEM_SHARE, dwSize);
if (hGlobal)
{
LPBYTE pb = (LPBYTE)GlobalLock(hGlobal);
if (pb)
{
CopyMemory(pb, &bmi, sizeof(BITMAPINFOHEADER));
pb += sizeof(BITMAPINFOHEADER);
CopyMemory(pb, bmi.bmiColors, cbColors);
pb += cbColors;
GetDIBits(hDC, hBitmap, 0, bm.bmHeight, pb, &bmi, DIB_RGB_COLORS);
GlobalUnlock(hGlobal);
}
else
{
GlobalFree(hGlobal);
hGlobal = NULL;
}
}
DeleteDC(hDC);
return hGlobal;
}
HBITMAP BitmapFromClipboardDIB(HGLOBAL hGlobal)
{
LPBYTE pb = (LPBYTE)GlobalLock(hGlobal);
if (!pb)
return NULL;
LPBITMAPINFO pbmi = (LPBITMAPINFO)pb;
pb += pbmi->bmiHeader.biSize;
INT cColors = 0, cbColors = 0;
if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
LPBITMAPCOREINFO pbmci = (LPBITMAPCOREINFO)pbmi;
WORD BitCount = pbmci->bmciHeader.bcBitCount;
if (BitCount < 16)
{
cColors = (1 << BitCount);
cbColors = cColors * sizeof(RGBTRIPLE);
pb += cbColors;
}
}
else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
{
WORD BitCount = pbmi->bmiHeader.biBitCount;
if (BitCount < 16)
{
cColors = (1 << BitCount);
cbColors = cColors * sizeof(RGBQUAD);
pb += cbColors;
}
}
HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hBitmap = CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, NULL, NULL, 0);
if (hBitmap)
{
SetDIBits(hDC, hBitmap, 0, labs(pbmi->bmiHeader.biHeight), pb, pbmi, DIB_RGB_COLORS);
}
DeleteDC(hDC);
GlobalUnlock(hGlobal);
return hBitmap;
}
HBITMAP BitmapFromHEMF(HENHMETAFILE hEMF)
{
ENHMETAHEADER header;
if (!GetEnhMetaFileHeader(hEMF, sizeof(header), &header))
return NULL;
CRect rc = *(LPRECT)&header.rclBounds;
INT cx = rc.Width(), cy = rc.Height();
HBITMAP hbm = CreateColorDIB(cx, cy, RGB(255, 255, 255));
if (!hbm)
return NULL;
HDC hDC = CreateCompatibleDC(NULL);
HGDIOBJ hbmOld = SelectObject(hDC, hbm);
PlayEnhMetaFile(hDC, hEMF, &rc);
SelectObject(hDC, hbmOld);
DeleteDC(hDC);
return hbm;
}

View file

@ -36,3 +36,7 @@ HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical);
float PpcmFromDpi(float dpi);
#define ROUND(x) (INT)((x) + 0.5)
HGLOBAL BitmapToClipboardDIB(HBITMAP hBitmap);
HBITMAP BitmapFromClipboardDIB(HGLOBAL hGlobal);
HBITMAP BitmapFromHEMF(HENHMETAFILE hEMF);

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Подчертан"
IDS_VERTICAL "Вертикален"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d dots per inch"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d dots per inch"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -244,4 +244,5 @@ BEGIN
IDS_UNDERLINE "Subrayado"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -234,4 +234,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -234,4 +234,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -237,4 +237,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -234,4 +234,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "下線"
IDS_VERTICAL "縦書き"
IDS_PRINTRES "%d x %d ピクセル/cm"
IDS_CANTPASTE "申し訳ありませんが、このデータを貼り付けできません。データ形式が間違っているか、対応していません。"
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -243,4 +243,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Sublinhado"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -243,4 +243,5 @@ BEGIN
IDS_UNDERLINE "Subliniat"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -234,4 +234,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -243,4 +243,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -234,4 +234,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Altı Çizgili"
IDS_VERTICAL "Düşey"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "Underline"
IDS_VERTICAL "Vertical"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -244,4 +244,5 @@ BEGIN
IDS_UNDERLINE "下划线"
IDS_VERTICAL "垂直"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "底線"
IDS_VERTICAL "垂直"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -242,4 +242,5 @@ BEGIN
IDS_UNDERLINE "底線"
IDS_VERTICAL "垂直"
IDS_PRINTRES "%d x %d pixel/cm"
IDS_CANTPASTE "Sorry, this application cannot paste this data. The data format is either incorrect or not supported."
END

View file

@ -547,7 +547,6 @@ struct TextTool : ToolBase
// 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);
}
@ -568,12 +567,11 @@ struct TextTool : ToolBase
BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow);
if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0)
{
imageModel.PushImageForUndo();
draw(m_hdc);
if (selectionModel.m_rc.IsRectEmpty())
if (::IsRectEmpty(&selectionModel.m_rc))
{
textEditWindow.ShowWindow(SW_HIDE);
textEditWindow.SetWindowText(NULL);
quit();
return;
}
}
@ -613,6 +611,7 @@ struct TextTool : ToolBase
void OnFinishDraw() override
{
imageModel.PushImageForUndo();
draw(m_hdc);
quit();
ToolBase::OnFinishDraw();

View file

@ -219,3 +219,4 @@
#define IDS_UNDERLINE 937
#define IDS_VERTICAL 938
#define IDS_PRINTRES 939
#define IDS_CANTPASTE 940

View file

@ -205,8 +205,12 @@ void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
m_rc.left = x;
m_rc.top = y;
m_rc.right = m_rc.left + GetDIBWidth(hBm);
m_rc.bottom = m_rc.top + GetDIBHeight(hBm);
m_rc.right = x + GetDIBWidth(hBm);
m_rc.bottom = y + GetDIBHeight(hBm);
// If m_rc and m_rcOld were same, the image cannot be pasted to the canvas.
// See also SelectionModel::Landing
::SetRect(&m_rcOld, -2, -2, -1, -1); // Outside of image
ClearMask();
}

View file

@ -410,15 +410,9 @@ void CTextEditWindow::Reposition()
CRect rcImage;
canvasWindow.GetImageRect(rcImage);
if (rc.bottom > rcImage.bottom)
::OffsetRect(&rc, 0, rcImage.Height());
if (rc.right > rcImage.right)
::OffsetRect(&rc, rcImage.Width(), 0);
// FIXME: Smartly restrict the position and size by using WM_WINDOWPOSCHANGING
if (rc.left < 0)
::OffsetRect(&rc, -rc.left, 0);
if (rc.top < 0)
::OffsetRect(&rc, 0, -rc.top);
@ -433,3 +427,24 @@ LRESULT CTextEditWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, B
{
return ::SendMessage(GetParent(), nMsg, wParam, lParam);
}
LRESULT CTextEditWindow::OnCut(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT ret = DefWindowProc(nMsg, wParam, lParam);
Invalidate(TRUE); // Redraw
return ret;
}
LRESULT CTextEditWindow::OnPaste(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT ret = DefWindowProc(nMsg, wParam, lParam);
FixEditPos(NULL);
return ret;
}
LRESULT CTextEditWindow::OnClear(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT ret = DefWindowProc(nMsg, wParam, lParam);
Invalidate(TRUE); // Redraw
return ret;
}

View file

@ -45,6 +45,9 @@ public:
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown);
MESSAGE_HANDLER(EM_SETSEL, OnSetSel);
MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel);
MESSAGE_HANDLER(WM_CUT, OnCut);
MESSAGE_HANDLER(WM_PASTE, OnPaste);
MESSAGE_HANDLER(WM_CLEAR, OnClear);
END_MSG_MAP()
LRESULT OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
@ -66,6 +69,9 @@ public:
LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSetSel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCut(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnPaste(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnClear(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
protected:
HWND m_hwndParent;

View file

@ -200,9 +200,7 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window)
}
}
HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, TOOLBARCLASSNAME, NULL);
SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELPARAM(TRUE, 0));
toolBoxContainer.SendMessage(WM_COMMAND, ID_RECTSEL);
toolsModel.SetActiveTool(TOOL_RECTSEL);
imageModel.PushImageForUndo();
selectionModel.InsertFromHBITMAP(bitmap, 0, 0);
@ -424,6 +422,10 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
BOOL trueSelection =
(selectionModel.m_bShow &&
((toolsModel.GetActiveTool() == TOOL_FREESEL) || (toolsModel.GetActiveTool() == TOOL_RECTSEL)));
BOOL textShown = (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow));
DWORD dwStart, dwEnd;
textEditWindow.SendMessage(EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
BOOL hasTextSel = (dwStart < dwEnd);
switch (lParam)
{
@ -431,16 +433,20 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
ProcessFileMenu((HMENU)wParam);
break;
case 1: /* Edit menu */
EnableMenuItem(menu, IDM_EDITUNDO, ENABLED_IF(imageModel.CanUndo()));
EnableMenuItem(menu, IDM_EDITREDO, ENABLED_IF(imageModel.CanRedo()));
EnableMenuItem(menu, IDM_EDITCUT, ENABLED_IF(trueSelection));
EnableMenuItem(menu, IDM_EDITCOPY, ENABLED_IF(trueSelection));
EnableMenuItem(menu, IDM_EDITDELETESELECTION, ENABLED_IF(trueSelection));
EnableMenuItem(menu, IDM_EDITUNDO,
ENABLED_IF(textShown ? textEditWindow.SendMessage(EM_CANUNDO) : imageModel.CanUndo()));
EnableMenuItem(menu, IDM_EDITREDO, ENABLED_IF(textShown ? FALSE : imageModel.CanRedo()));
EnableMenuItem(menu, IDM_EDITCUT, ENABLED_IF(textShown ? hasTextSel : trueSelection));
EnableMenuItem(menu, IDM_EDITCOPY, ENABLED_IF(textShown ? hasTextSel : trueSelection));
EnableMenuItem(menu, IDM_EDITDELETESELECTION,
ENABLED_IF(textShown ? hasTextSel : trueSelection));
EnableMenuItem(menu, IDM_EDITINVERTSELECTION, ENABLED_IF(trueSelection));
EnableMenuItem(menu, IDM_EDITCOPYTO, ENABLED_IF(trueSelection));
OpenClipboard();
EnableMenuItem(menu, IDM_EDITPASTE, ENABLED_IF(IsClipboardFormatAvailable(CF_BITMAP)));
CloseClipboard();
EnableMenuItem(menu, IDM_EDITPASTE,
ENABLED_IF(textShown ? ::IsClipboardFormatAvailable(CF_UNICODETEXT) :
::IsClipboardFormatAvailable(CF_ENHMETAFILE) ||
::IsClipboardFormatAvailable(CF_DIB) ||
::IsClipboardFormatAvailable(CF_BITMAP)));
break;
case 2: /* View menu */
CheckMenuItem(menu, IDM_VIEWTOOLBOX, CHECKED_IF(::IsWindowVisible(toolBoxContainer)));
@ -503,7 +509,7 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
if (canvasWindow.m_hWnd == hwndCapture ||
fullscreenWindow.m_hWnd == hwndCapture)
{
SendMessage(hwndCapture, nMsg, wParam, lParam);
::SendMessage(hwndCapture, nMsg, wParam, lParam);
}
}
else if (selectionModel.m_bShow)
@ -528,6 +534,8 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
case VK_DOWN:
canvasWindow.MoveSelection(0, +1);
break;
default:
break;
}
return 0;
}
@ -549,6 +557,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
return 0;
}
BOOL textShown = (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow));
switch (LOWORD(wParam))
{
case IDM_HELPINFO:
@ -641,7 +650,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
break;
}
case IDM_EDITUNDO:
if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
if (textShown)
{
textEditWindow.PostMessage(WM_UNDO, 0, 0);
break;
@ -663,8 +672,11 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
imageModel.Undo();
break;
case IDM_EDITREDO:
if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
if (textShown)
{
// There is no "WM_REDO". Do nothing
break;
}
if (ToolBase::pointSP != 0) // drawing something?
{
canvasWindow.finishDrawing();
@ -673,38 +685,110 @@ 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())
if (textShown)
{
EmptyClipboard();
if (selectionModel.m_bShow)
{
selectionModel.TakeOff();
SetClipboardData(CF_BITMAP, selectionModel.CopyBitmap());
}
else
{
SetClipboardData(CF_BITMAP, imageModel.CopyBitmap());
}
CloseClipboard();
textEditWindow.SendMessage(WM_COPY);
break;
}
if (!selectionModel.m_bShow || !OpenClipboard())
break;
EmptyClipboard();
selectionModel.TakeOff();
{
HBITMAP hbm = selectionModel.CopyBitmap();
if (hbm)
{
HGLOBAL hGlobal = BitmapToClipboardDIB(hbm);
if (hGlobal)
::SetClipboardData(CF_DIB, hGlobal);
::DeleteObject(hbm);
}
}
CloseClipboard();
break;
case IDM_EDITCUT:
if (textShown)
{
textEditWindow.SendMessage(WM_CUT);
break;
}
/* Copy */
SendMessage(WM_COMMAND, IDM_EDITCOPY, 0);
/* Delete selection */
SendMessage(WM_COMMAND, IDM_EDITDELETESELECTION, 0);
break;
case IDM_EDITPASTE:
OpenClipboard();
if (IsClipboardFormatAvailable(CF_BITMAP))
if (textShown)
{
InsertSelectionFromHBITMAP((HBITMAP) GetClipboardData(CF_BITMAP), m_hWnd);
textEditWindow.SendMessage(WM_PASTE);
break;
}
if (!OpenClipboard())
break;
// In many cases, CF_ENHMETAFILE provides a better image than CF_DIB
if (::IsClipboardFormatAvailable(CF_ENHMETAFILE))
{
HENHMETAFILE hEMF = (HENHMETAFILE)::GetClipboardData(CF_ENHMETAFILE);
if (hEMF)
{
HBITMAP hbm = BitmapFromHEMF(hEMF);
::DeleteEnhMetaFile(hEMF);
if (hbm)
{
InsertSelectionFromHBITMAP(hbm, m_hWnd);
CloseClipboard();
break;
}
}
}
// In many cases, CF_DIB provides a better image than CF_BITMAP
if (::IsClipboardFormatAvailable(CF_DIB))
{
HBITMAP hbm = BitmapFromClipboardDIB(::GetClipboardData(CF_DIB));
if (hbm)
{
InsertSelectionFromHBITMAP(hbm, m_hWnd);
CloseClipboard();
break;
}
}
// The last resort
if (::IsClipboardFormatAvailable(CF_BITMAP))
{
HBITMAP hbm = (HBITMAP)::GetClipboardData(CF_BITMAP);
if (hbm)
{
InsertSelectionFromHBITMAP(hbm, m_hWnd);
CloseClipboard();
break;
}
}
// Failed to paste
{
CString strText, strTitle;
strText.LoadString(IDS_CANTPASTE);
strTitle.LoadString(IDS_PROGRAMNAME);
MessageBox(strText, strTitle, MB_ICONINFORMATION);
}
CloseClipboard();
break;
case IDM_EDITDELETESELECTION:
{
if (textShown)
{
textEditWindow.SendMessage(WM_CLEAR);
break;
}
switch (toolsModel.GetActiveTool())
{
case TOOL_FREESEL:
@ -722,7 +806,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
}
case IDM_EDITSELECTALL:
{
if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
if (textShown)
{
textEditWindow.SendMessage(EM_SETSEL, 0, -1);
break;