From a52fec80a987e32b07e17c4237b2e29694c8a340 Mon Sep 17 00:00:00 2001 From: Cyd Date: Wed, 29 Jul 2026 09:21:54 -0500 Subject: [PATCH] mfd_layout.cfg: ,noframe takes a window's title bar off Append it to any line - "RPL4=240,120,1000,620,noframe" - and that window comes up with no caption and no border. For the game window that is a cockpit filling a monitor edge to edge at a rect you chose, which -fit could only do by taking the whole screen; for an exploded pane it is a display photographed without chrome. Per line rather than global, so the shell can go bare while the panes keep their captions, or the other way round. The flag is an instruction rather than something measured off the window, so Save carries it back out - otherwise the first finished drag would rewrite the file and quietly drop it. Windows are always built framed and Load only ever strips, so deleting the flag is all it takes to get the frame back; there is no un-strip path to get wrong. A bare window's rect IS its client rect, so the client area is what survives: a window that had a size in the file keeps it as the client, and a position-only pane keeps whatever client it had. That also makes the round trip stable - once bare, what Save records is already the client, so load-save-load does not creep. WS_SYSMENU stays on. It draws nothing without a caption, but without it DefWindowProc will not honour Alt+F4, and a window with no title bar and no way to close it is a trap. Nothing else can be dragged either, hence the note in the file header and environ.ini: place it first, add the flag after. Verified in both views. Cockpit: the same 240,120 1000x620 line with and without the flag, CAPTION|THICKFRAME and a 984x581 client becoming POPUP with a 1000x620 one, and a screenshot showing the displays hard against all four edges where the framed shot had them inside a letterbox. Save mode with the flag set, nudged with WM_EXITSIZEMOVE, rewrote the line with ",noframe" intact. Exploded: Map bare at 777,333 with its 500x640 client preserved while the shell beside it kept its caption. Co-Authored-By: Claude Opus 5 (1M context) --- MUNGA_L4/L4MFDVIEW.cpp | 61 +++++++++++++++++++++++++++++++++++++++--- MUNGA_L4/L4MFDVIEW.h | 9 ++++++- pack-dist.ps1 | 6 +++++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/MUNGA_L4/L4MFDVIEW.cpp b/MUNGA_L4/L4MFDVIEW.cpp index 27ac97a..dfa9adc 100644 --- a/MUNGA_L4/L4MFDVIEW.cpp +++ b/MUNGA_L4/L4MFDVIEW.cpp @@ -25,10 +25,26 @@ namespace void *window; const char *title; Logical withSize; + Logical bare; // frame stripped, per the file }; LayoutWindow layoutWindows[maxLayoutWindows]; int layoutWindowCount = 0; + //--------------------------------------------------------------- + // Take a window's frame off: no title bar, no border, nothing to + // drag it by. WS_SYSMENU stays - it draws nothing once the caption + // is gone, but without one DefWindowProc will not honour Alt+F4, + // and a bare window with no way to close it is a trap. + //--------------------------------------------------------------- + void StripWindowFrame(HWND window) + { + LONG_PTR style = GetWindowLongPtrA(window, GWL_STYLE); + style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | + WS_MAXIMIZEBOX | WS_BORDER | WS_DLGFRAME); + style |= WS_POPUP; + SetWindowLongPtrA(window, GWL_STYLE, style); + } + int LayoutMode() { static int mode = -1; @@ -360,6 +376,7 @@ void layoutWindows[layoutWindowCount].window = window; layoutWindows[layoutWindowCount].title = title; layoutWindows[layoutWindowCount].withSize = with_size; + layoutWindows[layoutWindowCount].bare = False; ++layoutWindowCount; } @@ -435,6 +452,13 @@ void continue; } + // + // Optional trailing keyword, "x,y,w,h,noframe". Searched for + // rather than parsed in place so a hand-edited line survives a + // stray space or a missing comma. + // + Logical bare = (strstr(equals + 1, "noframe") != NULL) ? True : False; + for (int i = 0; i < layoutWindowCount; ++i) { LayoutWindow &entry = layoutWindows[i]; @@ -483,8 +507,31 @@ void break; } + // + // Frame off, if the line asked. A bare window's rect IS its + // client rect, so whatever client area it has now is the size + // to hand back - which also makes the round trip stable: once + // bare, what Save records is already the client. + // + entry.bare = bare; + if (bare) + { + if (!size_it) + { + RECT client; + if (GetClientRect(target, &client)) + { + w = client.right; + h = client.bottom; + size_it = True; + } + } + StripWindowFrame(target); + } + SetWindowPos(target, NULL, x, y, w, h, - SWP_NOZORDER | SWP_NOACTIVATE | (size_it ? 0 : SWP_NOSIZE)); + SWP_NOZORDER | SWP_NOACTIVATE | + (size_it ? 0 : SWP_NOSIZE) | (bare ? SWP_FRAMECHANGED : 0)); ++restored; break; } @@ -520,7 +567,10 @@ void "# finished drag and on exit; =load restores it.\n" "# =<x>,<y>,<w>,<h>. The game window gets its size back too;\n" "# for the display panes the size is reference only, since theirs\n" - "# follows their content.\n", file); + "# follows their content.\n" + "# Append ,noframe to take that window's title bar and border off.\n" + "# Put it where you want it first - a bare window has nothing to\n" + "# drag by, so its line stops changing once the frame is gone.\n", file); int wrote = 0; for (int i = 0; i < layoutWindowCount; ++i) @@ -550,10 +600,13 @@ void continue; } RECT bounds = placement.rcNormalPosition; - fprintf(file, "%s=%ld,%ld,%ld,%ld\n", entry.title, + // the flag is the player's instruction, not something measured off + // the window, so a rewrite has to carry it back out + fprintf(file, "%s=%ld,%ld,%ld,%ld%s\n", entry.title, (long) bounds.left, (long) bounds.top, (long) (bounds.right - bounds.left), - (long) (bounds.bottom - bounds.top)); + (long) (bounds.bottom - bounds.top), + entry.bare ? ",noframe" : ""); ++wrote; } fclose(file); diff --git a/MUNGA_L4/L4MFDVIEW.h b/MUNGA_L4/L4MFDVIEW.h index f605f26..27666cc 100644 --- a/MUNGA_L4/L4MFDVIEW.h +++ b/MUNGA_L4/L4MFDVIEW.h @@ -180,7 +180,14 @@ protected: // save / adjust restore, then rewrite on each finished drag and // on teardown - the round trip // -// One "<title>=x,y,w,h" line per window. +// One "<title>=x,y,w,h" line per window, plus an optional ",noframe" +// that takes that window's title bar and border off - for a cockpit that +// fills a monitor edge to edge without -fit's all-or-nothing, or an +// exploded pane photographed without chrome. A bare window has nothing +// to drag by, so place it first and add the flag after; Save carries the +// flag back out, since it is an instruction rather than something +// measured off the window. Windows are always built framed, so deleting +// the flag is all it takes to get the frame back. // // Whether the size comes back depends on the window, which is why // Register takes it as a flag: diff --git a/pack-dist.ps1 b/pack-dist.ps1 index fb46cbc..de9a1aa 100644 --- a/pack-dist.ps1 +++ b/pack-dist.ps1 @@ -178,6 +178,12 @@ L4MFDSPLIT=1 # only: their size follows their content and their button banks, so an # old one is never restored over them. Arrange everything once with # save, then leave it on load. +# +# Each line in mfd_layout.cfg reads <title>=<x>,<y>,<w>,<h>, and you can +# append ,noframe to take that window's title bar and border off - a +# cockpit that fills the monitor edge to edge without -fit taking the +# whole screen. Put the window where you want it first: a bare window +# has nothing to drag by. Delete the flag to get the frame back. #RP412MFDLAYOUT=off # Size of the six secondary displays in the glass cockpit, as a