using System.IO; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using SheetMe.Core.Models; using SheetMe.Data.Stores; using SheetMe.Designer.Services; using SheetMe.Designer.ViewModels; using SheetMe.Designer.ViewModels.Inspector; namespace SheetMe.Designer.Diagnostics; /// /// 별도 창(대화상자) 오프스크린 스냅샷 — --dialog-shots <출력폴더>. /// /// 창 10종을 다크·라이트 양 테마로 열어 PNG 로 남긴다. 목적은 하나다: /// 테마 대비 결함을 사람 손 없이 재현 가능하게 확인한다. /// 실입력(마우스·키보드) 주입은 화면 잠금·세션 격리 상태에서 OS 가 거부하지만 /// 이 경로는 창을 화면 밖에 띄워 RenderTargetBitmap 으로 찍으므로 그 제약을 받지 않는다. /// /// 창은 화면 밖(-10000)에 Show() 로 띄운다 — 레이아웃이 실제로 돌아야 템플릿·트리거가 /// 적용된 상태로 찍힌다(Measure/Arrange 만으로는 Window 크롬이 구성되지 않는다). /// 모든 창은 찍은 뒤 즉시 닫는다. /// public static class DialogShots { #region Methods public static int Run(string outputDirectory) { try { Directory.CreateDirectory(outputDirectory); // 기본 ShutdownMode 는 OnLastWindowClose 라, 찍고 닫는 순간 마지막 창이 사라져 앱이 종료된다 // (그 뒤 Application.Current 가 null 이 되어 테마 교체에서 NRE). 명시 종료로 바꾼다. Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown; var lines = new List(); foreach (var light in new[] { false, true }) { ThemeManager.Apply(light); var suffix = light ? "light" : "dark"; foreach (var (name, factory) in Factories()) { try { var window = factory(); Capture(window, Path.Combine(outputDirectory, $"{name}-{suffix}.png")); // 창 배경이 실제로 무엇으로 해석됐는지 함께 남긴다 — 픽셀만 보면 원인을 못 가린다. // WPF 는 암시 스타일을 요소의 '정확한 타입'으로만 찾으므로, Window 를 상속한 // 대화상자에는