diff --git a/CreamInstaller/Forms/SelectDialogForm.Designer.cs b/CreamInstaller/Forms/SelectDialogForm.Designer.cs
index c627b86..4df8f90 100644
--- a/CreamInstaller/Forms/SelectDialogForm.Designer.cs
+++ b/CreamInstaller/Forms/SelectDialogForm.Designer.cs
@@ -33,7 +33,6 @@ namespace CreamInstaller.Forms
saveButton = new Button();
uninstallAllButton = new Button();
selectionTreeView = new CustomTreeView();
- filterLabel = new System.Windows.Forms.Label();
filterTextBox = new System.Windows.Forms.TextBox();
groupBox.SuspendLayout();
allCheckBoxFlowPanel.SuspendLayout();
@@ -53,21 +52,13 @@ namespace CreamInstaller.Forms
acceptButton.Text = "OK";
acceptButton.UseVisualStyleBackColor = true;
//
- // filterLabel
- //
- filterLabel.AutoSize = true;
- filterLabel.Location = new System.Drawing.Point(12, 17);
- filterLabel.Name = "filterLabel";
- filterLabel.Size = new System.Drawing.Size(68, 15);
- filterLabel.TabIndex = 1008;
- filterLabel.Text = "Game search:";
- //
// filterTextBox
//
filterTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
- filterTextBox.Location = new System.Drawing.Point(100, 14);
+ filterTextBox.Location = new System.Drawing.Point(12, 14);
filterTextBox.Name = "filterTextBox";
- filterTextBox.Size = new System.Drawing.Size(436, 23);
+ filterTextBox.PlaceholderText = "Enter the name of a game to search";
+ filterTextBox.Size = new System.Drawing.Size(524, 23);
filterTextBox.TabIndex = 0;
filterTextBox.TextChanged += OnFilterTextChanged;
//
@@ -209,7 +200,6 @@ namespace CreamInstaller.Forms
Controls.Add(acceptButton);
Controls.Add(groupBox);
Controls.Add(filterTextBox);
- Controls.Add(filterLabel);
FormBorderStyle = FormBorderStyle.FixedSingle;
MaximizeBox = false;
MinimizeBox = false;
@@ -237,7 +227,6 @@ namespace CreamInstaller.Forms
private Button saveButton;
private CheckBox sortCheckBox;
private Button uninstallAllButton;
- private System.Windows.Forms.Label filterLabel;
private System.Windows.Forms.TextBox filterTextBox;
}
}
\ No newline at end of file
diff --git a/CreamInstaller/Utility/ThemeManager.cs b/CreamInstaller/Utility/ThemeManager.cs
index c588cce..eef74be 100644
--- a/CreamInstaller/Utility/ThemeManager.cs
+++ b/CreamInstaller/Utility/ThemeManager.cs
@@ -211,6 +211,7 @@ internal static class ThemeManager
tb.BackColor = DarkBackAlt;
tb.ForeColor = DarkFore;
tb.BorderStyle = BorderStyle.FixedSingle;
+ NativeMethods.RefreshCueBanner(tb);
break;
// Layout panels set a consistent background
@@ -269,6 +270,7 @@ internal static class ThemeManager
tb.BackColor = LightBackAlt;
tb.ForeColor = LightFore;
tb.BorderStyle = BorderStyle.Fixed3D;
+ NativeMethods.RefreshCueBanner(tb);
break;
case TableLayoutPanel tlp:
tlp.BackColor = LightBack;
@@ -462,15 +464,54 @@ internal static class ThemeManager
}
}
+///
+/// Wraps Win32 API calls that have no managed equivalent in WinForms.
+/// These P/Invoke declarations are required because .NET does not expose
+/// the underlying Windows messages or DWM attributes through its own APIs.
+///
internal static class NativeMethods
{
+ // DWM attribute index for enabling/disabling the immersive dark title bar.
+ // Documented in dwmapi.h; value 20 corresponds to DWMWA_USE_IMMERSIVE_DARK_MODE
+ // (Windows 10 build 19041+ / Windows 11).
private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
+ // DwmSetWindowAttribute allows setting per-window Desktop Window Manager attributes.
+ // We use it here to flip the title bar to dark or light depending on the active theme,
+ // since WinForms has no built-in API to control title bar coloring.
[System.Runtime.InteropServices.DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(System.IntPtr hwnd, int attr, ref int attrValue, int attrSize);
+ ///
+ /// Toggles the dark/light title bar chrome for the given window handle.
+ /// Pass 1 for dark mode, 0 for light mode.
+ ///
internal static void EnableDarkTitleBar(System.IntPtr handle, int useDark)
{
_ = DwmSetWindowAttribute(handle, DWMWA_USE_IMMERSIVE_DARK_MODE, ref useDark, sizeof(int));
}
+
+ // Win32 Edit control message that sets or updates the cue (placeholder) banner text.
+ // WinForms sets PlaceholderText once at creation time via this same message internally,
+ // but does not re-send it when the control's colors change. When we restyle a TextBox
+ // for dark/light mode the cue banner can disappear, so we must re-send the message
+ // manually to make the placeholder visible again.
+ private const int EM_SETCUEBANNER = 0x1501;
+
+ // SendMessage is the standard Win32 mechanism for posting messages directly to a
+ // window/control handle. We use the Unicode variant so the placeholder string is
+ // transmitted without any ANSI conversion.
+ [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ private static extern System.IntPtr SendMessage(System.IntPtr hWnd, int msg, System.IntPtr wParam, string lParam);
+
+ ///
+ /// Re-sends EM_SETCUEBANNER to the given TextBox so its placeholder text
+ /// is redrawn after a theme change has altered the control's background or foreground colors.
+ /// Does nothing if the control handle has not yet been created or the placeholder is empty.
+ ///
+ internal static void RefreshCueBanner(System.Windows.Forms.TextBox textBox)
+ {
+ if (textBox?.IsHandleCreated == true && textBox.PlaceholderText is { Length: > 0 })
+ SendMessage(textBox.Handle, EM_SETCUEBANNER, (System.IntPtr)1, textBox.PlaceholderText);
+ }
}
\ No newline at end of file