Skip to content

* April 2026 (Canary)#3328

Merged
PWagner1 merged 81 commits into
canaryfrom
alpha
Apr 20, 2026
Merged

* April 2026 (Canary)#3328
PWagner1 merged 81 commits into
canaryfrom
alpha

Conversation

@PWagner1
Copy link
Copy Markdown
Contributor

  • April 2026 (Canary) - TBR 20/04/2026

PWagner1 and others added 30 commits March 23, 2026 08:46
# Fix KryptonDockingManager.LoadConfigFromArray throws exception (#3227)

## Summary

Resolves an `ArgumentException` thrown when loading a docking configuration via `LoadConfigFromArray` in certain scenarios where a dockspace ends up with no pages after load.

## Problem

When calling `KryptonDockingManager.LoadConfigFromArray()`, the following exception could occur:

```
System.ArgumentException: 'Cannot set the 'Space' property more than once.'
Parameter name: SpaceControl'
  at Krypton.Docking.KryptonDockingSpace.set_SpaceControl(KryptonSpace value)
  at Krypton.Docking.KryptonDockingDockspace.LoadElementFromXml(XmlReader xmlReader, KryptonPageCollection pages)
  ...
```

This happened when:
- Loading a saved docking configuration where some pages referenced in the config were not present in the `pages` collection passed to the loader
- The workspace structure (cells, groups) was restored, but no pages could be matched
- Result: a dockspace with `PageCount == 0`
- The code disposed the empty dockspace and attempted `SpaceControl = null!` to clear the reference
- The `SpaceControl` setter in `KryptonDockingSpace` only allowed a single assignment and threw on any subsequent call (including when clearing with null)

## Solution

Modified the `SpaceControl` setter in `KryptonDockingSpace` to allow clearing the reference when passed `null`:

- **When `value == null`**: Unhook from the current control's events, set `_space = null`, and return (no throw)
- **When `value` is non-null**: Existing behavior unchanged — assignment allowed only once; subsequent non-null assignments still throw

This supports the "clear after dispose" case used when an empty dockspace is removed during config load.

## Changes

| File | Description |
|------|-------------|
| `Source/Krypton Components/Krypton.Docking/Elements Impl/KryptonDockingSpace.cs` | Updated `SpaceControl` setter to handle `null` for clearing the reference |

## Testing

1. Build the solution (e.g. via `run.cmd` or `Scripts/VS2022/build-stable.cmd`)
2. Load a saved docking config using `LoadConfigFromArray(Convert.FromBase64String(configText))` where:
   - The config was saved with a prior session, or
   - Some referenced pages are not in the current `pages` collection
3. Verify the config loads successfully without throwing
4. Run TestForm and validate docking save/load scenarios

## Related

- Fixes [#3227](#3227)
- Area: Docking
…aximized

# Fix KryptonForm multi-monitor maximization border overflow (#3249)

## Summary

Fixes [#3249](#3249): KryptonForm shows an extra border on the secondary monitor when maximized in a multi-monitor setup. Also resolves a CS8600 nullable reference type warning in `KryptonCustomPaletteBase`.

## Problem

In a multi-monitor environment, maximizing a KryptonForm causes a visible border or shadow area to extend into the secondary monitor. This does not occur with a standard WinForms Form. The issue is especially noticeable when the primary monitor is on the left and the secondary monitor is on the right (or vice versa).

Per [issue comment #3249](#3249 (comment)), when `UseThemeFormChromeBorderWidth` is enabled, `BorderWidths(FormBorderStyle)` always returned (0, 0). Windows still applies non-client area adjustments internally when maximized. Since Krypton assumed no border, the calculated maximized bounds ended up slightly larger than the monitor's working area, causing overflow onto the secondary monitor.

## Changes

### 1. `VisualForm.cs` – `OnWM_GETMINMAXINFO`

- **Fix:** Use primary-monitor coordinates for `ptMaxPosition` per MSDN documentation.
- For multi-monitor setups, `MINMAXINFO.ptMaxPosition` must be expressed relative to the primary monitor so Windows correctly places the maximized window on the target (possibly secondary) monitor.
- Added `MonitorFromWindow(IntPtr.Zero, MONITOR_DEFAULTTOPRIMARY)` to obtain primary monitor info and adjusted the position calculation.
- References: [StackOverflow](https://stackoverflow.com/questions/35984883/handling-wm-getminmaxinfo-for-multiple-monitors).

### 2. `PaletteFormBorder.cs` – `BorderWidths`

- **Fix:** Removed the `UseThemeFormChromeBorderWidth` branch that returned (0, 0).
- `BorderWidths` now always returns the actual system metrics based on `FormBorderStyle` (e.g. `SM_CXSIZEFRAME`, `SM_CYSIZEFRAME` for `Sizable`).
- This allows `UpdateRegionForMaximized` in KryptonForm to compute the maximized region correctly, accounting for the non-client area that Windows reserves internally.

### 3. `KryptonCustomPaletteBase.cs` – CS8600 warning

- **Fix:** Resolved CS8600 (converting possible null to non-nullable type) in the theme export path.
- `TypeConverter.ConvertTo` returns `object?`; the previous code cast directly to `string`, causing the warning.
- Now uses a local variable and `?.ToString() ?? string.Empty` to handle possible null safely.

## Testing

- Build solution for all target frameworks (net472, net48, net481, net8.0-windows, net9.0-windows, net10.0-windows, net11.0-windows).
- Run TestForm and maximize a KryptonForm on the primary monitor with a secondary monitor attached; the border should no longer extend onto the secondary monitor.
- Verify palette XML export still serializes property values correctly (regression check for #3164).

## Checklist

- [x] Fixes #3249
- [x] No breaking changes
- [x] Code follows project conventions (AGENTS.md, .editorconfig)
- [x] Nullable reference type warning resolved
# Fix Ribbon large button image-to-text separator not DPI-scaled

## Summary

Resolves [#3225](#3225).

The separator between the image and text in Ribbon large buttons was hardcoded at 1 pixel and did not scale with DPI. At 150% DPI (PerMonitorV2), the `_largeImagePadding` scales correctly (3→4, 2→3, 3→4) but the 1px separator stayed at 1px, causing text labels to appear too close to the icons.

## Changes

Apply DPI scaling (`FactorDpiY`) to the image-to-text separator, consistent with how image padding is scaled:

**Before:**

```csharp
contentLayout.Add(new ViewLayoutRibbonSeparator(1, false), ViewDockStyle.Bottom);
```

**After:**

```csharp
contentLayout.Add(new ViewLayoutRibbonSeparator((int)(1 * FactorDpiY), false), ViewDockStyle.Bottom);
```

## Files Modified

| File | Change |
|------|--------|
| `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupButton.cs` | DPI-scale separator in `CreateLargeButtonView()` |
| `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupColorButton.cs` | DPI-scale separator in `CreateLargeButtonView()` |
| `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupGallery.cs` | DPI-scale separator in `CreateLargeButtonView()` |
| `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupLabel.cs` | DPI-scale separator in large label view |
| `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupCheckBox.cs` | DPI-scale separator in large check box view |
| `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupRadioButton.cs` | DPI-scale separator in large radio button view |
| `Documents/Changelog/Changelog.md` | Added changelog entry |

## Testing

- Verified at 100% and 150% display scaling with `HighDpiMode.PerMonitorV2`
- Manual validation via TestForm Ribbon scenarios
- No linter errors; changes are surgical and preserve existing structure

## Breaking Changes

None.
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 2 to 3.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Commits](microsoft/setup-msbuild@v2...v3)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps
[microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild)
from 2 to 3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/microsoft/setup-msbuild/releases">microsoft/setup-msbuild's
releases</a>.</em></p>
<blockquote>
<h2>v3 Update to move to Node24</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix small typo in README.md by <a
href="https://github.com/GeckoEidechse"><code>@​GeckoEidechse</code></a>
in <a
href="https://redirect.github.com/microsoft/setup-msbuild/pull/129">microsoft/setup-msbuild#129</a></li>
<li>Update to Node24 by <a
href="https://github.com/timheuer"><code>@​timheuer</code></a> in <a
href="https://redirect.github.com/microsoft/setup-msbuild/pull/145">microsoft/setup-msbuild#145</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/GeckoEidechse"><code>@​GeckoEidechse</code></a>
made their first contribution in <a
href="https://redirect.github.com/microsoft/setup-msbuild/pull/129">microsoft/setup-msbuild#129</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/microsoft/setup-msbuild/compare/v2...v3">https://github.com/microsoft/setup-msbuild/compare/v2...v3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/30375c66a4eea26614e0d39710365f22f8b0af57"><code>30375c6</code></a>
Merge updates to move to node24</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/53bd3e099e24147f05f31e7f8f5ccb5f57e47d60"><code>53bd3e0</code></a>
Merge branch 'timheuer/node24' of <a
href="https://github.com/microsoft/setup-msbuild">https://github.com/microsoft/setup-msbuild</a>
...</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/4031508ab2f2ca229b52e56ecf4760f8907a4e84"><code>4031508</code></a>
fix: move to node24</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/dfc05ccabba9e508d9319c9946e7df71c7c204ab"><code>dfc05cc</code></a>
feat: enhance MSBuild setup summary in workflow 🛠️</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/f62e96d7284c99d8ffd6299ac0a0718c917cebc0"><code>f62e96d</code></a>
fix: change test workflow for arch</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/c77b6bc497ea976e6602b3991bf1943869c75a7f"><code>c77b6bc</code></a>
fix: move to node24</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/767f00a3f09872d96a0cb9fcd5e6a4ff33311330"><code>767f00a</code></a>
[skip ci] Merge pull request <a
href="https://redirect.github.com/microsoft/setup-msbuild/issues/129">#129</a>
from GeckoEidechse/fix/readme-typo</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/442baebb598d469e9e428de529ec7948ed876e27"><code>442baeb</code></a>
Fix small typo in README.md</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/70b70342ae97ca98d5eaad06cafd26d30f9592a9"><code>70b7034</code></a>
Update README.md [skip ci]</li>
<li><a
href="https://github.com/microsoft/setup-msbuild/commit/31e0ba28c780f4bd10cfc8075d1fff655386e214"><code>31e0ba2</code></a>
Update README examples [skip ci]</li>
<li>See full diff in <a
href="https://github.com/microsoft/setup-msbuild/compare/v2...v3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=microsoft/setup-msbuild&package-manager=github_actions&previous-version=2&new-version=3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
#3252)

…aximized

# Fix KryptonForm multi-monitor maximization border overflow (#3249)

## Summary

Fixes
[#3249](#3249):
KryptonForm shows an extra border on the secondary monitor when
maximized in a multi-monitor setup. Also resolves a CS8600 nullable
reference type warning in `KryptonCustomPaletteBase`.

## Problem

In a multi-monitor environment, maximizing a KryptonForm causes a
visible border or shadow area to extend into the secondary monitor. This
does not occur with a standard WinForms Form. The issue is especially
noticeable when the primary monitor is on the left and the secondary
monitor is on the right (or vice versa).

Per [issue comment
#3249](#3249 (comment)),
when `UseThemeFormChromeBorderWidth` is enabled,
`BorderWidths(FormBorderStyle)` always returned (0, 0). Windows still
applies non-client area adjustments internally when maximized. Since
Krypton assumed no border, the calculated maximized bounds ended up
slightly larger than the monitor's working area, causing overflow onto
the secondary monitor.

## Changes

### 1. `VisualForm.cs` – `OnWM_GETMINMAXINFO`

- **Fix:** Use primary-monitor coordinates for `ptMaxPosition` per MSDN
documentation.
- For multi-monitor setups, `MINMAXINFO.ptMaxPosition` must be expressed
relative to the primary monitor so Windows correctly places the
maximized window on the target (possibly secondary) monitor.
- Added `MonitorFromWindow(IntPtr.Zero, MONITOR_DEFAULTTOPRIMARY)` to
obtain primary monitor info and adjusted the position calculation.
- References:
[StackOverflow](https://stackoverflow.com/questions/35984883/handling-wm-getminmaxinfo-for-multiple-monitors).

### 2. `PaletteFormBorder.cs` – `BorderWidths`

- **Fix:** Removed the `UseThemeFormChromeBorderWidth` branch that
returned (0, 0).
- `BorderWidths` now always returns the actual system metrics based on
`FormBorderStyle` (e.g. `SM_CXSIZEFRAME`, `SM_CYSIZEFRAME` for
`Sizable`).
- This allows `UpdateRegionForMaximized` in KryptonForm to compute the
maximized region correctly, accounting for the non-client area that
Windows reserves internally.

### 3. `KryptonCustomPaletteBase.cs` – CS8600 warning

- **Fix:** Resolved CS8600 (converting possible null to non-nullable
type) in the theme export path.
- `TypeConverter.ConvertTo` returns `object?`; the previous code cast
directly to `string`, causing the warning.
- Now uses a local variable and `?.ToString() ?? string.Empty` to handle
possible null safely.

## Testing

- Build solution for all target frameworks (net472, net48, net481,
net8.0-windows, net9.0-windows, net10.0-windows, net11.0-windows).
- Run TestForm and maximize a KryptonForm on the primary monitor with a
secondary monitor attached; the border should no longer extend onto the
secondary monitor.
- Verify palette XML export still serializes property values correctly
(regression check for #3164).

<img width="672" height="259" alt="image"
src="https://github.com/user-attachments/assets/27fc9d67-8e87-461c-979b-252193f01f74"
/>
# Fix crash when using custom palette with title-bar / toolbar button specs (#3256)

## Summary

Resolves a crash reported when interacting with controls (for example a `KryptonTreeView`) while using **`PaletteMode.Custom`** with **`KryptonCustomPaletteBase`**. The failure surfaced as the integrated “Not Implemented” dialog pointing at `GetPaletteButtonSpec` in `KryptonCustomPaletteBase.cs`.

## Root cause

`KryptonFormTitleBar` creates standard toolbar **`ButtonSpecAny`** entries with types such as **`New`**, **`Open`**, **`Save`**, and so on. Those types map to **`PaletteButtonSpecStyle`** values that must be resolved through the active palette.

If any **`PaletteButtonSpecStyle`** still fell through the **`switch`** in **`KryptonCustomPaletteBase.GetPaletteButtonSpec`**, the **`default`** branch called **`DebugTools.NotImplemented`**, which blocks the UI and throws. A repaint triggered by ordinary input (e.g. clicking the tree view) is enough to hit that path.

Related context: handling for the full set of toolbar-related **`PaletteButtonSpecStyle`** values in this method was expanded for **#3072**; this change completes the behaviour for **#3256** by making the **`default`** path safe when an unexpected or out-of-range value appears (forward compatibility, bad serialization, etc.).

## Changes

- **`KryptonCustomPaletteBase.GetPaletteButtonSpec`**: **`default`** now **`Debug.Assert`s** (debug builds) with the numeric style value, then **returns `ButtonSpecs.Generic`** instead of **`DebugTools.NotImplemented`**, so the application does not hard-crash.
- **`Documents/Changelog/Changelog.md`**: entry for **#3256**.

## Testing

- Run **Test Form** → **Tree View** example (or **Tree View Test**) with **`KryptoManager.GlobalPaletteMode = PaletteMode.Custom`** and a **`KryptonCustomPaletteBase`** instance as **`GlobalCustomPalette`**.
- Click the **`KryptonTreeView`** and interact with nodes; confirm no **“Not Implemented – GetPaletteButtonSpec”** dialog and no related exception.

## References

- Closes / fixes [Tree View Event is Crashing (#3256)](#3256)
- Related: [Some samples do not work (#3072)](#3072)
# Fix crash when using custom palette with title-bar / toolbar button
specs (#3256)

## Summary

Resolves a crash reported when interacting with controls (for example a
`KryptonTreeView`) while using **`PaletteMode.Custom`** with
**`KryptonCustomPaletteBase`**. The failure surfaced as the integrated
“Not Implemented” dialog pointing at `GetPaletteButtonSpec` in
`KryptonCustomPaletteBase.cs`.

## Root cause

`KryptonFormTitleBar` creates standard toolbar **`ButtonSpecAny`**
entries with types such as **`New`**, **`Open`**, **`Save`**, and so on.
Those types map to **`PaletteButtonSpecStyle`** values that must be
resolved through the active palette.

If any **`PaletteButtonSpecStyle`** still fell through the **`switch`**
in **`KryptonCustomPaletteBase.GetPaletteButtonSpec`**, the
**`default`** branch called **`DebugTools.NotImplemented`**, which
blocks the UI and throws. A repaint triggered by ordinary input (e.g.
clicking the tree view) is enough to hit that path.

Related context: handling for the full set of toolbar-related
**`PaletteButtonSpecStyle`** values in this method was expanded for
**#3072**; this change completes the behaviour for **#3256** by making
the **`default`** path safe when an unexpected or out-of-range value
appears (forward compatibility, bad serialization, etc.).

## Changes

- **`KryptonCustomPaletteBase.GetPaletteButtonSpec`**: **`default`** now
**`Debug.Assert`s** (debug builds) with the numeric style value, then
**returns `ButtonSpecs.Generic`** instead of
**`DebugTools.NotImplemented`**, so the application does not hard-crash.
- **`Documents/Changelog/Changelog.md`**: entry for **#3256**.

## Testing

- Run **Test Form** → **Tree View** example (or **Tree View Test**) with
**`KryptoManager.GlobalPaletteMode = PaletteMode.Custom`** and a
**`KryptonCustomPaletteBase`** instance as **`GlobalCustomPalette`**.
- Click the **`KryptonTreeView`** and interact with nodes; confirm no
**“Not Implemented – GetPaletteButtonSpec”** dialog and no related
exception.

## References

- Closes / fixes [Tree View Event is Crashing
(#3256)](#3256)
- Related: [Some samples do not work
(#3072)](#3072)

<img width="681" height="260" alt="image"
src="https://github.com/user-attachments/assets/10ef9bab-1848-4596-a2b0-9279bd8e0de4"
/>
- Remove TODO comments
- No changelog required
* - No issue connected.
- Updates startscreen.CreateButton to use generics for the form parameter.
- Refactor the PaletteViewer form and make it attach the KryptonManager internally.
- In method OnCommandLinkTestButtonClick remove the exception for the PaletteViewer form.
- Removed a debug message.

* - No issue connected.
- Updates startscreen.CreateButton to use generics for the form parameter.
- Refactor the PaletteViewer form and make it attach the KryptonManager internally.
- In method OnCommandLinkTestButtonClick remove the exception for the PaletteViewer form.
- Removed a debug message.
…3253)

# Fix Ribbon large button image-to-text separator not DPI-scaled

## Summary

Resolves
[#3225](#3225).

The separator between the image and text in Ribbon large buttons was
hardcoded at 1 pixel and did not scale with DPI. At 150% DPI
(PerMonitorV2), the `_largeImagePadding` scales correctly (3→4, 2→3,
3→4) but the 1px separator stayed at 1px, causing text labels to appear
too close to the icons.

## Changes

Apply DPI scaling (`FactorDpiY`) to the image-to-text separator,
consistent with how image padding is scaled:

**Before:**

```csharp
contentLayout.Add(new ViewLayoutRibbonSeparator(1, false), ViewDockStyle.Bottom);
```

**After:**

```csharp
contentLayout.Add(new ViewLayoutRibbonSeparator((int)(1 * FactorDpiY), false), ViewDockStyle.Bottom);
```

## Files Modified

| File | Change |
|------|--------|
| `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupButton.cs` | DPI-scale
separator in `CreateLargeButtonView()` | | `Krypton.Ribbon/View
Draw/ViewDrawRibbonGroupColorButton.cs` | DPI-scale separator in
`CreateLargeButtonView()` | | `Krypton.Ribbon/View
Draw/ViewDrawRibbonGroupGallery.cs` | DPI-scale separator in
`CreateLargeButtonView()` | | `Krypton.Ribbon/View
Draw/ViewDrawRibbonGroupLabel.cs` | DPI-scale separator in large label
view | | `Krypton.Ribbon/View Draw/ViewDrawRibbonGroupCheckBox.cs` |
DPI-scale separator in large check box view | | `Krypton.Ribbon/View
Draw/ViewDrawRibbonGroupRadioButton.cs` | DPI-scale separator in large
radio button view | | `Documents/Changelog/Changelog.md` | Added
changelog entry |

## Testing

- Verified at 100% and 150% display scaling with
`HighDpiMode.PerMonitorV2`
- Manual validation via TestForm Ribbon scenarios
- No linter errors; changes are surgical and preserve existing structure

## Breaking Changes

None.

<img width="697" height="113" alt="image"
src="https://github.com/user-attachments/assets/ae34673b-c416-46bf-aa43-7855975214b4"
/>

Warnings unrelated to this PR
# PR: Fix `run.cmd`, NuGet update scripts, and workspace clean helpers

## Summary

Repairs the interactive build menu (`run.cmd`), consolidates duplicated clean-up logic, and fixes all three `update-nuget.cmd` variants (`Scripts\VS2022`, `Scripts\Current`, `Scripts\Build`) so NuGet maintenance and “return to main menu” behave correctly when launched from `run.cmd`.

## Problems addressed

### `run.cmd`

- **Duplicate `:nugettools` label** — The first definition redirected to the archives menu, so main menu item **6 (NuGet Tools)** never reached the real NuGet flow.
- **Invalid `:packlts` target** — Pack menu option 4 referenced a missing label (`:packlts`); corrected to `:packltsmenu`.
- **Redundant / misleading `:cleanproject` block** — Removed the duplicate label that only jumped to itself.
- **Fall-through bugs** — Several labels ran into the next section without `goto`:
  - Debug path continued into NuGet tools after the nightly build.
  - NuGet “build packages” submenu invalid input fell through into nightly package steps.
  - Nightly package flow fell through into rebuild / other targets.
  - Rebuild path could continue into “build and pack nightly” after the child script returned.
- **WebView2** — Main menu item **8** pointed at a short `:webview2menu` that then fell through into `:updatenuget`. Menu now uses **`:webview2tools`**, and WebView2 scripts are invoked from **`Scripts\WebVew2`** via `pushd "%~dp0Scripts\WebVew2"` and `call` (folder name matches the repo as-is).
- **Missing labels** — NuGet package submenu options 2–5 jumped to non-existent labels; added **`:buildcanarypackages`**, **`:buildstablepackages`**, **`:buildstablelitepackages`**, **`:buildltspackages`** (clean + appropriate `build-*.cmd` `Pack` / `PackLite`).
- **Workspace clean-up** — Introduced **`:cleanbinandobj`**, **`:cleanlogs`**, and **`:cleanrootbuildlog`** and replaced repeated `rd`/`del` blocks.

### `update-nuget.cmd` (all three script folders)

- **“Go back to main menu”** — Starting nested `run.cmd` without `call` broke return to the outer `run.cmd`. The script now returns with **`exit /b 2`**; **`run.cmd`** checks **`UPDATE_NUGET_EC`** and **`goto mainmenu`** when the code is `2`.
- **Wrong NuGet command for “update client”** — `nuget update` updates solution packages, not `nuget.exe`. Client update uses **`nuget update -Self`**; second menu action is **`nuget locals http-cache -clear`**.
- **Wrong working directory for `run.cmd`** — Removed reliance on `cd ..` to find the repo root for nested `run.cmd` (superseded by return-code handling).
- **Unsafe `if %answer%==…`** — Replaced with quoted comparisons for empty input.
- **`exit` vs `exit /b`** — **`:end`** uses **`endlocal`** and **`exit /b 0`** when the script is **`call`**ed from `run.cmd` so the parent session is not torn down.
- **Duplicate menu** — Single **`:setmenu`** entry via initial **`goto setmenu`**.
- **`where nuget`** — Clear error if `nuget.exe` is not on `PATH`.

## Files touched

| Path | Change |
|------|--------|
| `run.cmd` | Menu fixes, flow/`goto` corrections, WebView2 paths, package targets, clean helpers, NuGet exit-code handling |
| `Scripts\VS2022\update-nuget.cmd` | Rewritten menu, commands, return codes, `call`-safe exit |
| `Scripts\Current\update-nuget.cmd` | Same as VS2022 variant |
| `Scripts\Build\update-nuget.cmd` | Same as VS2022 variant |
| `Documents\PR-run-cmd-and-build-scripts.md` | This PR description (optional to keep or delete after merge) |

## How to verify

1. Run **`run.cmd`**, pick a VS script set, and exercise:
   - **6** — NuGet Tools → option **3** — should return to **main menu** (not archives or a stuck submenu).
   - **7** → **10** (Update NuGet tools) → option **3** — should return to **main menu**.
   - **3** (Create NuGet packages) → **4** (LTS) — should open the LTS pack submenu (no “label not found”).
   - **8** — WebView2 — should show the WebView2 submenu and run scripts from `Scripts\WebVew2`.
2. From **NuGet Tools**, run **1** or **2** only if `nuget.exe` is on `PATH`; confirm sensible errors if it is missing.

## Notes

- **`Scripts\WebVew2`** is the existing folder spelling in the repo; paths intentionally match it.
- **`Documents\PR-run-cmd-and-build-scripts.md`** is for copy-paste into the GitHub/Git PR description; remove it from the branch if you prefer not to commit PR text.

## Suggested commit / PR title

`Fix run.cmd flow, NuGet update scripts, and workspace clean helpers`
…#3250)

# Fix KryptonDockingManager.LoadConfigFromArray throws exception (#3227)

## Summary

Resolves an `ArgumentException` thrown when loading a docking
configuration via `LoadConfigFromArray` in certain scenarios where a
dockspace ends up with no pages after load.

## Problem

When calling `KryptonDockingManager.LoadConfigFromArray()`, the
following exception could occur:

```
System.ArgumentException: 'Cannot set the 'Space' property more than once.'
Parameter name: SpaceControl'
  at Krypton.Docking.KryptonDockingSpace.set_SpaceControl(KryptonSpace value)
  at Krypton.Docking.KryptonDockingDockspace.LoadElementFromXml(XmlReader xmlReader, KryptonPageCollection pages)
  ...
```

This happened when:
- Loading a saved docking configuration where some pages referenced in
the config were not present in the `pages` collection passed to the
loader
- The workspace structure (cells, groups) was restored, but no pages
could be matched
- Result: a dockspace with `PageCount == 0`
- The code disposed the empty dockspace and attempted `SpaceControl =
null!` to clear the reference
- The `SpaceControl` setter in `KryptonDockingSpace` only allowed a
single assignment and threw on any subsequent call (including when
clearing with null)

## Solution

Modified the `SpaceControl` setter in `KryptonDockingSpace` to allow
clearing the reference when passed `null`:

- **When `value == null`**: Unhook from the current control's events,
set `_space = null`, and return (no throw)
- **When `value` is non-null**: Existing behavior unchanged — assignment
allowed only once; subsequent non-null assignments still throw

This supports the "clear after dispose" case used when an empty
dockspace is removed during config load.

## Changes

| File | Description |
|------|-------------|
| `Source/Krypton Components/Krypton.Docking/Elements
Impl/KryptonDockingSpace.cs` | Updated `SpaceControl` setter to handle
`null` for clearing the reference |

## Testing

1. Build the solution (e.g. via `run.cmd` or
`Scripts/VS2022/build-stable.cmd`)
2. Load a saved docking config using
`LoadConfigFromArray(Convert.FromBase64String(configText))` where:
   - The config was saved with a prior session, or
   - Some referenced pages are not in the current `pages` collection
3. Verify the config loads successfully without throwing
4. Run TestForm and validate docking save/load scenarios

## Related

- Fixes
[#3227](#3227)
- Area: Docking

<img width="702" height="133" alt="image"
src="https://github.com/user-attachments/assets/fe24d720-1a0f-4355-a4f1-cfbc090449d4"
/>

Warnings unrelated to this PR.
## Summary
- Fix aggregate package metadata for `Krypton.Standard.Toolkit` so NuGet does not emit project-reference dependencies.
- Add `SuppressDependenciesWhenPacking=true` in the aggregator project to prevent invalid dependency IDs (notably `Krypton.Navigator.Utilities`) from being written to package dependency groups.
- Preserve current package behavior of shipping toolkit binaries directly inside the package.

## Problem
Installing `Krypton.Standard.Toolkit` can fail with:

`Unable to find package Krypton.Navigator.Utilities`

`Krypton.Navigator.Utilities` is an internal assembly/project in this repository, not a published standalone NuGet package. If emitted as a dependency, restore fails on consumer machines.

## Root Cause
The aggregate package project references multiple internal projects to build and collect outputs. During packing, project references can be translated into NuGet dependency metadata unless explicitly suppressed.

## Fix
- File updated: `Source/Krypton Components/Krypton.Standard.Toolkit/Krypton.Standard.Toolkit.csproj`
- Added:
  - `<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>`

This keeps the package self-contained and prevents invalid dependency declarations.

## Impact
- Prevents restore/install failures caused by non-existent dependency package IDs.
- No runtime behavior change for toolkit assemblies.
- Affects package metadata generation only.
PWagner1 and others added 10 commits April 14, 2026 18:04
Restrict the special-case logic to FormBorderStyle.Sizable when the form
has no caption text and no control box.

This avoids affecting tool window styles, which may legitimately have
no title text while still requiring non-client painting.
## Summary

- Implemented
[#2125](#2125)
by adding configurable toast notification icon dimensions via
`NotificationIconWidth` and `NotificationIconHeight`.
- Added new icon size properties to `KryptonBasicToastData`,
`KryptonUserInputToastData`, and `KryptonCommonToastData` with
backward-compatible defaults (`128x128`).
- Centralized icon size resolution in `GraphicsExtensionUtilities` and
updated basic toast visual forms (LTR/RTL, with/without progress bar) to
render and layout icons using resolved size values.
- Updated docs in `Documents/KryptonToastNotification.md` and
`Documents/KryptonToastNotificationManager.md` to describe icon sizing
and current toast data types.
- Added a quick usage example in `ToastNotificationQuickTestForm`
showing a compact icon (`16x16`).
- Fixed `net472` compile failure in `Krypton.Navigator.Utilities` by
linking `WIN32ScrollBars.cs` alongside linked `PlatformInvoke.cs`,
resolving missing type errors (`CS0246`) for
`WIN32ScrollBars.ScrollInfo`.

## Why

Toast icons were fixed at `128x128`, which made notifications visually
heavy in many scenarios. This change allows consumers to set icon
dimensions per notification while preserving existing behavior when size
is not specified. In addition, `Krypton.Navigator.Utilities` links
`PlatformInvoke.cs` from `Krypton.Toolkit`; adding the matching
`WIN32ScrollBars` compile item keeps linked source dependencies intact
across target frameworks.

## Test Plan

- [ ] Open `TestForm` and trigger the basic toast quick test; verify
icon renders at `16x16` using the updated sample data.
- [ ] Trigger basic toast notifications without setting icon size;
verify default behavior remains `128x128`.
- [ ] Trigger basic progress bar toast notifications and verify custom
icon sizing is respected.
- [ ] Verify RTL basic toast notifications (with and without progress
bar) also respect custom icon dimensions.
- [ ] Verify invalid icon sizes (`<= 0`) gracefully fall back to default
size.
- [ ] Confirm documentation examples for icon sizing compile
conceptually against current API names (`KryptonBasicToastData`,
`KryptonUserInputToastData`).
- [ ] Build `Krypton.Navigator.Utilities` for `net472` and verify
`PlatformInvoke.cs` no longer reports `CS0246` for `WIN32ScrollBars`.

## Why

Toast icons were fixed at `128x128`, which made notifications visually
heavy in many scenarios. This change allows consumers to set icon
dimensions per notification while preserving existing behavior when size
is not specified.

## Test Plan

- [ ] Open `TestForm` and trigger the basic toast quick test; verify
icon renders at `16x16` using the updated sample data.
- [ ] Trigger basic toast notifications without setting icon size;
verify default behavior remains `128x128`.
- [ ] Trigger basic progress bar toast notifications and verify custom
icon sizing is respected.
- [ ] Verify RTL basic toast notifications (with and without progress
bar) also respect custom icon dimensions.
- [ ] Verify invalid icon sizes (`<= 0`) gracefully fall back to default
size.
- [ ] Confirm documentation examples for icon sizing compile
conceptually against current API names (`KryptonBasicToastData`,
`KryptonUserInputToastData`).

<img width="662" height="256" alt="image"
src="https://github.com/user-attachments/assets/085a8ac8-f717-4e3d-be95-5570d0303e57"
/>
…obox-kryptoncontextmenuprogressbar-need-to-be-implemented
Updated  code style
…tons and text (#3311)

Fixed an issue in KryptonForm where a white title bar area was still
rendered
when ControlBox was set to false and the form Text was empty.

The form now correctly hides the non-client title area when no caption
or control buttons are present, ensuring consistent visual behavior.

#2914
## Summary

- Add a pack-time normalization target in `Krypton.Standard.Toolkit.csproj` to align nuspec framework aliases with package `lib/ref` folder names.
- Ensure generated dependency groups include exact matches for:
  - `net8.0-windows7.0`
  - `net9.0-windows7.0`
  - `net10.0-windows7.0`
  - `net11.0-windows7.0`
  - `.NETFramework4.7.2`
  - `.NETFramework4.8`
  - `.NETFramework4.8.1`
- Prevent framework mismatch warnings (for example `NU5128`) caused by non-aligned TFM naming between dependency groups and packaged assets.

## Why

Nightly packaging produced dependency-group TFMs that did not exactly match the framework names used in packaged `lib/ref` paths. This causes NuGet analysis warnings and can lead to incorrect framework asset resolution.

## Implementation Details

- Hook `NormalizePackTargetFrameworkAliases` into `GenerateNuspecDependsOn`.
- Remap pack metadata framework identifiers before nuspec generation:
  - `net472` -> `.NETFramework4.7.2`
  - `net48` -> `.NETFramework4.8`
  - `net481` -> `.NETFramework4.8.1`
  - `net8.0-windows` -> `net8.0-windows7.0`
  - `net9.0-windows` -> `net9.0-windows7.0`
  - `net10.0-windows` -> `net10.0-windows7.0`
  - `net11.0-windows` -> `net11.0-windows7.0`
- Apply the same alias mapping to:
  - `_TargetFrameworks`
  - `_FrameworksWithSuppressedDependencies`
  - `_FrameworkAssemblyReferences` (metadata `TargetFramework`)

## Test Plan

- [x] Run pack for `Krypton.Standard.Toolkit` with nightly/all-TFM settings.
- [x] Inspect generated nuspec in the resulting package.
- [x] Confirm dependency groups exist for all expected framework aliases listed above.
- [x] Confirm no linter errors in the edited project file.

## Notes

- This change only affects pack-time metadata generation and does not change compile-time target frameworks.
…obox-kryptoncontextmenuprogressbar-need-to-be-implemented
@PWagner1 PWagner1 added this to the Version 110 milestone Apr 16, 2026
@PWagner1 PWagner1 requested a review from a team as a code owner April 16, 2026 15:27
@PWagner1 PWagner1 added the version:110 All things to do with V110. label Apr 16, 2026
PWagner1 and others added 14 commits April 16, 2026 16:28
Bumps [NuGet/setup-nuget](https://github.com/nuget/setup-nuget) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/nuget/setup-nuget/releases)
- [Commits](NuGet/setup-nuget@v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: NuGet/setup-nuget
  dependency-version: 3.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [NuGet/setup-nuget](https://github.com/nuget/setup-nuget) from
3.0.0 to 3.1.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nuget/setup-nuget/releases">NuGet/setup-nuget's
releases</a>.</em></p>
<blockquote>
<h2>v3.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Remove DEP0169 <code>url.parse()</code> usage from setup-nuget v3
runtime path by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/NuGet/setup-nuget/pull/233">NuGet/setup-nuget#233</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/NuGet/setup-nuget/compare/v3...v3.1.0">https://github.com/NuGet/setup-nuget/compare/v3...v3.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/NuGet/setup-nuget/commit/b26b823c478ee115be5c9403e62c90b0bf943843"><code>b26b823</code></a>
Remove DEP0169 <code>url.parse()</code> usage from setup-nuget v3
runtime path (<a
href="https://redirect.github.com/nuget/setup-nuget/issues/233">#233</a>)</li>
<li><a
href="https://github.com/NuGet/setup-nuget/commit/357a9866f42522d4e35e9920a33ca23903f1d0e2"><code>357a986</code></a>
Upgrade NuGet setup action to version 3 (<a
href="https://redirect.github.com/nuget/setup-nuget/issues/226">#226</a>)</li>
<li>See full diff in <a
href="https://github.com/nuget/setup-nuget/compare/v3.0.0...v3.1.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=NuGet/setup-nuget&package-manager=github_actions&previous-version=3.0.0&new-version=3.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
#3321)

… to be implemented

## Summary

- Implements
[#1673](#1673)
by completing `KryptonContextMenuProgressBar` and wiring it into context
menu rendering, design-time editors, and collection type restrictions.
- Enables the existing ComboBox option in the context menu collection
editor and adds explicit icon mapping for text box/combo box/progress
bar entries in the tree.
- Adds a small TestForm usage example and updates the changelog entry
for the V110 nightly section.

## What Changed

- Added `ViewDrawMenuProgressBar` to host `KryptonProgressBar` inside
context menus.
- Replaced the commented stub in `KryptonContextMenuProgressBar` with a
full implementation:
  - `GenerateView`, `Dispose`, and standard context-menu item overrides.
- Exposed properties: `Minimum`, `Maximum`, `Value`, `Step`, `Style`,
`MarqueeAnimationSpeed`, `MinimumWidth`, `Enabled`.
- Added `KryptonContextMenuProgressBar` to allowed item-type lists:
  - `KryptonContextMenuCollection`
  - `KryptonContextMenuItemCollection`
  - `KryptonContextMenuCollectionEditor`
  - `KryptonContextMenuItemCollectionEditor`
- Updated `KryptonContextMenuCollectionForm`:
  - Added **Add ProgressBar** button.
  - Enabled **Add ComboBox** button.
- Added icon list entries and tree-node icon mapping for
`KryptonContextMenuTextBox`, `KryptonContextMenuComboBox`, and
`KryptonContextMenuProgressBar`.
  - Switched unknown item icon fallback to a safe default.
- Added a TestForm sample insertion of `KryptonContextMenuProgressBar`
in `ButtonsTest`.
- Added changelog entry for #1673 in `Documents/Changelog/Changelog.md`.

## Manual Test Plan

- [ ] Open a form using the context menu collection editor and verify
**Add ComboBox** is enabled.
- [ ] In the same editor, verify **Add ProgressBar** appears and creates
a `KryptonContextMenuProgressBar` item.
- [ ] Confirm text box/combo box/progress bar entries show appropriate
icons in the hierarchy tree.
- [ ] Run TestForm and open the button context menu in `ButtonsTest`;
verify the progress bar item is visible and laid out correctly.
- [ ] Confirm normal/disabled context menu behavior still works for
existing items.

## Notes

- Full solution build currently reports existing environment/resource
issues (`MSB3822`/`MSB3823`) on legacy target frameworks; these are not
introduced by this change set.

<img width="669" height="261" alt="image"
src="https://github.com/user-attachments/assets/54027c94-d3f6-4966-a105-2379bda56bf0"
/>
## Summary

- Add a pack-time normalization target in
`Krypton.Standard.Toolkit.csproj` to align nuspec framework aliases with
package `lib/ref` folder names.
- Ensure generated dependency groups include exact matches for:
  - `net8.0-windows7.0`
  - `net9.0-windows7.0`
  - `net10.0-windows7.0`
  - `net11.0-windows7.0`
  - `.NETFramework4.7.2`
  - `.NETFramework4.8`
  - `.NETFramework4.8.1`
- Prevent framework mismatch warnings (for example `NU5128`) caused by
non-aligned TFM naming between dependency groups and packaged assets.

## Why

Nightly packaging produced dependency-group TFMs that did not exactly
match the framework names used in packaged `lib/ref` paths. This causes
NuGet analysis warnings and can lead to incorrect framework asset
resolution.

## Implementation Details

- Hook `NormalizePackTargetFrameworkAliases` into
`GenerateNuspecDependsOn`.
- Remap pack metadata framework identifiers before nuspec generation:
  - `net472` -> `.NETFramework4.7.2`
  - `net48` -> `.NETFramework4.8`
  - `net481` -> `.NETFramework4.8.1`
  - `net8.0-windows` -> `net8.0-windows7.0`
  - `net9.0-windows` -> `net9.0-windows7.0`
  - `net10.0-windows` -> `net10.0-windows7.0`
  - `net11.0-windows` -> `net11.0-windows7.0`
- Apply the same alias mapping to:
  - `_TargetFrameworks`
  - `_FrameworksWithSuppressedDependencies`
  - `_FrameworkAssemblyReferences` (metadata `TargetFramework`)

## Test Plan

- [x] Run pack for `Krypton.Standard.Toolkit` with nightly/all-TFM
settings.
- [x] Inspect generated nuspec in the resulting package.
- [x] Confirm dependency groups exist for all expected framework aliases
listed above.
- [x] Confirm no linter errors in the edited project file.

## Notes

- This change only affects pack-time metadata generation and does not
change compile-time target frameworks.
…it.KryptonManager' threw an exception.'

# PR description

## Title (suggested)

Fix net48 `System.Resources.Extensions` load failure, net10/11 Ribbon CS7069, and harden color-table font init

## Summary

This PR addresses **startup failures on .NET Framework 4.8** when preserialized resources load `System.Resources.Extensions` with an assembly-version mismatch, **CS7069 build breaks** for `Krypton.Ribbon` on **net10.0-windows** / **net11.0-windows**, and **defensive font initialization** in Microsoft 365 / 365 color tables when system menu fonts are missing or invalid.

Related: [Issue #3330 — `KryptonManager` `TypeInitializationException`](#3330) (root cause identified as `FileLoadException` on `System.Resources.Extensions`, not manager logic itself).

## Problem

### 1. `System.Resources.Extensions` / binding redirects (.NET Framework)

- Net4x builds use **preserialized resources** (`GenerateResourceUsePreserializedResources`), which require **`System.Resources.Extensions`** at runtime.
- The **NuGet 4.7.1** assembly is **version 4.0.1.0**; references often expect **4.0.0.0**. Without binding redirects, the CLR throws **`FileLoadException` (0x80131040)** — *manifest definition does not match the assembly reference*.
- That surfaces as **`TypeInitializationException`** for `GlobalStaticValues` → `PaletteMicrosoft365Blue` → `KryptonManager` when resource classes first run.
- **`Krypton.Standard.Toolkit`** bundles binaries with **suppressed NuGet dependencies**, so consumers may not get a consistent copy of **`System.Resources.Extensions.dll`** next to Krypton assemblies.

### 2. CS7069 on `Krypton.Ribbon` (net10 / net11)

- **`System.ComponentModel.Primitives`** / **`System.ComponentModel.TypeConverter`** were only referenced for **net8** / **net9** Windows TFMs.
- **net10.0-windows** / **net11.0-windows** builds lost compile-time metadata for **`Component`** (and related designer surface), causing **CS7069** in `ButtonSpecExpandRibbon`, `ButtonSpecAppMenu`, etc.

### 3. Color table font initialization (optional hardening)

- **`KryptonColorTable365`** / **`KryptonColorTableMicrosoft365`** used **`SystemFonts.MenuFont!.SizeInPoints!`** without guarding **null** or invalid sizes, which can throw during static initialization on unusual configurations.

## Solution

### System.Resources.Extensions and .NET Framework consumers

1. **`Source/Krypton Components/NetFramework.SystemResourcesExtensions.BindingRedirects.props`** (new)
   For **`$(TargetFrameworkIdentifier)' == '.NETFramework'`**, sets:
   - **`AutoGenerateBindingRedirects`** = `true`
   - **`GenerateBindingRedirectsOutputType`** = `true`
   so SDK-style **apps** generate **`exe.config`** redirects (including **4.0.0.0 → 4.0.1.0** for `System.Resources.Extensions`).

2. **`Krypton.Toolkit 2022.csproj`** and **`Krypton.Standard.Toolkit.csproj`**
   Pack that file as **`build/$(PackageId).props`** so NuGet **auto-imports** it for each shipped package id (Lite, Nightly, Stable, Standard, etc.).

3. **`Directory.Build.props`**
   - **`GeneratePathProperty="true"`** on **`System.Resources.Extensions`** so pack targets can resolve the package path.

4. **`Krypton.Standard.Toolkit.csproj`** (`AddReferencedAssembliesToPackage`)
   For **net4x**, include **`System.Resources.Extensions.dll`** from **`lib/net461`** in **`lib/$(TFM)/`** so the aggregate package ships a **matching** runtime assembly beside Krypton DLLs.

### CS7069 (net10 / net11)

5. **`Directory.Build.props`**
   Extend **`RestoreEnablePackagePruning`** = `false` and the **`System.ComponentModel.Primitives`** / **`System.ComponentModel.TypeConverter`** **PackageReference** items to **`net10.0-windows`** and **`net11.0-windows`**, with an updated comment.

### Color tables (hardening)

6. **`KryptonColorTable365.cs`** / **`KryptonColorTableMicrosoft365.cs`**
   Safe **`SizeInPoints`** resolution, **9 pt** fallback, **dispose** previous static fonts before replacing (preference-change path).

## How to verify

- **.NET Framework 4.8 sample app** referencing **`Krypton.Standard.Toolkit`** or **`Krypton.Toolkit`**: clean rebuild; confirm **`AppName.exe.config`** contains a binding redirect for **`System.Resources.Extensions`**; app starts without **`TypeInitializationException`** on `KryptonManager` / `GlobalStaticValues`.
- **`dotnet build`** on **`Krypton.Ribbon 2022.csproj`** for **`-f net10.0-windows`** and **`-f net11.0-windows`**: **0 CS7069** errors.
- Optional: run existing **`TestForm`** / harnesses on **net48** and **net10-windows** if part of your workflow.

## Files touched (high level)

| Area | Files |
|------|--------|
| Binding redirects + pack | `NetFramework.SystemResourcesExtensions.BindingRedirects.props`, `Krypton.Toolkit 2022.csproj`, `Krypton.Standard.Toolkit.csproj` |
| Shared MSBuild / packages | `Directory.Build.props` |
| Aggregate package content | `Krypton.Standard.Toolkit.csproj` (`TfmSpecificPackageFile` for `System.Resources.Extensions.dll`) |
| Color tables | `Palette Controls/KryptonColorTable365.cs`, `Palette Controls/KryptonColorTableMicrosoft365.cs` |

## Notes for reviewers

- **Binding redirect props** apply to **consuming** .NET Framework projects; **libraries** still benefit when the consumer is an **executable** with SDK-style build.
- **Manual `app.config`** may still be needed for **non–SDK-style** or **`packages.config`** apps if they do not import the shipped **`build\*.props`**.
- Changelog / release notes can cite **#3330** and the **net10/11 Ribbon** build fix under the appropriate version section (not updated in this PR file).
…it.KryptonManager' threw an exception.' (#3337)

# PR description

## Title `KryptonManager` exception 'The type initializer for
'Krypton.Toolkit.KryptonManager' threw an exception.'

Fix net48 `System.Resources.Extensions` load failure, net10/11 Ribbon
CS7069, and harden color-table font init

## Summary

This PR addresses **startup failures on .NET Framework 4.8** when
preserialized resources load `System.Resources.Extensions` with an
assembly-version mismatch, **CS7069 build breaks** for `Krypton.Ribbon`
on **net10.0-windows** / **net11.0-windows**, and **defensive font
initialization** in Microsoft 365 / 365 color tables when system menu
fonts are missing or invalid.

Related: [Issue #3330 — `KryptonManager`
`TypeInitializationException`](#3330)
(root cause identified as `FileLoadException` on
`System.Resources.Extensions`, not manager logic itself).

## Problem

### 1. `System.Resources.Extensions` / binding redirects (.NET
Framework)

- Net4x builds use **preserialized resources**
(`GenerateResourceUsePreserializedResources`), which require
**`System.Resources.Extensions`** at runtime.
- The **NuGet 4.7.1** assembly is **version 4.0.1.0**; references often
expect **4.0.0.0**. Without binding redirects, the CLR throws
**`FileLoadException` (0x80131040)** — *manifest definition does not
match the assembly reference*.
- That surfaces as **`TypeInitializationException`** for
`GlobalStaticValues` → `PaletteMicrosoft365Blue` → `KryptonManager` when
resource classes first run.
- **`Krypton.Standard.Toolkit`** bundles binaries with **suppressed
NuGet dependencies**, so consumers may not get a consistent copy of
**`System.Resources.Extensions.dll`** next to Krypton assemblies.

### 2. CS7069 on `Krypton.Ribbon` (net10 / net11)

- **`System.ComponentModel.Primitives`** /
**`System.ComponentModel.TypeConverter`** were only referenced for
**net8** / **net9** Windows TFMs.
- **net10.0-windows** / **net11.0-windows** builds lost compile-time
metadata for **`Component`** (and related designer surface), causing
**CS7069** in `ButtonSpecExpandRibbon`, `ButtonSpecAppMenu`, etc.
## Solution

### System.Resources.Extensions and .NET Framework consumers

1. **`Source/Krypton
Components/NetFramework.SystemResourcesExtensions.BindingRedirects.props`**
(new)
   For **`$(TargetFrameworkIdentifier)' == '.NETFramework'`**, sets:
   - **`AutoGenerateBindingRedirects`** = `true`
   - **`GenerateBindingRedirectsOutputType`** = `true`  
so SDK-style **apps** generate **`exe.config`** redirects (including
**4.0.0.0 → 4.0.1.0** for `System.Resources.Extensions`).

2. **`Krypton.Toolkit 2022.csproj`** and
**`Krypton.Standard.Toolkit.csproj`**
Pack that file as **`build/$(PackageId).props`** so NuGet
**auto-imports** it for each shipped package id (Lite, Nightly, Stable,
Standard, etc.).

3. **`Directory.Build.props`**  
- **`GeneratePathProperty="true"`** on **`System.Resources.Extensions`**
so pack targets can resolve the package path.

4. **`Krypton.Standard.Toolkit.csproj`**
(`AddReferencedAssembliesToPackage`)
For **net4x**, include **`System.Resources.Extensions.dll`** from
**`lib/net461`** in **`lib/$(TFM)/`** so the aggregate package ships a
**matching** runtime assembly beside Krypton DLLs.

### CS7069 (net10 / net11)

5. **`Directory.Build.props`**  
Extend **`RestoreEnablePackagePruning`** = `false` and the
**`System.ComponentModel.Primitives`** /
**`System.ComponentModel.TypeConverter`** **PackageReference** items to
**`net10.0-windows`** and **`net11.0-windows`**, with an updated
comment.

## How to verify

- **.NET Framework 4.8 sample app** referencing
**`Krypton.Standard.Toolkit`** or **`Krypton.Toolkit`**: clean rebuild;
confirm **`AppName.exe.config`** contains a binding redirect for
**`System.Resources.Extensions`**; app starts without
**`TypeInitializationException`** on `KryptonManager` /
`GlobalStaticValues`.
- **`dotnet build`** on **`Krypton.Ribbon 2022.csproj`** for **`-f
net10.0-windows`** and **`-f net11.0-windows`**: **0 CS7069** errors.
- Optional: run existing **`TestForm`** / harnesses on **net48** and
**net10-windows** if part of your workflow.

## Files touched (high level)

| Area | Files |
|------|--------|
| Binding redirects + pack |
`NetFramework.SystemResourcesExtensions.BindingRedirects.props`,
`Krypton.Toolkit 2022.csproj`, `Krypton.Standard.Toolkit.csproj` |
| Shared MSBuild / packages | `Directory.Build.props` |
| Aggregate package content | `Krypton.Standard.Toolkit.csproj`
(`TfmSpecificPackageFile` for `System.Resources.Extensions.dll`) |

## Notes for reviewers

- **Binding redirect props** apply to **consuming** .NET Framework
projects; **libraries** still benefit when the consumer is an
**executable** with SDK-style build.
- **Manual `app.config`** may still be needed for **non–SDK-style** or
**`packages.config`** apps if they do not import the shipped
**`build\*.props`**.
- Changelog / release notes can cite **#3330** and the **net10/11
Ribbon** build fix under the appropriate version section (not updated in
this PR file).

<img width="667" height="252" alt="image"
src="https://github.com/user-attachments/assets/7e1ef543-843e-439d-a483-522d319e7e83"
/>
Copy link
Copy Markdown
Member

@Smurf-IV Smurf-IV left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No check

@PWagner1 PWagner1 merged commit 108dd44 into canary Apr 20, 2026
17 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

version:110 All things to do with V110.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants