mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[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:
parent
aaa0cb6724
commit
9f56e67bc2
38 changed files with 320 additions and 45 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -242,4 +242,5 @@ BEGIN
|
|||
IDS_UNDERLINE "下線"
|
||||
IDS_VERTICAL "縦書き"
|
||||
IDS_PRINTRES "%d x %d ピクセル/cm"
|
||||
IDS_CANTPASTE "申し訳ありませんが、このデータを貼り付けできません。データ形式が間違っているか、対応していません。"
|
||||
END
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -219,3 +219,4 @@
|
|||
#define IDS_UNDERLINE 937
|
||||
#define IDS_VERTICAL 938
|
||||
#define IDS_PRINTRES 939
|
||||
#define IDS_CANTPASTE 940
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue