Browse Source

窗口阴影

张洋 3 weeks ago
parent
commit
8d75bdface
1 changed files with 32 additions and 0 deletions
  1. 32 0
      DuiLib/Core/UIBase.cpp

+ 32 - 0
DuiLib/Core/UIBase.cpp

@@ -696,6 +696,29 @@ INT_PTR CALLBACK CWindowWnd::__DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
         if( pManager != NULL )
         {
             pManager->AttachPaintWindow(hDlg);
+
+            // ---- [窗口阴影] 在对话框的新 HWND 上重建阴影窗口 ----
+            // 背景:CShadowUI 的阴影窗口(PerryShadowWnd)是**绑定父窗口 HWND** 的 ——
+            //   · Create() 把 (父HWND → CShadowUI*) 记进 GetShadowMap(),以该 HWND 为
+            //     owner 创建阴影窗口,并把父窗口的窗口过程换成 ParentProc
+            //     (UIShadow.cpp:73-105);
+            //   · 父窗口被销毁时,ParentProc 收到 WM_DESTROY → DestroyWindow(阴影窗口),
+            //     收到 WM_NCDESTROY → GetShadowMap().erase(父HWND)(UIShadow.cpp:238-243)。
+            // 而本函数上方的真模态流程恰好把弹框**原来的 HWND 销毁了**:
+            //   DetachPaintWindow() → ::DestroyWindow(hWndOldCaptured) →
+            //   DialogBoxIndirectParam()。于是弹框的阴影窗口连同映射记录一起消失;而全工程
+            //   唯一的 m_shadow.Create() 调用点在 CPaintManagerUI::AttachDialog
+            //   (UIManager.cpp:4918),**真模态路径不走它**(这里只调 AttachPaintWindow,
+            //   它只换 m_hWndPaint / m_hDcPaint)⇒ 30+ 个模态弹框从此全都没有阴影窗口。
+            //   主窗口不经过 ShowModal,所以它的阴影还在 —— 这正是
+            //   「除了主窗口,所有模态弹框的窗口阴影都没了」的根因。
+            //
+            // 为什么直接调 Create() 就够:阴影样式(shadowsize / shadowcolor /
+            //   shadowsharpness / shadowposition …)早在 XML 解析时就写进了 manager 的
+            //   m_shadow 对象,重建只需重新绑 HWND,无需再解析一次 XML。
+            //   Create() 内部自带 m_bIsShowShadow 判断,没开阴影的窗口自然跳过。
+            pManager->GetShadow()->Create(pManager);
+
             // 用掉即清:避免这个文件级静态变量残留一个已失效的指针,
             // 影响下一次 ShowModal(尤其嵌套弹框:A 弹框里再开 B 弹框)。
             SetDetachedManager(NULL);
@@ -755,6 +778,15 @@ INT_PTR CALLBACK CWindowWnd::__DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
             ::GetClientRect(hDlg, &rcAfter);
         }
 
+        // ---- [窗口阴影] 尺寸校正后再刷新一次 ----
+        // 上面的阴影是在尺寸校正**之前**建的,那时 hDlg 还是 DLGTEMPLATE 的初始尺寸,
+        // 阴影位图因此是旧几何;SetWindowPos 之后窗口尺寸才最终确定,这里补刷一次,
+        // 保证阴影与弹框逐像素对齐,而不依赖后续 WM_PAINT 的补正时机。
+        if( pManager != NULL )
+        {
+            pManager->UpdateShadow();
+        }
+
         // 交给 CWindowWnd::HandleMessage 处理 WM_INITDIALOG,业务层的 OnCreate 等由此触发。
         pThis->HandleMessage(uMsg, wParam, lParam);