diff --git a/src/EasyWindowsApplication/Core/Application.cs b/src/EasyWindowsApplication/Core/Application.cs index 5fd0d84..6ddb547 100644 --- a/src/EasyWindowsApplication/Core/Application.cs +++ b/src/EasyWindowsApplication/Core/Application.cs @@ -293,6 +293,10 @@ private void RegisterAlternative(WindowModel window) var surface = new Menus.MenuSurface(window.Content as ContentModel); if (!string.IsNullOrEmpty(window.Name)) surface.Name = window.Name; + // Dueño de respaldo sin tray: main HWND resuelto en Show() (lazy, + // igual que diálogos). WireMenuSurfaces() lo sobrescribe con el + // broker del tray si hay SystemTray declarado. + surface.OwnerProvider = () => _mainHwnd; surface.Registry = _registry; surface.EnsureMaterialized(); _registry.Attach(EntityKind.Surface, surface, hwnd: 0, window.Name); diff --git a/src/EasyWindowsApplication/Core/MasterRouter.cs b/src/EasyWindowsApplication/Core/MasterRouter.cs index c8e84f3..f187725 100644 --- a/src/EasyWindowsApplication/Core/MasterRouter.cs +++ b/src/EasyWindowsApplication/Core/MasterRouter.cs @@ -445,8 +445,18 @@ private void DispatchTypedEvent(uint msg, nint controlHwnd, nint wParam, nint lP nint code = Win32Helpers.HIWORD(wParam); if (control is IInputFeed feed) { - if (code == BN.CLICKED) feed.FeedTrigger(typeof(MainTap), 1); - if (code == BN.DOUBLECLICKED) feed.FeedTrigger(typeof(MainTap), 2); + bool fires = code == BN.CLICKED || code == BN.DOUBLECLICKED; + if (!fires) break; + // Publica el HWND origen para MenuSurface.Show() (ancla al + // control). Se limpia al salir: Show() solo lo ve dentro + // del handler en curso. Issue #53, sin cambiar Action. + InputTriggerContext.Publish(controlHwnd); + try + { + if (code == BN.CLICKED) feed.FeedTrigger(typeof(MainTap), 1); + if (code == BN.DOUBLECLICKED) feed.FeedTrigger(typeof(MainTap), 2); + } + finally { InputTriggerContext.Clear(); } } break; } diff --git a/src/EasyWindowsApplication/Core/Menus/MenuSurface.cs b/src/EasyWindowsApplication/Core/Menus/MenuSurface.cs index f73a037..70d2d17 100644 --- a/src/EasyWindowsApplication/Core/Menus/MenuSurface.cs +++ b/src/EasyWindowsApplication/Core/Menus/MenuSurface.cs @@ -17,6 +17,11 @@ internal sealed class MenuSurface : IMenu internal HandleRegistry? Registry { get; set; } + // Dueño de respaldo resuelto en Show(): diálogos usan el mismo patrón + // (DialogSurfaceBase.OwnerProvider) para no depender del orden de + // declaración en Layout. El tray lo sobrescribe vía SetOwner(). + internal Func OwnerProvider { get; set; } = static () => 0; + internal void SetOwner(nint hwnd) => _ownerHwnd = hwnd; internal void SetIconAnchor(nint trayHwnd, uint trayId) @@ -55,6 +60,15 @@ internal void SetIconAnchor(nint trayHwnd, uint trayId) public void Show() { + // Inteligente (issue #53, sin cambiar IMenu): control disparador en + // curso → icono del tray → cursor. Las explícitas ShowAtCursor() / + // ShowAtIcon() no leen el contexto por contrato. + if (InputTriggerContext.TryGetFresh(out var triggerHwnd) + && TryAnchorToControl(triggerHwnd, out var pos, out var align, out var owner)) + { + ShowAt(pos.X, pos.Y, align, owner); + return; + } if (_iconAnchor is not null) { var (x, y) = _iconAnchor(); @@ -153,9 +167,42 @@ private MenuItemModel ToItemModel(IViewSurface surface, ContentModel? sub) return model; } - private void ShowAt(int x, int y, uint align) + private void ShowAt(int x, int y, uint align) => ShowAt(x, y, align, ResolveOwner()); + + private void ShowAt(int x, int y, uint align, nint owner) { var model = EnsureMaterialized(); - Win32MenuEngine.Show(_ownerHwnd, model, x, y, align); + Win32MenuEngine.Show(owner, model, x, y, align); + } + + /// + /// Ancla al rect del control disparador con flip según el área de trabajo + /// del monitor (igual que el ancla del icono del tray). El dueño es el + /// propio control para ese Show() puntual. Falla si el HWND ya no es válido. + /// + private static bool TryAnchorToControl(nint hwnd, out (int X, int Y) pos, out uint align, out nint owner) + { + pos = default; + align = TPM.LEFTALIGN | TPM.TOPALIGN; + owner = hwnd; + if (!Win32.GetWindowRect(hwnd, out RECT rc)) return false; + nint mon = Win32.MonitorFromWindow(hwnd, MONITOR.DEFAULTTONEAREST); + if (mon == 0) mon = Win32.MonitorFromWindow(hwnd, MONITOR.DEFAULTTOPRIMARY); + if (mon == 0) + { + pos = (rc.Left, rc.Bottom); + return true; + } + MONITORINFO mi = new() { cbSize = (uint)Marshal.SizeOf() }; + if (!Win32.GetMonitorInfoW(mon, ref mi)) return false; + var work = mi.rcWork; + bool below = work.Bottom - rc.Bottom >= rc.Top - work.Top; + bool toRight = work.Right - rc.Left >= rc.Right - work.Left; + pos = below ? (rc.Left, rc.Bottom) : (rc.Left, rc.Top); + align = (toRight ? TPM.LEFTALIGN : TPM.RIGHTALIGN) + | (below ? TPM.TOPALIGN : TPM.BOTTOMALIGN); + return true; } + + private nint ResolveOwner() => _ownerHwnd != 0 ? _ownerHwnd : OwnerProvider(); } diff --git a/src/EasyWindowsApplication/Core/Surfaces/InputTriggerContext.cs b/src/EasyWindowsApplication/Core/Surfaces/InputTriggerContext.cs new file mode 100644 index 0000000..8a5c79f --- /dev/null +++ b/src/EasyWindowsApplication/Core/Surfaces/InputTriggerContext.cs @@ -0,0 +1,29 @@ +namespace EasyWindowsApplication.Core.Surfaces; + +/// +/// HWND del control que disparó el trigger en curso (hilo UI). +/// Permite a MenuSurface.Show() anclarse al control sin cambiar +/// las firmas Action de IInputSurface. Solo vive durante +/// el dispatch síncrono (Fire → handlers); se limpia con +/// try/finally en cada punto de publicación. +/// +internal static class InputTriggerContext +{ + private static readonly AsyncLocal<(nint Hwnd, int Tick)> _current = new(); + + internal static void Publish(nint hwnd) + { + if (hwnd == 0) return; + _current.Value = (hwnd, Environment.TickCount); + } + + internal static void Clear() => _current.Value = default; + + internal static bool TryGetFresh(out nint hwnd, int maxAgeMs = 2000) + { + var (h, tick) = _current.Value; + hwnd = h; + if (h == 0) return false; + return unchecked(Environment.TickCount - tick) <= maxAgeMs; + } +} diff --git a/src/EasyWindowsApplication/Core/SystemTray/SystemTrayBroker.cs b/src/EasyWindowsApplication/Core/SystemTray/SystemTrayBroker.cs index cfdc535..5086efb 100644 --- a/src/EasyWindowsApplication/Core/SystemTray/SystemTrayBroker.cs +++ b/src/EasyWindowsApplication/Core/SystemTray/SystemTrayBroker.cs @@ -228,7 +228,12 @@ private void OnHover() private void Fire(Type trigger) { int count = _counter.Next(trigger, Environment.TickCount, Win32.GetDoubleClickTime()); - _dispatch(trigger, count); + // El tray no es un control anclable: limpia cualquier contexto previo + // para que MenuSurface.Show() caiga al icono (iconAnchor), nunca a un + // botón de una ventana. Issue #53. + InputTriggerContext.Clear(); + try { _dispatch(trigger, count); } + finally { InputTriggerContext.Clear(); } } private NOTIFYICONDATAW NewData(uint flags) diff --git a/src/EasyWindowsApplication/Share/CaptionButtons.cs b/src/EasyWindowsApplication/Share/CaptionButtons.cs deleted file mode 100644 index 6560e3c..0000000 --- a/src/EasyWindowsApplication/Share/CaptionButtons.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EasyWindowsApplication.Share; - -/// Botones de caption nativos. -[Flags] -public enum CaptionButtons -{ - None = 0, - Close = 1, - Minimize = 2, - Maximize = 4, - All = Close | Minimize | Maximize, -} diff --git a/src/EasyWindowsApplication/Share/Enums.cs b/src/EasyWindowsApplication/Share/Enums.cs index 3df1ef0..8f1d5cc 100644 --- a/src/EasyWindowsApplication/Share/Enums.cs +++ b/src/EasyWindowsApplication/Share/Enums.cs @@ -11,4 +11,41 @@ public enum GridUnitType { Absolute, Auto, Star } public enum LayoutAlignment { Start, Center, End, Fill } -public enum DockPosition { Left, Top, Right, Bottom } \ No newline at end of file +public enum DockPosition { Left, Top, Right, Bottom } + +/// Botones de caption nativos. +[Flags] +public enum CaptionButtons { None = 0, Close = 1, Minimize = 2, Maximize = 4, All = Close | Minimize | Maximize } + +/// Estado de la ventana principal. +public enum WindowState { Normal, Minimized, Maximized, FullScreen } + +public enum WindowPositionPreset { Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight } + +public enum SnapRegion { Left, Right, Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight } + +/// Fondo translúcido del shell (DWM). Requiere Windows 10 1809+ para efectos; en sistemas anteriores se ignora. +public enum WindowBackdrop { None, Mica, Acrylic, DesktopAcrylic, SolidColor } + +/// Modo de title bar de la ventana principal. +public enum TitleBarMode +{ + /// Title bar nativa Win32 (WNDCLASSEX icon + SetWindowText). + Simple, + + /// Custom title bar extendida sobre el client area (DwmExtendFrameIntoClientArea). + Custom +} + +/// Modo de visibilidad en capturas de pantalla (PrtSc, Teams, etc.). +public enum ScreenCaptureMode +{ + /// Contenido normal, capturable. + Allow, + + /// La ventana aparece negra en captura (WDA_EXCLUDEFROMCAPTURE, Win10 2004+). + HideContent, + + /// La ventana no aparece en captura (WDA_EXCLUDEFROMCAPTURE con fallback a WDA_MONITOR). + HideWindow +} diff --git a/src/EasyWindowsApplication/Share/ILayout.cs b/src/EasyWindowsApplication/Share/ILayout.cs index b37bef7..be01543 100644 --- a/src/EasyWindowsApplication/Share/ILayout.cs +++ b/src/EasyWindowsApplication/Share/ILayout.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace EasyWindowsApplication.Share; +namespace EasyWindowsApplication.Share; public interface ILayout { diff --git a/src/EasyWindowsApplication/Share/TitleBarMode.cs b/src/EasyWindowsApplication/Share/ITitleBarConfig.cs similarity index 67% rename from src/EasyWindowsApplication/Share/TitleBarMode.cs rename to src/EasyWindowsApplication/Share/ITitleBarConfig.cs index 0a7eee1..cf61b83 100644 --- a/src/EasyWindowsApplication/Share/TitleBarMode.cs +++ b/src/EasyWindowsApplication/Share/ITitleBarConfig.cs @@ -1,15 +1,5 @@ namespace EasyWindowsApplication.Share; -/// Modo de title bar de la ventana principal. -public enum TitleBarMode -{ - /// Title bar nativa Win32 (WNDCLASSEX icon + SetWindowText). - Simple, - - /// Custom title bar extendida sobre el client area (DwmExtendFrameIntoClientArea). - Custom, -} - /// Configuración de title bar. public interface ITitleBarConfig { diff --git a/src/EasyWindowsApplication/Share/ScreenCaptureMode.cs b/src/EasyWindowsApplication/Share/ScreenCaptureMode.cs deleted file mode 100644 index 65d0448..0000000 --- a/src/EasyWindowsApplication/Share/ScreenCaptureMode.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace EasyWindowsApplication.Share; - -/// Modo de visibilidad en capturas de pantalla (PrtSc, Teams, etc.). -public enum ScreenCaptureMode -{ - /// Contenido normal, capturable. - Allow, - - /// La ventana aparece negra en captura (WDA_EXCLUDEFROMCAPTURE, Win10 2004+). - HideContent, - - /// La ventana no aparece en captura (WDA_EXCLUDEFROMCAPTURE con fallback a WDA_MONITOR). - HideWindow, -} diff --git a/src/EasyWindowsApplication/Share/View.cs b/src/EasyWindowsApplication/Share/View.cs index 06d8090..6316022 100644 --- a/src/EasyWindowsApplication/Share/View.cs +++ b/src/EasyWindowsApplication/Share/View.cs @@ -18,7 +18,7 @@ internal ViewBase() { } public sealed class View where T : class, IViewSurface { - private readonly List> _configure = new(); + private readonly List> _configure = []; internal string? PendingName { get; private set; } public View() { } diff --git a/src/EasyWindowsApplication/Share/WindowBackdrop.cs b/src/EasyWindowsApplication/Share/WindowBackdrop.cs deleted file mode 100644 index 9ad7092..0000000 --- a/src/EasyWindowsApplication/Share/WindowBackdrop.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace EasyWindowsApplication.Share; - -/// Fondo translúcido del shell (DWM). Requiere Windows 10 1809+ para efectos; en sistemas anteriores se ignora. -public enum WindowBackdrop { None, Mica, Acrylic, DesktopAcrylic, SolidColor } diff --git a/src/EasyWindowsApplication/Share/WindowPosition.cs b/src/EasyWindowsApplication/Share/WindowPosition.cs index 05e9dec..c689e09 100644 --- a/src/EasyWindowsApplication/Share/WindowPosition.cs +++ b/src/EasyWindowsApplication/Share/WindowPosition.cs @@ -13,28 +13,3 @@ public sealed record PositionPreset(WindowPositionPreset Preset) : IWindowPositi /// Snap a borde de pantalla (o trackbar) estilo Aero Snap. public sealed record PositionSnap(SnapRegion Region) : IWindowPosition; - -public enum WindowPositionPreset -{ - Center, - TopLeft, - Top, - TopRight, - Left, - Right, - BottomLeft, - Bottom, - BottomRight, -} - -public enum SnapRegion -{ - Left, - Right, - Top, - Bottom, - TopLeft, - TopRight, - BottomLeft, - BottomRight, -} diff --git a/src/EasyWindowsApplication/Share/WindowState.cs b/src/EasyWindowsApplication/Share/WindowState.cs deleted file mode 100644 index b1e06a2..0000000 --- a/src/EasyWindowsApplication/Share/WindowState.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace EasyWindowsApplication.Share; - -/// Estado de la ventana principal. -public enum WindowState { Normal, Minimized, Maximized, FullScreen } diff --git a/src/Sample/Program.cs b/src/Sample/Program.cs index f5948d6..2a26ffe 100644 --- a/src/Sample/Program.cs +++ b/src/Sample/Program.cs @@ -12,163 +12,67 @@ { ly.Window(iw => iw .Name("MainWindow") - .Title("EWA - Demo") - .Dimensions(525, 494) + .Title("EWA - TrayMenu Demo") + .Dimensions(420, 200) + .SystemTray(st => st.Tooltip("EWA Demo")) .Content(c => c .Spacing(8) .Padding(8) .Children(ch => { - ch.View(lb => lb.Name("LbResult").Text("Press a button to test an AlternativeWindow.")); - ch.View(b => b.Name("BtnAltWindow").Text("Secondary window(HWND)")); - ch.View(b => b.Name("BtnMenu").Text("Context menu (IMenu)")); - ch.View(b => b.Name("BtnTaskDialog").Text("TaskDialog — .Content() mode")); - ch.View(b => b.Name("BtnTaskDialogMin").Text("TaskDialog — .Text() mode")); - ch.View(b => b.Name("BtnOpenFile").Text("OpenFileDialog")); - ch.View(b => b.Name("BtnSaveFile").Text("SaveFileDialog")); - ch.View(b => b.Name("BtnSelectFolder").Text("SelectFolderDialog")); - ch.View(b => b.Name("BtnWinState").Text("Window: Min/Max/Restore/Fullscreen")); - ch.View(b => b.Name("BtnZOrder").Text("BringToFront + SendToBack demo")); + ch.View(lb => lb.Name("LbResult").Text("Boton muestra el mismo menu del tray.")); + ch.View(b => b.Name("BtnCursor").Text("Menu en cursor (testigo)")); + ch.View(b => b.Name("BtnMenu").Text("Mostrar menu (Show inteligente)")); }) ) ); - ly.AlternativeWindow(aw => aw - .Name("OtherWindow") - .Title("Secondary window (HWND)") - .Dimensions(340, 190) - .Background(Color.LightSkyBlue) - .Content(c => c.Children(ch => - { - ch.View(lb => lb.Text("Close it and show it again: it recreates itself.")); - ch.View(b => b.Name("BtnOtherHide").Text("Hide")); - ch.View(b => b.Name("BtnOtherClose").Text("Close")); - })) - ); ly.AlternativeWindow(m => m - .Name("GalleryMenu") + .Name("TrayMenu") .Content(c => c.Children(ch => { - ch.View(mi => mi.Name("MiHello").Text("To greet")); + ch.View(mi => mi.Name("MiShow").Text("Mostrar ventana")); ch.View(); - ch.View(mi => mi.Name("MiExit").Text("Exit")); + ch.View(mi => mi.Name("MiExit").Text("Salir")); })) ); - ly.AlternativeWindow(td => td - .Name("TaskDialog") - .Title("Complete TaskDialog") - .Content(c => - { - c.NotificationIcon(TaskDialogIcon.Information); - c.PrimaryText("Builder mode .Content()"); - c.SecondaryText("Choices Yes/No, Default choice No."); - c.Choices(TaskDialogChoices.Yes | TaskDialogChoices.No); - c.DefaultChoice(TaskDialogChoice.No); - }) - ); - ly.AlternativeWindow(td => td - .Name("TaskDialogMin") - .Title("Minimum TaskDialog") - .Text("Minimal mode .Text() — defaults: Ok, no icon.") - ); - ly.AlternativeWindow(ofd => ofd - .Name("OpenFileDialog") - .Title("Open image") - .Filters(f => f.Children(fc => fc - .FileFilter(PngFile) - .FileFilter(JpgFile) - .FileFilter(AllFile))) - .Content(c => c - .DefaultDirectory(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)) - .MultiSelect(true)) - ); - ly.AlternativeWindow(sfd => sfd - .Name("SaveFileDialog") - .Title("Save text") - .Filters(f => f.Children(fc => fc.FileFilter(TxtFile))) - .Content(c => c - .DefaultDirectory(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)) - .DefaultFileName("exit") - .DefaultExtension(TxtFile)) - ); - ly.AlternativeWindow(sfd => sfd - .Name("SelectFolderDialog") - .Title("Select folder") - .Content(c => c - .DefaultDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)) - .PersistLastDirectory(false)) - ); }) .Behavior(bh => { - bh.BtnAltWindow.OnInputWithSpatialPosition(() => bh.OtherWindow.Show()); - bh.BtnMenu.OnInputWithSpatialPosition(() => bh.GalleryMenu.Show()); - - bh.BtnTaskDialog.OnInputWithSpatialPosition(() => - { - var r = bh.TaskDialog.Show(); - bh.LbResult.Text = r.IsCanceled ? "TaskDialog: cancelado." : $"TaskDialog: {r.Choice}."; - }); - bh.BtnTaskDialogMin.OnInputWithSpatialPosition(() => - { - var r = bh.TaskDialogMin.Show(); - bh.LbResult.Text = r.IsCanceled ? "TaskDialog mín: cancelado." : $"TaskDialog mín: {r.Choice}."; - }); - bh.BtnOpenFile.OnInputWithSpatialPosition(() => + bh.WindowsApplication.OnLaunched(wa => { - var r = bh.OpenFileDialog.Show(); - bh.LbResult.Text = r.IsCanceled ? "OpenFile: cancelado." - : $"OpenFile: {r.FilePaths.Count} archivo(s) — {string.Join(", ", r.FilePaths)}"; + wa.TaskbarButtonVisibility(false); + bh.MainWindow.Visibility(false); + bh.SystemTray.Visibility(true); }); - bh.BtnSaveFile.OnInputWithSpatialPosition(() => - { - var r = bh.SaveFileDialog.Show(); - bh.LbResult.Text = r.IsCanceled ? "SaveFile: cancelado." : $"SaveFile: {r.FilePath}"; - }); - bh.BtnSelectFolder.OnInputWithSpatialPosition(() => - { - var r = bh.SelectFolderDialog.Show(); - bh.LbResult.Text = r.IsCanceled ? "SelectFolder: cancelado." : $"SelectFolder: {r.FolderPath}"; - }); - bh.OtherWindow.OnLoaded(() => bh.LbResult.Text = "OtherWindow: Loaded (ciclo fresco)."); - bh.OtherWindow.OnClosing(e => - { - bh.LbResult.Text = "OtherWindow: Closing..."; - System.Threading.Thread.Sleep(2000); - }); - bh.OtherWindow.OnClosed(() => bh.LbResult.Text = "OtherWindow: Closed — Show() la re-crea."); - bh.BtnOtherHide.OnInputWithSpatialPosition(() => bh.OtherWindow.Visibility(false)); - bh.BtnOtherClose.OnInputWithSpatialPosition(() => bh.OtherWindow.Close()); - // Phase C/D: ventana principal (State + Z-order) - bh.MainWindow.OnResized(a => bh.LbResult.Text = $"MainWindow: Resized {a.Width}×{a.Height} (accepted)"); - bh.BtnWinState.OnInputWithSpatialPosition(() => - { - IWindow win = bh.MainWindow; - // Demo: ciclo Normal → FullScreen → Maximize → Normal - switch (win.State) - { - case WindowState.Normal: win.State = WindowState.FullScreen; break; - case WindowState.FullScreen: win.ExitFullScreen(); break; - case WindowState.Maximized: win.Minimize(); break; - case WindowState.Minimized: win.RestoreState(); break; - } - bh.LbResult.Text = $"MainWindow: State = {win.State} | {win.MaxSize}"; - }); - bh.BtnZOrder.OnInputWithSpatialPosition(() => - { - // Traer al frente, luego al fondo 1 segundo después (visible en la taskbar) - ((IWindow)bh.MainWindow).BringToFront(); - bh.LbResult.Text = "MainWindow: BringToFront ejecutado (que la haga visible encima de otras apps)"; - }); - bh.MiHello.OnInputWithSpatialPosition(() => bh.LbResult.Text = "Menú: ¡Hola!"); + // Click derecho en icono del tray -> menu anclado al icono (iconAnchor). + bh.SystemTray.OnInputWithSpatialPosition(() => bh.TrayMenu.Show()); + + + // Doble click izquierdo en icono del tray -> mostrar ventana principal. + bh.SystemTray.OnInputWithSpatialPosition(() => bh.MainWindow.Show()); + //bh.SystemTray.OnInputWithSpatialPosition(() => + //{ + // bh.WindowsApplication.TaskbarButtonVisibility(true); + // bh.MainWindow.Visibility(true); + // bh.SystemTray.Visibility(false); + //}); + + // Boton de la ventana principal -> Show() inteligente (issue #53): + // con click real ancla al rect del boton; sin contexto cae a icono/cursor. + bh.BtnMenu.OnInputWithSpatialPosition(() => bh.TrayMenu.Show()); + + // Testigo explicito: siempre en cursor, no lee el contexto del disparador. + bh.BtnCursor.OnInputWithSpatialPosition(() => bh.TrayMenu.ShowAtCursor()); + + bh.MiShow.OnInputWithSpatialPosition(() => bh.MainWindow.Show()); + //bh.MiShow.OnInputWithSpatialPosition(() => + //{ + // bh.WindowsApplication.TaskbarButtonVisibility(true); + // bh.MainWindow.Visibility(true); + // bh.SystemTray.Visibility(false); + //}); bh.MiExit.OnInputWithSpatialPosition(() => bh.WindowsApplication.Terminate()); - bh.WindowsApplication.OnTerminated(() => System.Diagnostics.Trace.WriteLine("[EWA] Terminated")); - bh.MainWindow.OnInputWithoutSpatialPosition(() => - { - if (bh.MainWindow.State is WindowState.FullScreen) - { - bh.MainWindow.RestoreState(); - } - }); + }) .Initialize();