mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 15:51:49 +00:00
[MSPAINT] Improve behaviour on memory shortage (#7780)
Improve UX on memory shortage. JIRA issue: CORE-20020 - Clear history on memory shortage. - Improve CCanvasWindow::OnPaint on memory shortage. - Add null check in CCanvasWindow::DoDraw. - Retire using of cache in CCanvasWindow.
This commit is contained in:
parent
c930c8c464
commit
9563c07146
5 changed files with 47 additions and 18 deletions
|
@ -16,16 +16,11 @@ CCanvasWindow::CCanvasWindow()
|
|||
, m_hitCanvasSizeBox(HIT_NONE)
|
||||
, m_ptOrig { -1, -1 }
|
||||
{
|
||||
m_ahbmCached[0] = m_ahbmCached[1] = NULL;
|
||||
m_rcResizing.SetRectEmpty();
|
||||
}
|
||||
|
||||
CCanvasWindow::~CCanvasWindow()
|
||||
{
|
||||
if (m_ahbmCached[0])
|
||||
::DeleteObject(m_ahbmCached[0]);
|
||||
if (m_ahbmCached[1])
|
||||
::DeleteObject(m_ahbmCached[1]);
|
||||
}
|
||||
|
||||
RECT CCanvasWindow::GetBaseRect()
|
||||
|
@ -119,16 +114,30 @@ VOID CCanvasWindow::zoomTo(INT newZoom, LONG left, LONG top)
|
|||
Invalidate(TRUE);
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
|
||||
BOOL CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
|
||||
{
|
||||
// This is the target area we have to draw on
|
||||
CRect rcCanvasDraw;
|
||||
rcCanvasDraw.IntersectRect(&rcClient, &rcPaint);
|
||||
|
||||
// Calculate image size
|
||||
CRect rcImage;
|
||||
GetImageRect(rcImage);
|
||||
SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
|
||||
|
||||
// We use a memory bitmap to reduce flickering
|
||||
HBITMAP hbmCache1 = CreateDIBWithProperties(rcClient.right, rcClient.bottom);
|
||||
if (!hbmCache1)
|
||||
return FALSE; // Out of memory
|
||||
HBITMAP hbmCache2 = CreateDIBWithProperties(sizeImage.cx, sizeImage.cy);
|
||||
if (!hbmCache2)
|
||||
{
|
||||
::DeleteObject(hbmCache1);
|
||||
return FALSE; // Out of memory
|
||||
}
|
||||
|
||||
HDC hdcMem0 = ::CreateCompatibleDC(hDC);
|
||||
m_ahbmCached[0] = CachedBufferDIB(m_ahbmCached[0], rcClient.right, rcClient.bottom);
|
||||
HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, m_ahbmCached[0]);
|
||||
HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, hbmCache1);
|
||||
|
||||
// Fill the background on hdcMem0
|
||||
::FillRect(hdcMem0, &rcCanvasDraw, (HBRUSH)(COLOR_APPWORKSPACE + 1));
|
||||
|
@ -138,11 +147,6 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
|
|||
if (!selectionModel.m_bShow && !::IsWindowVisible(textEditWindow))
|
||||
drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcCanvasDraw);
|
||||
|
||||
// Calculate image size
|
||||
CRect rcImage;
|
||||
GetImageRect(rcImage);
|
||||
SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
|
||||
|
||||
// Calculate the target area on the image
|
||||
CRect rcImageDraw = rcCanvasDraw;
|
||||
CanvasToImage(rcImageDraw);
|
||||
|
@ -154,8 +158,7 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
|
|||
|
||||
// hdcMem1 <-- imageModel
|
||||
HDC hdcMem1 = ::CreateCompatibleDC(hDC);
|
||||
m_ahbmCached[1] = CachedBufferDIB(m_ahbmCached[1], sizeImage.cx, sizeImage.cy);
|
||||
HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, m_ahbmCached[1]);
|
||||
HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, hbmCache2);
|
||||
::BitBlt(hdcMem1, rcImageDraw.left, rcImageDraw.top, rcImageDraw.Width(), rcImageDraw.Height(),
|
||||
imageModel.GetDC(), rcImageDraw.left, rcImageDraw.top, SRCCOPY);
|
||||
|
||||
|
@ -208,6 +211,10 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
|
|||
// Clean up hdcMem0
|
||||
::SelectObject(hdcMem0, hbm0Old);
|
||||
::DeleteDC(hdcMem0);
|
||||
::DeleteObject(hbmCache2);
|
||||
::DeleteObject(hbmCache1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID CCanvasWindow::updateScrollRange()
|
||||
|
@ -691,9 +698,22 @@ LRESULT CCanvasWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
RECT rcClient;
|
||||
GetClientRect(&rcClient);
|
||||
|
||||
static BOOL s_bShowedOutOfMemory = FALSE; // Don't show "Out Of Memory" message multiple time
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
HDC hDC = BeginPaint(&ps);
|
||||
DoDraw(hDC, rcClient, ps.rcPaint);
|
||||
|
||||
if (DoDraw(hDC, rcClient, ps.rcPaint))
|
||||
{
|
||||
s_bShowedOutOfMemory = FALSE;
|
||||
}
|
||||
else if (!s_bShowedOutOfMemory)
|
||||
{
|
||||
ShowOutOfMemory();
|
||||
s_bShowedOutOfMemory = TRUE;
|
||||
imageModel.ClearHistory(); // Reduce memory usage
|
||||
}
|
||||
|
||||
EndPaint(&ps);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -57,12 +57,11 @@ public:
|
|||
protected:
|
||||
HITTEST m_hitCanvasSizeBox;
|
||||
POINT m_ptOrig; // The origin of drag start
|
||||
HBITMAP m_ahbmCached[2]; // The cached buffer bitmaps
|
||||
CRect m_rcResizing; // Resizing rectagle
|
||||
|
||||
HITTEST CanvasHitTest(POINT pt);
|
||||
RECT GetBaseRect();
|
||||
VOID DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint);
|
||||
BOOL DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint);
|
||||
VOID OnHVScroll(WPARAM wParam, INT fnBar);
|
||||
|
||||
LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
|
|
|
@ -230,6 +230,7 @@ HBITMAP InitializeImage(LPCWSTR name, LPWIN32_FIND_DATAW pFound, BOOL isFile)
|
|||
if (hBitmap == NULL)
|
||||
{
|
||||
ShowOutOfMemory();
|
||||
imageModel.ClearHistory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ void ImageModel::PushImageForUndo()
|
|||
if (hbm == NULL)
|
||||
{
|
||||
ShowOutOfMemory();
|
||||
ClearHistory();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -143,6 +144,7 @@ void ImageModel::PushImageForUndo(HBITMAP hbm)
|
|||
if (hbm == NULL)
|
||||
{
|
||||
ShowOutOfMemory();
|
||||
ClearHistory();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -201,6 +203,7 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
|
|||
if (!hbmNew)
|
||||
{
|
||||
ShowOutOfMemory();
|
||||
ClearHistory();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -957,9 +957,14 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
HBITMAP hbmCopy = selectionModel.GetSelectionContents();
|
||||
HGLOBAL hGlobal = BitmapToClipboardDIB(hbmCopy);
|
||||
if (hGlobal)
|
||||
{
|
||||
::SetClipboardData(CF_DIB, hGlobal);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowOutOfMemory();
|
||||
imageModel.ClearHistory();
|
||||
}
|
||||
::DeleteObject(hbmCopy);
|
||||
}
|
||||
|
||||
|
@ -1093,6 +1098,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
|
|||
if (!hbmSelection)
|
||||
{
|
||||
ShowOutOfMemory();
|
||||
imageModel.ClearHistory();
|
||||
break;
|
||||
}
|
||||
SaveDIBToFile(hbmSelection, szFileName, FALSE);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue