diff --git a/Ui/ShellUiHost.cs b/Ui/ShellUiHost.cs
index eae185d..cc888b1 100644
--- a/Ui/ShellUiHost.cs
+++ b/Ui/ShellUiHost.cs
@@ -28,6 +28,20 @@ namespace PolyTraderSharp.Ui
/// Setzt das Hauptfenster (Launcher) – Ziel für .
public void SetMainWindow(Form main) => _mainWindow = main;
+ ///
+ /// Fügt einem Fenster das gemeinsame „Fenster"-Menü hinzu (oberste Leiste). Als letztes
+ /// hinzugefügtes Top-Control belegt der MenuStrip die oberste Zeile über etwaigen ToolStrips.
+ ///
+ private void AttachWindowMenu(Form form, string currentViewId)
+ {
+ var menu = new MenuStrip { Dock = DockStyle.Top };
+ var fenster = new ToolStripMenuItem("Fenster");
+ menu.Items.Add(fenster);
+ PolyTrader.Core.Modularity.WindowMenu.Wire(fenster, this, currentViewId);
+ form.Controls.Add(menu);
+ form.MainMenuStrip = menu;
+ }
+
public void ActivateMain()
{
if (_mainWindow == null || _mainWindow.IsDisposed) return;
@@ -61,6 +75,12 @@ namespace PolyTraderSharp.Ui
if (string.IsNullOrEmpty(form.Text) || form.Text == form.Name)
form.Text = view.Title;
+ // Gemeinsames „Fenster"-Menü zentral in jedes Fenster injizieren (identische Shell-Chrome
+ // auf allen Fenstern; die inhaltlichen Controls bleiben designerbasiert). Nur, wenn das
+ // Fenster nicht bereits ein eigenes Menü mitbringt (z. B. der Launcher).
+ if (form.MainMenuStrip == null)
+ AttachWindowMenu(form, view.Id);
+
// Alle Fenster maximiert (Vorgabe): Full-HD-Ziel, skaliert auf größere Auflösungen.
form.StartPosition = FormStartPosition.CenterScreen;
form.WindowState = FormWindowState.Maximized;
diff --git a/tests/PolyTrader.Tests/WindowMenuTests.cs b/tests/PolyTrader.Tests/WindowMenuTests.cs
new file mode 100644
index 0000000..236f6b5
--- /dev/null
+++ b/tests/PolyTrader.Tests/WindowMenuTests.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using PolyTrader.Core.Modularity;
+using Xunit;
+
+namespace PolyTrader.Tests
+{
+ /// Sicherheitsnetz für das gemeinsame „Fenster"-Menü (Slice 1): Inhalt + Verhalten.
+ public class WindowMenuTests
+ {
+ private sealed class FakeUiHost : IModuleUiHost
+ {
+ public List ViewList { get; } = new();
+ public HashSet OpenIds { get; } = new();
+ public List Opened { get; } = new();
+ public bool MainActivated { get; private set; }
+
+ public IReadOnlyList Views => ViewList;
+ public bool IsOpen(string viewId) => OpenIds.Contains(viewId);
+ public void OpenView(string viewId) => Opened.Add(viewId);
+ public void ActivateMain() => MainActivated = true;
+ public void RegisterView(ModuleView view) => ViewList.Add(view);
+ public event Action? OpenStateChanged { add { } remove { } }
+ }
+
+ private static FakeUiHost Host()
+ {
+ var h = new FakeUiHost();
+ h.RegisterView(new ModuleView { Id = "core.dashboard", Title = "Dashboard", Order = 1 });
+ h.RegisterView(new ModuleView { Id = "core.terminal", Title = "Terminal / Logs", Order = 2 });
+ h.OpenIds.Add("core.terminal"); // Terminal ist offen
+ return h;
+ }
+
+ [Fact]
+ public void Populate_lists_launcher_views_and_exit()
+ {
+ var host = Host();
+ var fenster = new ToolStripMenuItem("Fenster");
+
+ WindowMenu.Populate(fenster, host, currentViewId: "core.dashboard");
+
+ var texts = fenster.DropDownItems.OfType().Select(i => i.Text).ToList();
+ Assert.Equal("Launcher", texts[0]);
+ Assert.Contains("Dashboard", texts);
+ Assert.Contains("Terminal / Logs", texts);
+ Assert.Contains("Beenden", texts);
+ }
+
+ [Fact]
+ public void Current_view_is_bold_and_checked_open_view_is_checked()
+ {
+ var host = Host();
+ var fenster = new ToolStripMenuItem("Fenster");
+
+ WindowMenu.Populate(fenster, host, currentViewId: "core.dashboard");
+
+ var dashboard = fenster.DropDownItems.OfType().First(i => i.Text == "Dashboard");
+ var terminal = fenster.DropDownItems.OfType().First(i => i.Text == "Terminal / Logs");
+
+ Assert.True(dashboard.Checked); // aktuelles Fenster
+ Assert.True(dashboard.Font.Bold);
+ Assert.True(terminal.Checked); // offenes Fenster
+ Assert.False(terminal.Font.Bold);
+ }
+
+ [Fact]
+ public void Clicking_items_navigates()
+ {
+ var host = Host();
+ var fenster = new ToolStripMenuItem("Fenster");
+ WindowMenu.Populate(fenster, host, currentViewId: null);
+
+ var items = fenster.DropDownItems.OfType().ToList();
+ items.First(i => i.Text == "Launcher").PerformClick();
+ items.First(i => i.Text == "Terminal / Logs").PerformClick();
+
+ Assert.True(host.MainActivated);
+ Assert.Contains("core.terminal", host.Opened);
+ }
+ }
+}