Skip to content

Commit 9563c07

Browse files
authored
[MSPAINT] Improve behaviour on memory shortage (reactos#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.
1 parent c930c8c commit 9563c07

File tree

5 files changed

+47
-18
lines changed

5 files changed

+47
-18
lines changed

base/applications/mspaint/canvas.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,11 @@ CCanvasWindow::CCanvasWindow()
1616
, m_hitCanvasSizeBox(HIT_NONE)
1717
, m_ptOrig { -1, -1 }
1818
{
19-
m_ahbmCached[0] = m_ahbmCached[1] = NULL;
2019
m_rcResizing.SetRectEmpty();
2120
}
2221

2322
CCanvasWindow::~CCanvasWindow()
2423
{
25-
if (m_ahbmCached[0])
26-
::DeleteObject(m_ahbmCached[0]);
27-
if (m_ahbmCached[1])
28-
::DeleteObject(m_ahbmCached[1]);
2924
}
3025

3126
RECT CCanvasWindow::GetBaseRect()
@@ -119,16 +114,30 @@ VOID CCanvasWindow::zoomTo(INT newZoom, LONG left, LONG top)
119114
Invalidate(TRUE);
120115
}
121116

122-
VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
117+
BOOL CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
123118
{
124119
// This is the target area we have to draw on
125120
CRect rcCanvasDraw;
126121
rcCanvasDraw.IntersectRect(&rcClient, &rcPaint);
127122

123+
// Calculate image size
124+
CRect rcImage;
125+
GetImageRect(rcImage);
126+
SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
127+
128128
// We use a memory bitmap to reduce flickering
129+
HBITMAP hbmCache1 = CreateDIBWithProperties(rcClient.right, rcClient.bottom);
130+
if (!hbmCache1)
131+
return FALSE; // Out of memory
132+
HBITMAP hbmCache2 = CreateDIBWithProperties(sizeImage.cx, sizeImage.cy);
133+
if (!hbmCache2)
134+
{
135+
::DeleteObject(hbmCache1);
136+
return FALSE; // Out of memory
137+
}
138+
129139
HDC hdcMem0 = ::CreateCompatibleDC(hDC);
130-
m_ahbmCached[0] = CachedBufferDIB(m_ahbmCached[0], rcClient.right, rcClient.bottom);
131-
HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, m_ahbmCached[0]);
140+
HGDIOBJ hbm0Old = ::SelectObject(hdcMem0, hbmCache1);
132141

133142
// Fill the background on hdcMem0
134143
::FillRect(hdcMem0, &rcCanvasDraw, (HBRUSH)(COLOR_APPWORKSPACE + 1));
@@ -138,11 +147,6 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
138147
if (!selectionModel.m_bShow && !::IsWindowVisible(textEditWindow))
139148
drawSizeBoxes(hdcMem0, &rcBase, FALSE, &rcCanvasDraw);
140149

141-
// Calculate image size
142-
CRect rcImage;
143-
GetImageRect(rcImage);
144-
SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
145-
146150
// Calculate the target area on the image
147151
CRect rcImageDraw = rcCanvasDraw;
148152
CanvasToImage(rcImageDraw);
@@ -154,8 +158,7 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
154158

155159
// hdcMem1 <-- imageModel
156160
HDC hdcMem1 = ::CreateCompatibleDC(hDC);
157-
m_ahbmCached[1] = CachedBufferDIB(m_ahbmCached[1], sizeImage.cx, sizeImage.cy);
158-
HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, m_ahbmCached[1]);
161+
HGDIOBJ hbm1Old = ::SelectObject(hdcMem1, hbmCache2);
159162
::BitBlt(hdcMem1, rcImageDraw.left, rcImageDraw.top, rcImageDraw.Width(), rcImageDraw.Height(),
160163
imageModel.GetDC(), rcImageDraw.left, rcImageDraw.top, SRCCOPY);
161164

