Browse Source

修复阴影导致的崩溃

张洋 6 days ago
parent
commit
1dc49f5a98

+ 36 - 2
DuiLib/Utils/UIShadow.cpp

@@ -496,6 +496,13 @@ void CShadowUI::MakeShadow(UINT32 *pShadBits, HWND hParent, RECT *rcParent)
 	int nAnchors = max(szParent.cy, szShadow.cy);	// # of anchor points pares
 	int (*ptAnchors)[2] = new int[nAnchors + 2][2];
 	int (*ptAnchorsOri)[2] = new int[szParent.cy][2];	// anchor points, will not modify during erosion
+	// [2026-10-09] R55: zero both arrays. The scan loop below only writes the rows it
+	// can resolve; a row with no pixel inside hParentRgn leaves its [1] / [0] pair
+	// untouched (see the "Start point not found" branch further down). Memory from
+	// new[] is not zeroed, so those slots used to carry arbitrary values which then
+	// leaked into the fill loops below as loop bounds.
+	::ZeroMemory(ptAnchors, sizeof(int) * 2 * (nAnchors + 2));
+	::ZeroMemory(ptAnchorsOri, sizeof(int) * 2 * szParent.cy);
 	ptAnchors[0][0] = szParent.cx;
 	ptAnchors[0][1] = 0;
 	ptAnchors[nAnchors + 1][0] = szParent.cx;
@@ -522,9 +529,16 @@ void CShadowUI::MakeShadow(UINT32 *pShadBits, HWND hParent, RECT *rcParent)
 		}
 		// Start point not found
 		if(j >= szParent.cx) {
+			// [2026-10-09] R55: the 2nd and 3rd line used to duplicate the 1st and 2nd,
+			// so ptAnchors[i + 1][1] and ptAnchorsOri[i][0] were never written at all.
+			// Empty rows are not theoretical here: a rounded window region built by
+			// CreateRoundRectRgn has NO pixel on its very last row, so this branch runs
+			// on every shadow repaint of a roundcorner window. The uninitialised pair
+			// then acted as the bound of the clCenter fill below, which ran past the
+			// end of the DIB section (crash: access violation on write).
 			ptAnchors[i + 1][0] = szParent.cx;
-			ptAnchorsOri[i][1] = 0;
-			ptAnchors[i + 1][0] = szParent.cx;
+			ptAnchorsOri[i][0] = szParent.cx;
+			ptAnchors[i + 1][1] = 0;
 			ptAnchorsOri[i][1] = 0;
 		}
 		else {
@@ -567,6 +581,26 @@ void CShadowUI::MakeShadow(UINT32 *pShadBits, HWND hParent, RECT *rcParent)
 
 	// morphologic dilation
 	ptAnchors += (m_nSize < 0 ? -m_nSize : 0) + 1;	// now coordinates in ptAnchors are same as in shadow window
+	// [2026-10-09] R55: last line of defence. Both anchor arrays are consumed directly
+	// as x bounds of the clCenter / kernel loops below, so clamp every span into the
+	// DIB row before it is used. Healthy values already live in [0, szShadow.cx], so
+	// this is a no-op on every correct path; it only bites when something still slips
+	// through, and it turns "write past the end of a 620x544 DIB" into "write nothing".
+	// The +1 shift above maps index 0..nAnchorCnt onto the original 1..nAnchorCnt+1
+	// slots, which is exactly the index range both loops touch.
+	const int nAnchorCnt = nAnchors - (m_nSize < 0 ? -m_nSize : 0);
+	for(int i = 0; i <= nAnchorCnt; i++) {
+		if(ptAnchors[i][0] < 0) ptAnchors[i][0] = 0;
+		else if(ptAnchors[i][0] > szShadow.cx) ptAnchors[i][0] = szShadow.cx;
+		if(ptAnchors[i][1] < 0) ptAnchors[i][1] = 0;
+		else if(ptAnchors[i][1] > szShadow.cx) ptAnchors[i][1] = szShadow.cx;
+	}
+	for(int i = 0; i < szParent.cy; i++) {
+		if(ptAnchorsOri[i][0] < 0) ptAnchorsOri[i][0] = 0;
+		else if(ptAnchorsOri[i][0] > szShadow.cx) ptAnchorsOri[i][0] = szShadow.cx;
+		if(ptAnchorsOri[i][1] < 0) ptAnchorsOri[i][1] = 0;
+		else if(ptAnchorsOri[i][1] > szShadow.cx) ptAnchorsOri[i][1] = szShadow.cx;
+	}
 	// Generate the kernel
 	int nKernelSize = m_nSize > m_nSharpness ? m_nSize : m_nSharpness;
 	int nCenterSize = m_nSize > m_nSharpness ? (m_nSize - m_nSharpness) : 0;

BIN
bin/Win32/Release/zhipuzi_pos_windows/dump/2026-09-26-18-07-22.dmp


BIN
bin/Win32/Release/zhipuzi_pos_windows/dump/2026-10-09-22-38-18.dmp