From 0e097b1fc65ff92fa4e8c98e53019c685f8fc4dc Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 19 Mar 2026 17:25:06 -0500 Subject: [PATCH] Minor slot hover performance improvements Skip repaint on cursor moving the hover window Cache reference to the slot interaction types and "nothing" slot image Dispose of slot sprites when updating with a new one If scrolling box/group, auto-update hover with the newly displayed slot's content instead of hiding --- .../Builder/SpriteBuilder5668.cs | 12 ++++----- .../Builder/SpriteBuilder5668a.cs | 12 ++++----- .../Builder/SpriteBuilder5668c.cs | 12 ++++----- .../Controls/SAV Editor/SAVEditor.cs | 2 ++ .../Controls/SAV Editor/SlotChangeManager.cs | 14 ++++++++++ PKHeX.WinForms/Controls/Slots/PokePreview.cs | 26 +++++++++++++++++++ PKHeX.WinForms/Controls/Slots/SlotUtil.cs | 7 +++-- .../Controls/Slots/SummaryPreviewer.cs | 2 +- .../Subforms/Save Editors/SAV_BoxViewer.cs | 1 + .../Subforms/Save Editors/SAV_GroupViewer.cs | 16 ++++++++++-- 10 files changed, 81 insertions(+), 23 deletions(-) diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs index 150c3fe35..0fc578ffd 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs @@ -26,14 +26,14 @@ public sealed class SpriteBuilder5668s : SpriteBuilder protected override Bitmap Unknown => Resources.b_unknown; protected override Bitmap GetEggSprite(ushort species) => species == (int)Species.Manaphy ? Resources.b_490_e : Resources.b_egg; - public override Bitmap Hover => Resources.slotHover68; - public override Bitmap View => Resources.slotView68; - public override Bitmap Set => Resources.slotSet68; - public override Bitmap Delete => Resources.slotDel68; - public override Bitmap Transparent => Resources.slotTrans68; + public override Bitmap Hover { get; } = Resources.slotHover68; + public override Bitmap View { get; } = Resources.slotView68; + public override Bitmap Set { get; } = Resources.slotSet68; + public override Bitmap Delete { get; } = Resources.slotDel68; + public override Bitmap Transparent { get; } = Resources.slotTrans68; public override Bitmap Drag => Resources.slotDrag68; public override Bitmap UnknownItem => Resources.bitem_unk; - public override Bitmap None => Resources.b_0; + public override Bitmap None { get; } = Resources.b_0; public override Bitmap ItemTM => Resources.bitem_tm; public override Bitmap ItemTR => Resources.bitem_tr; public override Bitmap ShadowLugia => Resources.b_249x; diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs index abae3d71f..5247a896a 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs @@ -26,14 +26,14 @@ public sealed class SpriteBuilder5668a : SpriteBuilder protected override Bitmap Unknown => Resources.b_unknown; protected override Bitmap GetEggSprite(ushort species) => species == (int)Species.Manaphy ? Resources.a_490_e : Resources.a_egg; - public override Bitmap Hover => Resources.slotHover68; - public override Bitmap View => Resources.slotView68; - public override Bitmap Set => Resources.slotSet68; - public override Bitmap Delete => Resources.slotDel68; - public override Bitmap Transparent => Resources.slotTrans68; + public override Bitmap Hover { get; } = Resources.slotHover68; + public override Bitmap View { get; } = Resources.slotView68; + public override Bitmap Set { get; } = Resources.slotSet68; + public override Bitmap Delete { get; } = Resources.slotDel68; + public override Bitmap Transparent { get; } = Resources.slotTrans68; public override Bitmap Drag => Resources.slotDrag68; public override Bitmap UnknownItem => Resources.bitem_unk; - public override Bitmap None => Resources.b_0; + public override Bitmap None { get; } = Resources.b_0; public override Bitmap ItemTM => Resources.aitem_tm; public override Bitmap ItemTR => Resources.bitem_tr; public override Bitmap ShadowLugia => Resources.b_249x; diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs index 493203f71..8dfaf60cb 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs @@ -26,14 +26,14 @@ public sealed class SpriteBuilder5668c : SpriteBuilder protected override Bitmap Unknown => Resources.b_unknown; protected override Bitmap GetEggSprite(ushort species) => species == (int)Species.Manaphy ? Resources.b_490_e : Resources.b_egg; - public override Bitmap Hover => Resources.slotHover68; - public override Bitmap View => Resources.slotView68; - public override Bitmap Set => Resources.slotSet68; - public override Bitmap Delete => Resources.slotDel68; - public override Bitmap Transparent => Resources.slotTrans68; + public override Bitmap Hover { get; } = Resources.slotHover68; + public override Bitmap View { get; } = Resources.slotView68; + public override Bitmap Set { get; } = Resources.slotSet68; + public override Bitmap Delete { get; } = Resources.slotDel68; + public override Bitmap Transparent { get; } = Resources.slotTrans68; public override Bitmap Drag => Resources.slotDrag68; public override Bitmap UnknownItem => Resources.bitem_unk; - public override Bitmap None => Resources.b_0; + public override Bitmap None { get; } = Resources.b_0; public override Bitmap ItemTM => Resources.bitem_tm; public override Bitmap ItemTR => Resources.bitem_tr; public override Bitmap ShadowLugia => Resources.b_249x; diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs index 2ac9228d5..fd0d46773 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs @@ -104,6 +104,8 @@ private void InitializeEvents() if (menu.mnuVSD.Visible) return; Box.CurrentBox = e.Delta > 1 ? Box.Editor.MoveLeft() : Box.Editor.MoveRight(); + if (Box.M is { } m) + m.MouseRestart(); // should always trigger if properly connected }; GB_Daycare.Click += (_, _) => SwitchDaycare(); diff --git a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs index 33e7f1b1b..24a9805bf 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs @@ -18,6 +18,7 @@ public sealed class SlotChangeManager(SAVEditor se) : IDisposable { public readonly SAVEditor SE = se; public readonly SlotTrackerImage LastSlot = new(); + public PictureBox? Hovered { get; private set; } public readonly DragManager Drag = new(); public SaveDataEditor Env { get; set; } = null!; @@ -34,15 +35,28 @@ public void MouseEnter(object? sender, EventArgs e) { if (sender is not PictureBox pb) return; + MouseRestart(pb); + } + + public void MouseRestart() + { + if (Hovered is { } pb) + MouseRestart(pb); + } + + private void MouseRestart(PictureBox pb) + { bool dataPresent = pb.Image is not null; if (dataPresent) Hover.Start(pb, LastSlot); + Hovered = pb; pb.Cursor = dataPresent ? Cursors.Hand : Cursors.Default; } public void MouseLeave(object? sender, EventArgs e) { Hover.Stop(); + Hovered = null; } public void MouseClick(object? sender, MouseEventArgs e) diff --git a/PKHeX.WinForms/Controls/Slots/PokePreview.cs b/PKHeX.WinForms/Controls/Slots/PokePreview.cs index f3eed0e70..f9f26bbdb 100644 --- a/PKHeX.WinForms/Controls/Slots/PokePreview.cs +++ b/PKHeX.WinForms/Controls/Slots/PokePreview.cs @@ -447,4 +447,30 @@ protected override CreateParams CreateParams private readonly record struct RenderMoveLine(string Text, Image? Icon, Color Color); private readonly record struct RenderTextLine(string Text, Color Color, int TopPadding, int BottomPadding); + + /// + /// Moves the form to the specified screen coordinates without resizing or changing its z-order. + /// + /// + /// This method updates the form's position using the Win32 SetWindowPos API with flags that minimize redraws and prevent activation or z-order changes. + /// Use this method when you need to reposition the form efficiently without affecting its size or focus. + /// + /// The new horizontal position, in pixels, of the form's upper-left corner relative to the screen. + /// The new vertical position, in pixels, of the form's upper-left corner relative to the screen. + public void MoveForm(int x, int y) + { + const uint SWP_NOSIZE = 0x0001; + const uint SWP_NOZORDER = 0x0004; + const uint SWP_NOREDRAW = 0x0008; + const uint SWP_NOACTIVATE = 0x0010; + const uint SWP_NOSENDCHANGING = 0x0400; + const uint SWP_ASYNCWINDOWPOS = 0x4000; + const uint flags = SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_ASYNCWINDOWPOS; + + SetWindowPos(Handle, 0, x, y, 0, 0, flags); + return; + + [System.Runtime.InteropServices.DllImport("user32.dll")] + static extern bool SetWindowPos(nint hWnd, nint hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); + } } diff --git a/PKHeX.WinForms/Controls/Slots/SlotUtil.cs b/PKHeX.WinForms/Controls/Slots/SlotUtil.cs index 73a32dd42..69393d4ee 100644 --- a/PKHeX.WinForms/Controls/Slots/SlotUtil.cs +++ b/PKHeX.WinForms/Controls/Slots/SlotUtil.cs @@ -14,9 +14,9 @@ public static class SlotUtil /// /// Gets the background image for a slot based on the provided . /// - public static Bitmap GetTouchTypeBackground(SlotTouchType type) => type switch + public static Bitmap? GetTouchTypeBackground(SlotTouchType type) => type switch { - SlotTouchType.None => SpriteUtil.Spriter.Transparent, + SlotTouchType.None => null, SlotTouchType.Get => SpriteUtil.Spriter.View, SlotTouchType.Set => SpriteUtil.Spriter.Set, SlotTouchType.Delete => SpriteUtil.Spriter.Delete, @@ -42,6 +42,9 @@ public static class SlotUtil /// public static void UpdateSlot(PictureBox pb, ISlotInfo info, PKM pk, SaveFile sav, SlotVisibilityType flags, SlotTouchType t = SlotTouchType.None) { + pb.Image?.Dispose(); + pb.BackgroundImage?.Dispose(); + pb.BackgroundImage = GetTouchTypeBackground(t); if (pk.Species == 0) // Nothing in slot { diff --git a/PKHeX.WinForms/Controls/Slots/SummaryPreviewer.cs b/PKHeX.WinForms/Controls/Slots/SummaryPreviewer.cs index c44289b8c..7388c5f90 100644 --- a/PKHeX.WinForms/Controls/Slots/SummaryPreviewer.cs +++ b/PKHeX.WinForms/Controls/Slots/SummaryPreviewer.cs @@ -103,7 +103,7 @@ public void UpdatePreviewPosition(Point location) var cLoc = Cursor.Position; var shift = Settings.PreviewCursorShift; cLoc.Offset(shift); - Previewer.Location = cLoc; + Previewer.MoveForm(cLoc.X, cLoc.Y); } public void Show(Control pb, IEncounterInfo enc) diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs index e5de66e9a..60da5b479 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_BoxViewer.cs @@ -54,6 +54,7 @@ public SAV_BoxViewer(SAVEditor p, SlotChangeManager m, int box) if (parent.menu.mnuVSD.Visible) return; Box.CurrentBox = e.Delta > 1 ? Box.Editor.MoveLeft() : Box.Editor.MoveRight(); + m.MouseRestart(); }; var mnu = parent.SlotPictureBoxes[0].ContextMenuStrip; diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs index 8cb7e89ce..7ee39e6c8 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs @@ -15,6 +15,8 @@ public sealed partial class SAV_GroupViewer : Form private readonly IReadOnlyList Groups; private readonly SummaryPreviewer Preview = new(); + private PictureBox? Hover; + public int CurrentGroup { get; set; } = -1; public SAV_GroupViewer(SaveFile sav, IPKMView view, IReadOnlyList groups) @@ -28,7 +30,12 @@ public SAV_GroupViewer(SaveFile sav, IPKMView view, IReadOnlyList gro Regenerate(count); CenterToParent(); - MouseWheel += (_, e) => CurrentGroup = e.Delta > 1 ? MoveLeft() : MoveRight(); + MouseWheel += (_, e) => + { + CurrentGroup = e.Delta > 1 ? MoveLeft() : MoveRight(); + if (Hover is { } pb) + HoverSlot(pb); + }; var names = groups.Select(z => $"{z.GroupName}").ToArray(); CB_BoxSelect.Items.AddRange(names); @@ -48,7 +55,11 @@ public SAV_GroupViewer(SaveFile sav, IPKMView view, IReadOnlyList gro pb.ContextMenuStrip = mnu; pb.MouseMove += (_, args) => Preview.UpdatePreviewPosition(args.Location); pb.MouseEnter += (_, _) => HoverSlot(pb); - pb.MouseLeave += (_, _) => Preview.Clear(); + pb.MouseLeave += (_, _) => + { + Preview.Clear(); + Hover = null; + }; } FormClosing += (_, _) => Preview.Clear(); } @@ -59,6 +70,7 @@ private void HoverSlot(PictureBox pb) var index = Box.Entries.IndexOf(pb); var slot = group.Slots[index]; Preview.Show(pb, slot, group.Type); + Hover = pb; } private void OmniClick(object sender, EventArgs e)