diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 950f088..29823c9 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -28,5 +28,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("1.0.8.1")] -[assembly: AssemblyFileVersion("1.0.8.1")] +[assembly: AssemblyVersion("1.0.8.4")] +[assembly: AssemblyFileVersion("1.0.8.4")] diff --git a/WelcomeScreenCustomizer.cs b/WelcomeScreenCustomizer.cs index 626471f..20e986c 100644 --- a/WelcomeScreenCustomizer.cs +++ b/WelcomeScreenCustomizer.cs @@ -10,19 +10,22 @@ namespace WelcomeScreenCustomizer { public partial class MainForm : Form { - private string selectedImagePath = null; - private Color primaryColor = Color.FromArgb(0, 120, 212); // Windows blue - private Color backgroundColor = Color.FromArgb(243, 243, 243); - private Color buttonHoverColor = Color.FromArgb(0, 102, 184); + private string selectedImagePath; + private CheckBox debugCheckBox; + private readonly Color primaryColor = Color.FromArgb(0, 120, 212); + private readonly Color backgroundColor = Color.FromArgb(243, 243, 243); + private readonly Color buttonHoverColor = Color.FromArgb(0, 102, 184); private PictureBox previewBox; private Label fileLabel; private Label versionLabel; + private Image placeholderImage; public MainForm() { InitializeComponents(); CheckAdminRights(); - LoadCurrentImage(); + CreatePlaceholderImage(); + ShowPlaceholder(); } private void InitializeComponents() @@ -30,6 +33,7 @@ private void InitializeComponents() // Set form properties this.Text = "Windows 11 Welcome Screen Customizer"; this.Size = new Size(800, 600); + this.MinimumSize = new Size(800, 600); this.FormBorderStyle = FormBorderStyle.FixedSingle; this.MaximizeBox = false; this.StartPosition = FormStartPosition.CenterScreen; @@ -78,7 +82,7 @@ private void InitializeComponents() // Subtitle/instruction label Label instructionLabel = new Label { - Text = "Select an image file to set as your Windows welcome screen background.", + Text = "Select an image file to set as your Windows welcome screen background for all user accounts.", Font = new Font("Segoe UI", 9F, FontStyle.Regular), ForeColor = Color.FromArgb(88, 88, 88), AutoSize = false, @@ -89,24 +93,6 @@ private void InitializeComponents() }; mainPanel.Controls.Add(instructionLabel); - // Version label - Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; - string versionText = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; - versionLabel = new Label - { - Text = $"v{versionText}", - Font = new Font("Segoe UI", 8F, FontStyle.Regular), - ForeColor = Color.Gray, - AutoSize = true, - Location = new Point(mainPanel.Width - 80, mainPanel.Height - 25) - }; - mainPanel.Controls.Add(versionLabel); - mainPanel.Resize += (s, e) => - { - // Keep version label in bottom-right corner when form is resized - versionLabel.Location = new Point(mainPanel.Width - 80, mainPanel.Height - 25); - }; - // File path panel Panel filePanel = new Panel { @@ -177,13 +163,54 @@ private void InitializeComponents() // Browse button Button browseButton = CreateStyledButton("Browse for Image", new Point(245, 0)); - browseButton.Click += (s, e) => BrowseFile(fileLabel); + browseButton.Click += SelectImage_Click; buttonPanel.Controls.Add(browseButton); // Undo button Button undoButton = CreateStyledButton("Revert to Original Settings", new Point(245, 40)); undoButton.Click += (s, e) => UndoChanges(); buttonPanel.Controls.Add(undoButton); + + // Create bottom panel for debug checkbox and version + Panel bottomPanel = new Panel + { + Height = 30, + Dock = DockStyle.Bottom, + BackColor = backgroundColor, + Padding = new Padding(20, 0, 20, 0) + }; + this.Controls.Add(bottomPanel); + + // Add debug checkbox + debugCheckBox = new CheckBox + { + Text = "Show Registry Debug Info", + Location = new Point(20, 5), + AutoSize = true, + Checked = false + }; + bottomPanel.Controls.Add(debugCheckBox); + + // Version label + Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; + string versionText = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; + versionLabel = new Label + { + Text = $"v{versionText}", + AutoSize = true, + Location = new Point(bottomPanel.Width - 80, 5), + ForeColor = Color.Gray + }; + bottomPanel.Controls.Add(versionLabel); + + // Handle form resize to update version label position + bottomPanel.Resize += (s, e) => + { + if (versionLabel != null) + { + versionLabel.Location = new Point(bottomPanel.Width - 80, 5); + } + }; } private Button CreateStyledButton(string text, Point location) @@ -202,8 +229,7 @@ private Button CreateStyledButton(string text, Point location) }; button.FlatAppearance.BorderSize = 0; - button.MouseEnter += (s, e) => button.BackColor = buttonHoverColor; - button.MouseLeave += (s, e) => button.BackColor = primaryColor; + button.FlatAppearance.MouseOverBackColor = buttonHoverColor; return button; } @@ -220,37 +246,90 @@ private void CheckAdminRights() } } - private void UpdatePreview(string imagePath) + private void CreatePlaceholderImage() { - try + int width = 200; + int height = 150; + placeholderImage = new Bitmap(width, height); + + using (Graphics g = Graphics.FromImage(placeholderImage)) { - if (previewBox.Image != null) + // Fill background with a light gray + g.Clear(Color.FromArgb(250, 250, 250)); + + // Draw a photo icon + using (Pen pen = new Pen(Color.FromArgb(200, 200, 200), 2)) { - previewBox.Image.Dispose(); - previewBox.Image = null; + // Draw a rectangle for the photo frame + g.DrawRectangle(pen, width/4, height/4, width/2, height/2); + + // Draw a mountain scene + Point[] mountains = { + new Point(width/4, 3*height/4), // Left bottom + new Point(3*width/8, height/2), // Small peak + new Point(width/2, 2*height/3), // Valley + new Point(5*width/8, 5*height/12), // High peak + new Point(3*width/4, 3*height/4) // Right bottom + }; + g.DrawLines(pen, mountains); + + // Draw a sun + g.DrawEllipse(pen, 5*width/8, height/3, width/12, width/12); } - if (!string.IsNullOrEmpty(imagePath)) + // Add text + using (Font font = new Font("Segoe UI", 9)) + using (StringFormat sf = new StringFormat()) { - using (var img = Image.FromFile(imagePath)) - { - // Create a new bitmap to avoid file locking - previewBox.Image = new Bitmap(img); - } + sf.Alignment = StringAlignment.Center; + sf.LineAlignment = StringAlignment.Center; + g.DrawString("Select an image to preview", font, Brushes.Gray, + new RectangleF(0, height - 40, width, 30), sf); } } - catch (Exception) + } + + private void ShowPlaceholder() + { + if (previewBox.Image != null && previewBox.Image != placeholderImage) + { + previewBox.Image.Dispose(); + } + previewBox.Image = placeholderImage; + } + + private void UpdatePreview(string imagePath) + { + try { - // If there's an error loading the image, clear the preview - if (previewBox.Image != null) + if (string.IsNullOrEmpty(imagePath)) + { + ShowPlaceholder(); + return; + } + + if (previewBox.Image != null && previewBox.Image != placeholderImage) { previewBox.Image.Dispose(); - previewBox.Image = null; } + + using (var img = Image.FromFile(imagePath)) + { + previewBox.Image = new Bitmap(img); + } + } + catch (Exception ex) + { + MessageBox.Show( + $"Error loading image preview: {ex.Message}", + "Preview Error", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + ShowPlaceholder(); } } - private void BrowseFile(Label fileLabel) + private void SelectImage_Click(object sender, EventArgs e) { using (OpenFileDialog dialog = new OpenFileDialog()) { @@ -262,11 +341,49 @@ private void BrowseFile(Label fileLabel) selectedImagePath = dialog.FileName; fileLabel.Text = selectedImagePath; UpdatePreview(selectedImagePath); - SetLockScreen(); // Automatically set the image after selection } } } + private void CheckRegistryValues(string message) + { + if (!debugCheckBox.Checked) return; + + try + { + using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP")) + { + string status = "Key not found"; + string path = "Key not found"; + string url = "Key not found"; + + if (key != null) + { + status = key.GetValue("LockScreenImageStatus")?.ToString() ?? "Value not found"; + path = key.GetValue("LockScreenImagePath")?.ToString() ?? "Value not found"; + url = key.GetValue("LockScreenImageUrl")?.ToString() ?? "Value not found"; + } + + MessageBox.Show( + $"Registry Check - {message}:\n" + + $"Status: {status}\n" + + $"Path: {path}\n" + + $"URL: {url}", + $"Registry State - {message}", + MessageBoxButtons.OK, + MessageBoxIcon.Information); + } + } + catch (Exception ex) + { + MessageBox.Show( + $"Error checking registry - {message}:\n{ex.Message}", + "Registry Check Error", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + } + } + private void SetLockScreen() { if (string.IsNullOrEmpty(selectedImagePath)) @@ -281,37 +398,68 @@ private void SetLockScreen() try { - // First, set the image using PersonalizationCSP - using (RegistryKey key = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP")) + const string cspKeyPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"; + const string policyKeyPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization"; + + CheckRegistryValues("Before Any Changes"); + + try { - if (key != null) - { - key.SetValue("LockScreenImageStatus", 1); - key.SetValue("LockScreenImagePath", selectedImagePath); - key.SetValue("LockScreenImageUrl", selectedImagePath); - } + // Create the PersonalizationCSP key directly without deleting first + Registry.SetValue(cspKeyPath, "LockScreenImageStatus", 1, RegistryValueKind.DWord); + CheckRegistryValues("After Setting Status"); + + Registry.SetValue(cspKeyPath, "LockScreenImagePath", selectedImagePath, RegistryValueKind.String); + CheckRegistryValues("After Setting Path"); + + Registry.SetValue(cspKeyPath, "LockScreenImageUrl", selectedImagePath, RegistryValueKind.String); + CheckRegistryValues("After Setting URL"); + + // Run reg query to verify from command line + System.Diagnostics.Process process = new System.Diagnostics.Process(); + process.StartInfo.FileName = "reg"; + process.StartInfo.Arguments = "query \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PersonalizationCSP\""; + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.CreateNoWindow = true; + process.Start(); + string regOutput = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + + MessageBox.Show( + $"Reg Query Output:\n{regOutput}", + "Debug - Registry Query", + MessageBoxButtons.OK, + MessageBoxIcon.Information); + + // Set policy values + Registry.SetValue(policyKeyPath, "LockScreenImage", selectedImagePath, RegistryValueKind.String); + Registry.SetValue(policyKeyPath, "NoChangingLockScreen", 1, RegistryValueKind.DWord); + + CheckRegistryValues("After Setting Policy Values"); + + MessageBox.Show( + "Welcome screen background has been set successfully!", + "Success", + MessageBoxButtons.OK, + MessageBoxIcon.Information); + + // Final check after everything is done + CheckRegistryValues("Final Check"); } - - // Then, set it using the Personalization key and prevent changes - using (RegistryKey key = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Policies\Microsoft\Windows\Personalization")) + catch (Exception ex) { - if (key != null) - { - key.SetValue("LockScreenImage", selectedImagePath); - key.SetValue("NoChangingLockScreen", 1); - } + MessageBox.Show( + $"Error setting registry values:\n{ex.Message}\n\nStack Trace:\n{ex.StackTrace}", + "Registry Error", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); } - - MessageBox.Show( - "Welcome screen background has been set successfully!", - "Success", - MessageBoxButtons.OK, - MessageBoxIcon.Information); } catch (Exception ex) { MessageBox.Show( - string.Format("Error setting welcome screen background: {0}", ex.Message), + $"Error setting welcome screen background:\n{ex.Message}\n\nStack Trace:\n{ex.StackTrace}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); @@ -322,53 +470,56 @@ private void UndoChanges() { try { - // Remove Personalization policy values - using (RegistryKey key = Registry.LocalMachine.OpenSubKey( - @"SOFTWARE\Policies\Microsoft\Windows\Personalization", true)) + // Delete PersonalizationCSP key + try { - if (key != null) - { - try { key.DeleteValue("LockScreenImage"); } catch { } - try { key.DeleteValue("NoChangingLockScreen"); } catch { } - } + Registry.LocalMachine.DeleteSubKeyTree(@"SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP", false); + } + catch (Exception ex) + { + MessageBox.Show( + $"Error removing PersonalizationCSP key: {ex.Message}", + "Registry Error", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); } - // Remove PersonalizationCSP values - using (RegistryKey key = Registry.LocalMachine.OpenSubKey( - @"SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP", true)) + // Delete policy values + try { - if (key != null) + using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Policies\Microsoft\Windows\Personalization", true)) { - // Delete all values - try { key.DeleteValue("LockScreenImageStatus"); } catch { } - try { key.DeleteValue("LockScreenImagePath"); } catch { } - try { key.DeleteValue("LockScreenImageUrl"); } catch { } - - // If the key is empty after deleting values, delete the entire key - if (key.GetValueNames().Length == 0 && key.GetSubKeyNames().Length == 0) + if (key != null) { - Registry.LocalMachine.DeleteSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP", false); + key.DeleteValue("LockScreenImage", false); + key.DeleteValue("NoChangingLockScreen", false); } } } + catch (Exception ex) + { + MessageBox.Show( + $"Error removing policy values: {ex.Message}", + "Registry Error", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + } // Clear the UI selectedImagePath = null; fileLabel.Text = "No file selected"; - if (previewBox.Image != null) - { - previewBox.Image.Dispose(); - previewBox.Image = null; - } + ShowPlaceholder(); - MessageBox.Show("All lock screen registry changes have been removed.", + MessageBox.Show( + "Welcome screen settings have been reverted to default.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { - MessageBox.Show(string.Format("Error removing registry changes: {0}", ex.Message), + MessageBox.Show( + $"Error reverting settings: {ex.Message}\n\nStack Trace:\n{ex.StackTrace}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); diff --git a/dotnet b/dotnet deleted file mode 100644 index e69de29..0000000