@@ -208,6 +211,10 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
208211
// Clean up hdcMem0
209212
::SelectObject(hdcMem0, hbm0Old);
210213
::DeleteDC(hdcMem0);
214+
::DeleteObject(hbmCache2);
215+
::DeleteObject(hbmCache1);
216+
217+
return TRUE;
211218
}
212219

213220
VOID CCanvasWindow::updateScrollRange()
@@ -691,9 +698,22 @@ LRESULT CCanvasWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
691698
RECT rcClient;
692699
GetClientRect(&rcClient);
693700

701+
static BOOL s_bShowedOutOfMemory = FALSE; // Don't show "Out Of Memory" message multiple time
702+
694703
PAINTSTRUCT ps;
695704
HDC hDC = BeginPaint(&ps);
696-
DoDraw(hDC, rcClient, ps.rcPaint);
705+
706+
if (DoDraw(hDC, rcClient, ps.rcPaint))
707+
{
708+
s_bShowedOutOfMemory = FALSE;
709+
}
710+
else if (!s_bShowedOutOfMemory)
711+
{
712+
ShowOutOfMemory();
713+
s_bShowedOutOfMemory = TRUE;
714+
imageModel.ClearHistory(); // Reduce memory usage
715+
}
716+
697717
EndPaint(&ps);
698718
return 0;
699719
}

base/applications/mspaint/canvas.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,11 @@ class CCanvasWindow : public CWindowImpl<CCanvasWindow>
5757
protected:
5858
HITTEST m_hitCanvasSizeBox;
5959
POINT m_ptOrig; // The origin of drag start
60-
HBITMAP m_ahbmCached[2]; // The cached buffer bitmaps
6160
CRect m_rcResizing; // Resizing rectagle
6261

6362
HITTEST CanvasHitTest(POINT pt);
6463
RECT GetBaseRect();
65-
VOID DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint);
64+
BOOL DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint);
6665
VOID OnHVScroll(WPARAM wParam, INT fnBar);
6766

6867
LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

base/applications/mspaint/dib.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ HBITMAP InitializeImage(LPCWSTR name, LPWIN32_FIND_DATAW pFound, BOOL isFile)
230230
if (hBitmap == NULL)
231231
{
232232
ShowOutOfMemory();
233+
imageModel.ClearHistory();
233234
return NULL;
234235
}
235236

base/applications/mspaint/history.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ void ImageModel::PushImageForUndo()
130130
if (hbm == NULL)
131131
{
132132
ShowOutOfMemory();
133+
ClearHistory();
133134
return;
134135
}
135136

@@ -143,6 +144,7 @@ void ImageModel::PushImageForUndo(HBITMAP hbm)
143144
if (hbm == NULL)
144145
{
145146
ShowOutOfMemory();
147+
ClearHistory();
146148
return;
147149
}
148150

@@ -201,6 +203,7 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
201203
if (!hbmNew)
202204
{
203205
ShowOutOfMemory();
206+
ClearHistory();
204207
return;
205208
}
206209

base/applications/mspaint/main.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,9 +957,14 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
957957
HBITMAP hbmCopy = selectionModel.GetSelectionContents();
958958
HGLOBAL hGlobal = BitmapToClipboardDIB(hbmCopy);
959959
if (hGlobal)
960+
{
960961
::SetClipboardData(CF_DIB, hGlobal);
962+
}
961963
else
964+
{
962965
ShowOutOfMemory();
966+
imageModel.ClearHistory();
967+
}
963968
::DeleteObject(hbmCopy);
964969
}
965970

@@ -1093,6 +1098,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
10931098
if (!hbmSelection)
10941099
{
10951100
ShowOutOfMemory();
1101+
imageModel.ClearHistory();
10961102
break;
10971103
}
10981104
SaveDIBToFile(hbmSelection, szFileName, FALSE);

0 commit comments

Comments
 (0)