Dreamine.UI.Wpf.Equipment 1.0.1
Dreamine.UI.Wpf.Equipment 사용자 인터페이스 기능과 구성 요소를 제공합니다.
로딩중...
검색중...
일치하는것 없음
DreamineBlinkPopupWindow.xaml.cs
이 파일의 문서화 페이지로 가기
1using System;
2using System.ComponentModel;
3using System.Diagnostics;
4using System.Windows;
5using System.Windows.Input;
6using System.Windows.Interop;
7using System.Windows.Media;
8using System.Windows.Media.Animation;
9using System.Windows.Threading;
10using Dreamine.UI.Abstractions.Popup;
11using Dreamine.UI.Wpf.Controls.MessageBox;
13{
22 internal enum PopupAction
23 {
32 None,
33
42 Ok,
43
52 Cancel,
53
62 SystemClose
63 }
64
73 public partial class DreamineBlinkPopupWindow : Window
74 {
83 private readonly BlinkPopupOptions _opt;
84
93 private Storyboard? _blinkSb;
94
103 private bool? _requestedResult = null;
104
114
123 private bool _inClosing = false;
124
133 private PopupAction _lastAction = PopupAction.None;
134
143 private HwndSource? _hwndSrc;
144
153 private const int WM_SYSCOMMAND = 0x0112;
162 private const int SC_CLOSE = 0xF060;
163
188 public DreamineBlinkPopupWindow(BlinkPopupOptions opt)
189 {
190 InitializeComponent();
191 _opt = opt;
192
193 // ViewModel 생성 및 닫힘 이벤트 연결
194 var vm = new DreamineBlinkPopupWindowViewModel(opt);
195 vm.CloseRequested += (_, dr) =>
196 {
197 _requestedResult = dr;
198 _lastAction = dr == true
199 ? PopupAction.Ok
200 : dr == false
201 ? PopupAction.Cancel
202 : PopupAction.SystemClose;
203
205 };
206 DataContext = vm;
207
208 // TopMost / 기본 타이틀 적용
209 Topmost = _opt.TopMost;
210 if (!string.IsNullOrEmpty(_opt.Title))
211 {
212 Title = _opt.Title;
213 }
214
215 // 윈도우 크기 / 모드 설정
216 if (_opt.Fullscreen)
217 {
218 WindowState = WindowState.Maximized;
219 }
220 else
221 {
222 WindowState = WindowState.Normal;
223
224 if (_opt.FixedSize is Size sz)
225 {
226 Width = sz.Width;
227 Height = sz.Height;
228 }
229 else
230 {
231 SizeToContent = SizeToContent.WidthAndHeight;
232 }
233 }
234 }
235
252 protected override void OnContentRendered(EventArgs e)
253 {
254 base.OnContentRendered(e);
255 if (_opt.UseBlink)
256 {
257 StartBlink();
258 }
259 }
260
285 protected override void OnClosing(CancelEventArgs e)
286 {
287 if (_lastAction == PopupAction.None)
288 _lastAction = PopupAction.SystemClose;
289
290 if (_inClosing)
291 {
292 base.OnClosing(e);
293 return;
294 }
295 _inClosing = true;
296
297 try
298 {
299 if (_requestedResult.HasValue)
300 {
301 try { DialogResult = _requestedResult; }
302 catch (InvalidOperationException) { }
303 }
304
305 base.OnClosing(e);
306 }
307 finally
308 {
309 _inClosing = false;
310 }
311 }
312
329 protected override void OnSourceInitialized(EventArgs e)
330 {
331 base.OnSourceInitialized(e);
332 _hwndSrc = PresentationSource.FromVisual(this) as HwndSource;
333 _hwndSrc?.AddHook(WndProcHook);
334 }
335
360 protected override void OnPreviewKeyDown(KeyEventArgs e)
361 {
362 if (_opt.BlockAltF4 &&
363 e.SystemKey == Key.F4 &&
364 (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)
365 {
366 e.Handled = true;
367 return;
368 }
369
370 base.OnPreviewKeyDown(e);
371 }
372
429 private IntPtr WndProcHook(
430 IntPtr hwnd,
431 int msg,
432 IntPtr wParam,
433 IntPtr lParam,
434 ref bool handled)
435 {
436 if (_opt.BlockAltF4 &&
437 msg == WM_SYSCOMMAND &&
438 wParam.ToInt32() == SC_CLOSE)
439 {
440 handled = true;
441 return IntPtr.Zero;
442 }
443
444 return IntPtr.Zero;
445 }
446
455 private void RequestCloseNextTick()
456 {
457 if (!IsLoaded)
458 {
459 return;
460 }
461
462 var timer = new DispatcherTimer(DispatcherPriority.ApplicationIdle)
463 {
464 Interval = TimeSpan.FromMilliseconds(1)
465 };
466
467 timer.Tick += (_, __) =>
468 {
469 timer.Stop();
470
471 if (!IsLoaded)
472 {
473 return;
474 }
475
476 try
477 {
478 Close();
479 }
480 catch (Exception ex)
481 {
482 Debug.WriteLine($"[Popup] Close failed, retrying: {ex.Message}");
483 Dispatcher.BeginInvoke(
484 () =>
485 {
486 try { if (IsLoaded) Close(); }
487 catch (Exception retryEx) { Debug.WriteLine($"[Popup] Close retry failed: {retryEx.Message}"); }
488 },
489 DispatcherPriority.ContextIdle);
490 }
491 };
492
493 timer.Start();
494 }
495
512 protected override void OnClosed(EventArgs e)
513 {
514 base.OnClosed(e);
515 StopBlink();
516 }
517
542 private void StartBlink()
543 {
544 var rootBrushObj = Resources["RootBrush"];
545 SolidColorBrush brush =
546 rootBrushObj is SolidColorBrush scb
547 ? (scb.IsFrozen ? scb.Clone() : scb)
548 : new SolidColorBrush(_opt.Color1);
549
550 Resources["RootBrush"] = brush;
551
552 var colorAnim = new ColorAnimationUsingKeyFrames();
553 colorAnim.KeyFrames.Add(
554 new DiscreteColorKeyFrame(
555 _opt.Color1,
556 KeyTime.FromTimeSpan(TimeSpan.Zero)));
557 colorAnim.KeyFrames.Add(
558 new DiscreteColorKeyFrame(
559 _opt.Color2,
560 KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(_opt.BlinkIntervalMs))));
561 colorAnim.KeyFrames.Add(
562 new DiscreteColorKeyFrame(
563 _opt.Color1,
564 KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(_opt.BlinkIntervalMs * 2))));
565
566 Storyboard.SetTarget(colorAnim, brush);
567 Storyboard.SetTargetProperty(colorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
568
569 var opAnim = new DoubleAnimationUsingKeyFrames();
570 opAnim.KeyFrames.Add(
571 new DiscreteDoubleKeyFrame(
572 _opt.Opacity1,
573 KeyTime.FromTimeSpan(TimeSpan.Zero)));
574 opAnim.KeyFrames.Add(
575 new DiscreteDoubleKeyFrame(
576 _opt.Opacity2,
577 KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(_opt.BlinkIntervalMs))));
578 opAnim.KeyFrames.Add(
579 new DiscreteDoubleKeyFrame(
580 _opt.Opacity1,
581 KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(_opt.BlinkIntervalMs * 2))));
582
583 Storyboard.SetTarget(opAnim, RootBorder);
584 Storyboard.SetTargetProperty(opAnim, new PropertyPath(OpacityProperty));
585
586 _blinkSb = new Storyboard
587 {
588 RepeatBehavior = _opt.BlinkRepeatCount <= 0
589 ? RepeatBehavior.Forever
590 : new RepeatBehavior(_opt.BlinkRepeatCount)
591 };
592 _blinkSb.Children.Add(colorAnim);
593 _blinkSb.Children.Add(opAnim);
594 _blinkSb.Begin(this, true);
595 }
596
605 private void StopBlink()
606 {
607 _blinkSb?.Stop(this);
608 _blinkSb = null;
609
610 _hwndSrc?.RemoveHook(WndProcHook);
611 _hwndSrc = null;
612 }
613 }
614}
IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)