diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 0000000..a73cc8b --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,25 @@ +name: .NET + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal diff --git a/.gitignore b/.gitignore index 2c70369..dc250f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,196 +1,6 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -x64/ -build/ -bld/ -[Bb]in/ -[Oo]bj/ - -# Roslyn cache directories -*.ide/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -#NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding addin-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -## TODO: Comment the next line if you want to checkin your -## web deploy settings but do note that will include unencrypted -## passwords -#*.pubxml - -# NuGet Packages Directory -packages/* -## TODO: If the tool you use requires repositories.config -## uncomment the next line -#!packages/repositories.config - -# Enable "build/" folder in the NuGet Packages folder since -# NuGet packages use it for MSBuild targets. -# This line needs to be after the ignore of the build folder -# (and the packages folder if the line above has been uncommented) -!packages/build/ - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ -bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# LightSwitch generated files -GeneratedArtifacts/ -_Pvt_Extensions/ -ModelManifest.xml - -Thumbs.db -/.vs -/.vs -/.vs/slnx.sqlite -/.vs/ProjectSettings.json +**/.vs/ +**/.vscode/ +**/bin/ +**/obj/ +**/Properties/* +**/*.user diff --git a/.hgignore b/.hgignore deleted file mode 100644 index f6552a8..0000000 --- a/.hgignore +++ /dev/null @@ -1,4 +0,0 @@ -relre:bin/ -relre:obj/ -glob:Web-Page-Screensaver.csproj.user -glob:Web-Page-Screensaver.suo diff --git a/Extensions.cs b/Extensions.cs new file mode 100644 index 0000000..8ca18f5 --- /dev/null +++ b/Extensions.cs @@ -0,0 +1,59 @@ +using Microsoft.Win32; +using System; + +namespace WebPageScreensaver +{ + public static class Extensions + { + public static RegistryKey GetOrCreateSubKey(this RegistryKey root, string subKeyName) + { + if (root == null) + { + throw new ArgumentNullException(nameof(root)); + } + if (string.IsNullOrWhiteSpace(subKeyName)) + { + throw new ArgumentException($"Argument is null or whitespace: {nameof(subKeyName)}"); + } + + RegistryKey? key = root.OpenSubKey(subKeyName, writable: true); + if (key == null) + { + key = root.CreateSubKey(subKeyName, writable: true); + if (key == null) + { + throw new UnauthorizedAccessException($"Could not get/create key to registry: {subKeyName}"); + } + } + return key; + } + + public static string GetOrCreateValue(this RegistryKey root, string valueName, T defaultValue) + { + if (root == null) + { + throw new ArgumentNullException(nameof(root)); + } + if (defaultValue == null) + { + throw new ArgumentNullException(nameof(defaultValue)); + } + if (string.IsNullOrWhiteSpace(valueName)) + { + throw new ArgumentNullException(nameof(valueName)); + } + + object? obj = root.GetValue(valueName); + if (obj == null) + { + root.SetValue(valueName, defaultValue); + obj = root.GetValue(valueName); + if (obj == null) + { + throw new UnauthorizedAccessException($"Could not get/create the registry value: {valueName}"); + } + } + return obj.ToString() ?? string.Empty; + } + } +} \ No newline at end of file diff --git a/MultiFormContext.cs b/MultiFormContext.cs new file mode 100644 index 0000000..736821f --- /dev/null +++ b/MultiFormContext.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace WebPageScreensaver +{ + internal class MultiFormContext : ApplicationContext + { + public MultiFormContext(List
forms) + { + if (forms == null) + { + throw new ArgumentNullException(nameof(forms)); + } + + foreach (Form form in forms) + { + form.FormClosed += (s, args) => ExitThread(); + form.Show(); + } + } + } +} diff --git a/MultiScreenMode.cs b/MultiScreenMode.cs new file mode 100644 index 0000000..c7fe5fa --- /dev/null +++ b/MultiScreenMode.cs @@ -0,0 +1,23 @@ +namespace WebPageScreensaver +{ + /// + /// Specifies the different ways a screensaver can be shown in multiple screens. + /// + internal enum MultiScreenMode + { + /// + /// Same webpage in all screens. + /// + Mirror, + + /// + /// Each screen has its own individual list of webpages. + /// + Separate, + + /// + /// Show one webpage split among all the screens. + /// + Span + } +} diff --git a/PreUpgradePrefs.reg b/PreUpgradePrefs.reg deleted file mode 100644 index 6751843..0000000 Binary files a/PreUpgradePrefs.reg and /dev/null differ diff --git a/Preferences.cs b/Preferences.cs new file mode 100644 index 0000000..e5e7745 --- /dev/null +++ b/Preferences.cs @@ -0,0 +1,56 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace WebPageScreensaver +{ + internal static class Preferences + { + private const string CloseOnMouseMovementName = "CloseOnMouseMovement"; + private const string MultiScreenModeName = "MultiScreenMode"; + + private struct SettingDefaultValue + { + public const int RotationInterval = 30; + public const bool Shuffle = false; + } + + private const string KeyWebPageScreensaver = @"Software\WebPageScreensaver"; + + private static RegistryKey RootKey => Registry.CurrentUser.GetOrCreateSubKey(KeyWebPageScreensaver); + + public static int ScreenCount => Screen.AllScreens.Length; + + public static MultiScreenMode MultiScreen + { + get => Enum.Parse(RootKey.GetOrCreateValue(MultiScreenModeName, MultiScreenMode.Separate /* default */)); + set => RootKey.SetValue(MultiScreenModeName, value); + } + + public static bool CloseOnMouseMovement + { + get => bool.Parse(RootKey.GetOrCreateValue(CloseOnMouseMovementName, true /* default */)); + set => RootKey.SetValue(CloseOnMouseMovementName, value); + } + + public static Dictionary Screens + { + get + { + var screens = new Dictionary(); + + MultiScreenMode multiScreenMode = MultiScreen; + for (int screenNumber = 0; screenNumber < ScreenCount; screenNumber++) + { + string screenKeyName = $"Display{screenNumber + 1}"; // To match tab name + RegistryKey subKey = RootKey.GetOrCreateSubKey(screenKeyName); + var info = new ScreenInformation(subKey, screenNumber, multiScreenMode); + screens.Add(screenNumber, info); + } + + return screens; + } + } + } +} \ No newline at end of file diff --git a/PreferencesForm.Designer.cs b/PreferencesForm.Designer.cs index ee7e032..7126be6 100644 --- a/PreferencesForm.Designer.cs +++ b/PreferencesForm.Designer.cs @@ -1,13 +1,11 @@ -namespace pl.polidea.lab.Web_Page_Screensaver +namespace WebPageScreensaver { - using global::Web_Page_Screensaver; - - partial class PreferencesForm + internal partial class PreferencesForm { /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private System.ComponentModel.IContainer _components = null; /// /// Clean up any resources being used. @@ -15,15 +13,13 @@ partial class PreferencesForm /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { - if (disposing && (components != null)) + if (disposing && _components != null) { - components.Dispose(); + _components.Dispose(); } base.Dispose(disposing); } - #region Windows Form Designer generated code - /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. @@ -31,246 +27,302 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - this.label1 = new System.Windows.Forms.Label(); - this.llProjectLocationUrl = new System.Windows.Forms.LinkLabel(); - this.okButton = new System.Windows.Forms.Button(); - this.cancelButton = new System.Windows.Forms.Button(); - this.cbCloseOnActivity = new System.Windows.Forms.CheckBox(); - this.screenTabControl = new System.Windows.Forms.TabControl(); - this.screenTabPage1 = new System.Windows.Forms.TabPage(); - this.prefsByScreenUserControl1 = new PrefsByScreenUserControl(); - this.spanScreensButton = new System.Windows.Forms.RadioButton(); - this.separateScreensButton = new System.Windows.Forms.RadioButton(); - this.label4 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.mirrorScreensButton = new System.Windows.Forms.RadioButton(); - this.multiScreenGroup = new System.Windows.Forms.GroupBox(); - this.screenModeTooltip = new System.Windows.Forms.ToolTip(this.components); - this.screenTabControl.SuspendLayout(); - this.screenTabPage1.SuspendLayout(); - this.multiScreenGroup.SuspendLayout(); + this._linkLabelProjectURL = new System.Windows.Forms.LinkLabel(); + this._tabControlScreens = new System.Windows.Forms.TabControl(); + this._tabPageScreen = new System.Windows.Forms.TabPage(); + this._labelWebsiteURLs = new System.Windows.Forms.Label(); + this._toolTipScreenMode = new System.Windows.Forms.ToolTip(this.components); + this._radioButtonSeparateScreens = new System.Windows.Forms.RadioButton(); + this._radioButtonMirrorScreens = new System.Windows.Forms.RadioButton(); + this._radioButtonSpanScreens = new System.Windows.Forms.RadioButton(); + this._tableLayoutPanelMain = new System.Windows.Forms.TableLayoutPanel(); + this._tableLayoutPanelMainBottom = new System.Windows.Forms.TableLayoutPanel(); + this._buttonCancel = new System.Windows.Forms.Button(); + this._buttonOK = new System.Windows.Forms.Button(); + this._tableLayoutPanelMainTop = new System.Windows.Forms.TableLayoutPanel(); + this._checkBoxCloseOnMouseMovement = new System.Windows.Forms.CheckBox(); + this._labelMultiScreen = new System.Windows.Forms.Label(); + this._flowLayoutPanelMultiScreenMode = new System.Windows.Forms.FlowLayoutPanel(); + this._tabControlScreens.SuspendLayout(); + this._tableLayoutPanelMain.SuspendLayout(); + this._tableLayoutPanelMainBottom.SuspendLayout(); + this._tableLayoutPanelMainTop.SuspendLayout(); + this._flowLayoutPanelMultiScreenMode.SuspendLayout(); this.SuspendLayout(); // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(101, 11); - this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(158, 17); - this.label1.TabIndex = 0; - this.label1.Text = "Web Page Screensaver"; - // - // llProjectLocationUrl - // - this.llProjectLocationUrl.AutoSize = true; - this.llProjectLocationUrl.Location = new System.Drawing.Point(29, 31); - this.llProjectLocationUrl.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.llProjectLocationUrl.Name = "llProjectLocationUrl"; - this.llProjectLocationUrl.Size = new System.Drawing.Size(293, 17); - this.llProjectLocationUrl.TabIndex = 1; - this.llProjectLocationUrl.TabStop = true; - this.llProjectLocationUrl.Text = "http://github.com/cwc/web-page-screensaver/"; - this.llProjectLocationUrl.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.llProjectLocationUrl_LinkClicked); - // - // okButton - // - this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; - this.okButton.Location = new System.Drawing.Point(127, 441); - this.okButton.Margin = new System.Windows.Forms.Padding(4); - this.okButton.Name = "okButton"; - this.okButton.Size = new System.Drawing.Size(100, 28); - this.okButton.TabIndex = 4; - this.okButton.Text = "OK"; - this.okButton.UseVisualStyleBackColor = true; - this.okButton.Click += new System.EventHandler(this.okButton_Click); - // - // cancelButton - // - this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(235, 441); - this.cancelButton.Margin = new System.Windows.Forms.Padding(4); - this.cancelButton.Name = "cancelButton"; - this.cancelButton.Size = new System.Drawing.Size(100, 28); - this.cancelButton.TabIndex = 5; - this.cancelButton.Text = "Cancel"; - this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); - // - // cbCloseOnActivity - // - this.cbCloseOnActivity.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.cbCloseOnActivity.AutoSize = true; - this.cbCloseOnActivity.Checked = true; - this.cbCloseOnActivity.CheckState = System.Windows.Forms.CheckState.Checked; - this.cbCloseOnActivity.Location = new System.Drawing.Point(20, 411); - this.cbCloseOnActivity.Margin = new System.Windows.Forms.Padding(4); - this.cbCloseOnActivity.Name = "cbCloseOnActivity"; - this.cbCloseOnActivity.Size = new System.Drawing.Size(200, 21); - this.cbCloseOnActivity.TabIndex = 6; - this.cbCloseOnActivity.Text = "Close on mouse movement"; - this.cbCloseOnActivity.UseVisualStyleBackColor = true; - // - // screenTabControl - // - this.screenTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + // _linkLabelProjectURL + // + this._linkLabelProjectURL.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.screenTabControl.Controls.Add(this.screenTabPage1); - this.screenTabControl.Location = new System.Drawing.Point(20, 119); - this.screenTabControl.Name = "screenTabControl"; - this.screenTabControl.SelectedIndex = 0; - this.screenTabControl.Size = new System.Drawing.Size(319, 271); - this.screenTabControl.TabIndex = 13; - // - // screenTabPage1 - // - this.screenTabPage1.Controls.Add(this.prefsByScreenUserControl1); - this.screenTabPage1.Location = new System.Drawing.Point(4, 25); - this.screenTabPage1.Name = "screenTabPage1"; - this.screenTabPage1.Padding = new System.Windows.Forms.Padding(3); - this.screenTabPage1.Size = new System.Drawing.Size(311, 242); - this.screenTabPage1.TabIndex = 0; - this.screenTabPage1.Text = "Screen 1"; - this.screenTabPage1.UseVisualStyleBackColor = true; - // - // prefsByScreenUserControl1 - // - this.prefsByScreenUserControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this._linkLabelProjectURL.AutoSize = true; + this._linkLabelProjectURL.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._linkLabelProjectURL.Location = new System.Drawing.Point(6, 0); + this._linkLabelProjectURL.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0); + this._linkLabelProjectURL.Name = "_linkLabelProjectURL"; + this._linkLabelProjectURL.Size = new System.Drawing.Size(278, 35); + this._linkLabelProjectURL.TabIndex = 13; + this._linkLabelProjectURL.TabStop = true; + this._linkLabelProjectURL.Text = "Website"; + this._linkLabelProjectURL.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + this._linkLabelProjectURL.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelProjectURL_LinkClicked); + // + // _tabControlScreens + // + this._tabControlScreens.Controls.Add(this._tabPageScreen); + this._tabControlScreens.Dock = System.Windows.Forms.DockStyle.Fill; + this._tabControlScreens.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._tabControlScreens.Location = new System.Drawing.Point(0, 105); + this._tabControlScreens.Margin = new System.Windows.Forms.Padding(0); + this._tabControlScreens.Name = "_tabControlScreens"; + this._tabControlScreens.SelectedIndex = 0; + this._tabControlScreens.Size = new System.Drawing.Size(464, 221); + // + // _tabPageScreen + // + this._tabPageScreen.Location = new System.Drawing.Point(4, 24); + this._tabPageScreen.Margin = new System.Windows.Forms.Padding(6); + this._tabPageScreen.Name = "_tabPageScreen"; + this._tabPageScreen.Size = new System.Drawing.Size(456, 193); + this._tabPageScreen.TabIndex = 5; + this._tabPageScreen.UseVisualStyleBackColor = true; + // + // _labelWebsiteURLs + // + this._labelWebsiteURLs.AutoSize = true; + this._labelWebsiteURLs.Dock = System.Windows.Forms.DockStyle.Fill; + this._labelWebsiteURLs.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._labelWebsiteURLs.Location = new System.Drawing.Point(6, 76); + this._labelWebsiteURLs.Margin = new System.Windows.Forms.Padding(6); + this._labelWebsiteURLs.Name = "_labelWebsiteURLs"; + this._labelWebsiteURLs.Size = new System.Drawing.Size(452, 23); + this._labelWebsiteURLs.Text = "Website URLs:"; + this._labelWebsiteURLs.TextAlign = System.Drawing.ContentAlignment.BottomLeft; + // + // _radioButtonSeparateScreens + // + this._radioButtonSeparateScreens.AutoSize = true; + this._radioButtonSeparateScreens.Dock = System.Windows.Forms.DockStyle.Fill; + this._radioButtonSeparateScreens.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._radioButtonSeparateScreens.Location = new System.Drawing.Point(6, 6); + this._radioButtonSeparateScreens.Margin = new System.Windows.Forms.Padding(6); + this._radioButtonSeparateScreens.Name = "_radioButtonSeparateScreens"; + this._radioButtonSeparateScreens.Size = new System.Drawing.Size(70, 19); + this._radioButtonSeparateScreens.TabIndex = 2; + this._radioButtonSeparateScreens.Tag = "MultiScreenMode"; + this._radioButtonSeparateScreens.Text = "Separate"; + this._toolTipScreenMode.SetToolTip(this._radioButtonSeparateScreens, "Each to their own!"); + this._radioButtonSeparateScreens.UseVisualStyleBackColor = true; + this._radioButtonSeparateScreens.CheckedChanged += new System.EventHandler(this.RadioButtonMultiScreenMode_Checked); + // + // _radioButtonMirrorScreens + // + this._radioButtonMirrorScreens.AutoSize = true; + this._radioButtonMirrorScreens.Dock = System.Windows.Forms.DockStyle.Fill; + this._radioButtonMirrorScreens.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._radioButtonMirrorScreens.Location = new System.Drawing.Point(88, 6); + this._radioButtonMirrorScreens.Margin = new System.Windows.Forms.Padding(6); + this._radioButtonMirrorScreens.Name = "_radioButtonMirrorScreens"; + this._radioButtonMirrorScreens.Size = new System.Drawing.Size(58, 19); + this._radioButtonMirrorScreens.TabIndex = 3; + this._radioButtonMirrorScreens.Tag = "MultiScreenMode"; + this._radioButtonMirrorScreens.Text = "Mirror"; + this._toolTipScreenMode.SetToolTip(this._radioButtonMirrorScreens, "One for All!"); + this._radioButtonMirrorScreens.UseVisualStyleBackColor = true; + this._radioButtonMirrorScreens.CheckedChanged += new System.EventHandler(this.RadioButtonMultiScreenMode_Checked); + // + // _radioButtonSpanScreens + // + this._radioButtonSpanScreens.AutoSize = true; + this._radioButtonSpanScreens.Dock = System.Windows.Forms.DockStyle.Fill; + this._radioButtonSpanScreens.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._radioButtonSpanScreens.Location = new System.Drawing.Point(158, 6); + this._radioButtonSpanScreens.Margin = new System.Windows.Forms.Padding(6); + this._radioButtonSpanScreens.Name = "_radioButtonSpanScreens"; + this._radioButtonSpanScreens.Size = new System.Drawing.Size(51, 19); + this._radioButtonSpanScreens.TabIndex = 4; + this._radioButtonSpanScreens.Tag = "MultiScreenMode"; + this._radioButtonSpanScreens.Text = "Span"; + this._toolTipScreenMode.SetToolTip(this._radioButtonSpanScreens, "All for One!"); + this._radioButtonSpanScreens.UseVisualStyleBackColor = true; + this._radioButtonSpanScreens.CheckedChanged += new System.EventHandler(this.RadioButtonMultiScreenMode_Checked); + // + // _tableLayoutPanelMain + // + this._tableLayoutPanelMain.AutoSize = true; + this._tableLayoutPanelMain.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._tableLayoutPanelMain.ColumnCount = 1; + this._tableLayoutPanelMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMain.Controls.Add(this._tabControlScreens, 0, 2); + this._tableLayoutPanelMain.Controls.Add(this._tableLayoutPanelMainBottom, 0, 3); + this._tableLayoutPanelMain.Controls.Add(this._tableLayoutPanelMainTop, 0, 0); + this._tableLayoutPanelMain.Controls.Add(this._labelWebsiteURLs, 0, 1); + this._tableLayoutPanelMain.Dock = System.Windows.Forms.DockStyle.Fill; + this._tableLayoutPanelMain.Location = new System.Drawing.Point(0, 0); + this._tableLayoutPanelMain.Margin = new System.Windows.Forms.Padding(0); + this._tableLayoutPanelMain.Name = "_tableLayoutPanelMain"; + this._tableLayoutPanelMain.RowCount = 4; + this._tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 70F)); + this._tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F)); + this._tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F)); + this._tableLayoutPanelMain.Size = new System.Drawing.Size(464, 361); + // + // _tableLayoutPanelMainBottom + // + this._tableLayoutPanelMainBottom.AutoSize = true; + this._tableLayoutPanelMainBottom.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._tableLayoutPanelMainBottom.ColumnCount = 3; + this._tableLayoutPanelMainBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMainBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanelMainBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanelMainBottom.Controls.Add(this._buttonCancel, 2, 0); + this._tableLayoutPanelMainBottom.Controls.Add(this._linkLabelProjectURL, 0, 0); + this._tableLayoutPanelMainBottom.Controls.Add(this._buttonOK, 1, 0); + this._tableLayoutPanelMainBottom.Dock = System.Windows.Forms.DockStyle.Fill; + this._tableLayoutPanelMainBottom.Location = new System.Drawing.Point(0, 326); + this._tableLayoutPanelMainBottom.Margin = new System.Windows.Forms.Padding(0); + this._tableLayoutPanelMainBottom.Name = "_tableLayoutPanelMainBottom"; + this._tableLayoutPanelMainBottom.RowCount = 1; + this._tableLayoutPanelMainBottom.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this._tableLayoutPanelMainBottom.Size = new System.Drawing.Size(464, 35); + // + // _buttonCancel + // + this._buttonCancel.Anchor = System.Windows.Forms.AnchorStyles.None; + this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this._buttonCancel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._buttonCancel.Location = new System.Drawing.Point(383, 6); + this._buttonCancel.Margin = new System.Windows.Forms.Padding(6); + this._buttonCancel.Name = "_buttonCancel"; + this._buttonCancel.Size = new System.Drawing.Size(75, 23); + this._buttonCancel.TabIndex = 15; + this._buttonCancel.Text = "Cancel"; + this._buttonCancel.UseVisualStyleBackColor = true; + this._buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click); + // + // _buttonOK + // + this._buttonOK.Anchor = System.Windows.Forms.AnchorStyles.None; + this._buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this._buttonOK.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._buttonOK.Location = new System.Drawing.Point(296, 6); + this._buttonOK.Margin = new System.Windows.Forms.Padding(6); + this._buttonOK.Name = "_buttonOK"; + this._buttonOK.Size = new System.Drawing.Size(75, 23); + this._buttonOK.TabIndex = 14; + this._buttonOK.Text = "OK"; + this._buttonOK.UseVisualStyleBackColor = true; + this._buttonOK.Click += new System.EventHandler(this.ButtonOK_Click); + // + // _tableLayoutPanelMainTop + // + this._tableLayoutPanelMainTop.AutoSize = true; + this._tableLayoutPanelMainTop.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._tableLayoutPanelMainTop.ColumnCount = 2; + this._tableLayoutPanelMainTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanelMainTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanelMainTop.Controls.Add(this._checkBoxCloseOnMouseMovement, 0, 0); + this._tableLayoutPanelMainTop.Controls.Add(this._labelMultiScreen, 1, 0); + this._tableLayoutPanelMainTop.Controls.Add(this._flowLayoutPanelMultiScreenMode, 1, 1); + this._tableLayoutPanelMainTop.Dock = System.Windows.Forms.DockStyle.Fill; + this._tableLayoutPanelMainTop.Location = new System.Drawing.Point(0, 0); + this._tableLayoutPanelMainTop.Margin = new System.Windows.Forms.Padding(0); + this._tableLayoutPanelMainTop.Name = "_tableLayoutPanelMainTop"; + this._tableLayoutPanelMainTop.RowCount = 2; + this._tableLayoutPanelMainTop.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this._tableLayoutPanelMainTop.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this._tableLayoutPanelMainTop.Size = new System.Drawing.Size(464, 70); + // + // _checkBoxCloseOnMouseMovement + // + this._checkBoxCloseOnMouseMovement.AutoSize = true; + this._checkBoxCloseOnMouseMovement.Checked = true; + this._checkBoxCloseOnMouseMovement.CheckState = System.Windows.Forms.CheckState.Checked; + this._checkBoxCloseOnMouseMovement.Dock = System.Windows.Forms.DockStyle.Fill; + this._checkBoxCloseOnMouseMovement.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._checkBoxCloseOnMouseMovement.Location = new System.Drawing.Point(6, 6); + this._checkBoxCloseOnMouseMovement.Margin = new System.Windows.Forms.Padding(6); + this._checkBoxCloseOnMouseMovement.Name = "_checkBoxCloseOnMouseMovement"; + this._checkBoxCloseOnMouseMovement.Size = new System.Drawing.Size(172, 19); + this._checkBoxCloseOnMouseMovement.TabIndex = 1; + this._checkBoxCloseOnMouseMovement.Text = "Close on mouse movement"; + this._checkBoxCloseOnMouseMovement.UseVisualStyleBackColor = true; + // + // _labelMultiScreen + // + this._labelMultiScreen.AutoSize = true; + this._labelMultiScreen.Dock = System.Windows.Forms.DockStyle.Fill; + this._labelMultiScreen.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._labelMultiScreen.Location = new System.Drawing.Point(190, 6); + this._labelMultiScreen.Margin = new System.Windows.Forms.Padding(6); + this._labelMultiScreen.Name = "_labelMultiScreen"; + this._labelMultiScreen.Size = new System.Drawing.Size(268, 19); + this._labelMultiScreen.Text = "Multiscreen:"; + this._labelMultiScreen.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // _flowLayoutPanelMultiScreenMode + // + this._flowLayoutPanelMultiScreenMode.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.prefsByScreenUserControl1.BackColor = System.Drawing.Color.White; - this.prefsByScreenUserControl1.Location = new System.Drawing.Point(0, 0); - this.prefsByScreenUserControl1.Name = "prefsByScreenUserControl1"; - this.prefsByScreenUserControl1.Size = new System.Drawing.Size(312, 242); - this.prefsByScreenUserControl1.TabIndex = 21; - // - // spanScreensButton - // - this.spanScreensButton.AutoSize = true; - this.spanScreensButton.Checked = true; - this.spanScreensButton.Location = new System.Drawing.Point(100, 10); - this.spanScreensButton.Name = "spanScreensButton"; - this.spanScreensButton.Size = new System.Drawing.Size(62, 21); - this.spanScreensButton.TabIndex = 14; - this.spanScreensButton.TabStop = true; - this.spanScreensButton.Tag = "MultiScreenMode"; - this.spanScreensButton.Text = "Span"; - this.screenModeTooltip.SetToolTip(this.spanScreensButton, "All for One!"); - this.spanScreensButton.UseVisualStyleBackColor = true; - this.spanScreensButton.Click += new System.EventHandler(this.anyMultiScreenModeButton_Click); - // - // separateScreensButton - // - this.separateScreensButton.AutoSize = true; - this.separateScreensButton.Location = new System.Drawing.Point(238, 10); - this.separateScreensButton.Name = "separateScreensButton"; - this.separateScreensButton.Size = new System.Drawing.Size(87, 21); - this.separateScreensButton.TabIndex = 15; - this.separateScreensButton.TabStop = true; - this.separateScreensButton.Tag = "MultiScreenMode"; - this.separateScreensButton.Text = "Separate"; - this.screenModeTooltip.SetToolTip(this.separateScreensButton, "Each to their own."); - this.separateScreensButton.UseVisualStyleBackColor = true; - this.separateScreensButton.Click += new System.EventHandler(this.anyMultiScreenModeButton_Click); - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(4, 12); - this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(84, 17); - this.label4.TabIndex = 16; - this.label4.Text = "Multiscreen:"; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(16, 97); - this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(98, 17); - this.label2.TabIndex = 2; - this.label2.Text = "Website URLs"; - // - // mirrorScreensButton - // - this.mirrorScreensButton.AutoSize = true; - this.mirrorScreensButton.Location = new System.Drawing.Point(168, 10); - this.mirrorScreensButton.Name = "mirrorScreensButton"; - this.mirrorScreensButton.Size = new System.Drawing.Size(66, 21); - this.mirrorScreensButton.TabIndex = 17; - this.mirrorScreensButton.TabStop = true; - this.mirrorScreensButton.Tag = "MultiScreenMode"; - this.mirrorScreensButton.Text = "Mirror"; - this.screenModeTooltip.SetToolTip(this.mirrorScreensButton, "One for All!"); - this.mirrorScreensButton.UseVisualStyleBackColor = true; - this.mirrorScreensButton.Click += new System.EventHandler(this.anyMultiScreenModeButton_Click); - // - // multiScreenGroup - // - this.multiScreenGroup.Controls.Add(this.label4); - this.multiScreenGroup.Controls.Add(this.mirrorScreensButton); - this.multiScreenGroup.Controls.Add(this.spanScreensButton); - this.multiScreenGroup.Controls.Add(this.separateScreensButton); - this.multiScreenGroup.Location = new System.Drawing.Point(20, 56); - this.multiScreenGroup.Name = "multiScreenGroup"; - this.multiScreenGroup.Size = new System.Drawing.Size(326, 34); - this.multiScreenGroup.TabIndex = 18; - this.multiScreenGroup.TabStop = false; + this._flowLayoutPanelMultiScreenMode.AutoSize = true; + this._flowLayoutPanelMultiScreenMode.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._flowLayoutPanelMultiScreenMode.Controls.Add(this._radioButtonSeparateScreens); + this._flowLayoutPanelMultiScreenMode.Controls.Add(this._radioButtonMirrorScreens); + this._flowLayoutPanelMultiScreenMode.Controls.Add(this._radioButtonSpanScreens); + this._flowLayoutPanelMultiScreenMode.Location = new System.Drawing.Point(187, 34); + this._flowLayoutPanelMultiScreenMode.Name = "_flowLayoutPanelMultiScreenMode"; + this._flowLayoutPanelMultiScreenMode.Size = new System.Drawing.Size(274, 33); // // PreferencesForm // - this.AcceptButton = this.okButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.cancelButton; - this.ClientSize = new System.Drawing.Size(360, 478); - this.Controls.Add(this.multiScreenGroup); - this.Controls.Add(this.screenTabControl); - this.Controls.Add(this.cbCloseOnActivity); - this.Controls.Add(this.cancelButton); - this.Controls.Add(this.okButton); - this.Controls.Add(this.label2); - this.Controls.Add(this.llProjectLocationUrl); - this.Controls.Add(this.label1); - this.Margin = new System.Windows.Forms.Padding(4); + this.AutoSize = true; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.ClientSize = new System.Drawing.Size(464, 361); + this.Controls.Add(this._tableLayoutPanelMain); + this.Margin = new System.Windows.Forms.Padding(6, 7, 6, 7); this.MaximizeBox = false; this.MinimizeBox = false; - this.MinimumSize = new System.Drawing.Size(378, 428); this.Name = "PreferencesForm"; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Web Page Screensaver Settings"; this.Load += new System.EventHandler(this.PreferencesForm_Load); - this.screenTabControl.ResumeLayout(false); - this.screenTabPage1.ResumeLayout(false); - this.multiScreenGroup.ResumeLayout(false); - this.multiScreenGroup.PerformLayout(); + this._tabControlScreens.ResumeLayout(false); + this._tableLayoutPanelMain.ResumeLayout(false); + this._tableLayoutPanelMain.PerformLayout(); + this._tableLayoutPanelMainBottom.ResumeLayout(false); + this._tableLayoutPanelMainBottom.PerformLayout(); + this._tableLayoutPanelMainTop.ResumeLayout(false); + this._tableLayoutPanelMainTop.PerformLayout(); + this._flowLayoutPanelMultiScreenMode.ResumeLayout(false); + this._flowLayoutPanelMultiScreenMode.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } - #endregion + private System.Windows.Forms.TableLayoutPanel _tableLayoutPanelMain; + + private System.Windows.Forms.TableLayoutPanel _tableLayoutPanelMainTop; + private System.Windows.Forms.Label _labelMultiScreen; + private System.Windows.Forms.RadioButton _radioButtonSpanScreens; + private System.Windows.Forms.RadioButton _radioButtonMirrorScreens; + private System.Windows.Forms.RadioButton _radioButtonSeparateScreens; + private System.Windows.Forms.ToolTip _toolTipScreenMode; + private System.Windows.Forms.CheckBox _checkBoxCloseOnMouseMovement; + + private System.Windows.Forms.Label _labelWebsiteURLs; + private System.Windows.Forms.TabControl _tabControlScreens; + private System.Windows.Forms.TabPage _tabPageScreen; + + private System.Windows.Forms.TableLayoutPanel _tableLayoutPanelMainBottom; + private System.Windows.Forms.LinkLabel _linkLabelProjectURL; + private System.Windows.Forms.Button _buttonCancel; + private System.Windows.Forms.Button _buttonOK; + private System.Windows.Forms.FlowLayoutPanel _flowLayoutPanelMultiScreenMode; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.LinkLabel llProjectLocationUrl; - private System.Windows.Forms.Button okButton; - private System.Windows.Forms.Button cancelButton; - private System.Windows.Forms.CheckBox cbCloseOnActivity; - private System.Windows.Forms.TabControl screenTabControl; - private System.Windows.Forms.TabPage screenTabPage1; - private System.Windows.Forms.RadioButton spanScreensButton; - private System.Windows.Forms.RadioButton separateScreensButton; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.RadioButton mirrorScreensButton; - private System.Windows.Forms.GroupBox multiScreenGroup; - private PrefsByScreenUserControl prefsByScreenUserControl1; - private System.Windows.Forms.ToolTip screenModeTooltip; + private System.ComponentModel.IContainer components; } } \ No newline at end of file diff --git a/PreferencesForm.cs b/PreferencesForm.cs index 5c63c85..1ca3c0f 100644 --- a/PreferencesForm.cs +++ b/PreferencesForm.cs @@ -1,208 +1,168 @@ using System; -using System.Linq; -using Microsoft.Win32; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; using System.Windows.Forms; -namespace pl.polidea.lab.Web_Page_Screensaver +namespace WebPageScreensaver { - using System.Collections.Generic; - using System.Drawing; - - using global::Web_Page_Screensaver; - - public partial class PreferencesForm : Form + internal partial class PreferencesForm : Form { - private PreferencesManager prefsManager = new PreferencesManager(); - - private List screenUserControls; + private const string Webpage = "http://github.com/carlossanlop/web-page-screensaver/"; public PreferencesForm() { InitializeComponent(); } + /// + /// Method called when the form is loaded, so the UI gets updated with the registry data. + /// private void PreferencesForm_Load(object sender, EventArgs e) { - cbCloseOnActivity.Checked = prefsManager.CloseOnActivity; - if (Screen.AllScreens.Count() == 1) - { - multiScreenGroup.Enabled = false; - } - else - { - multiScreenGroup.Enabled = true; - SetMultiScreenButtonFromMode(); - ArrangeScreenTabs(); - } - } + _checkBoxCloseOnMouseMovement.Checked = Preferences.CloseOnMouseMovement; - private void LoadValuesForTab(int screenNum) - { - var currentPrefsUserControl = screenUserControls[screenNum]; - loadUrlsForTabToControl(screenNum, currentPrefsUserControl); - currentPrefsUserControl.nudRotationInterval.Value = prefsManager.GetRotationIntervalByScreen(screenNum); - currentPrefsUserControl.cbRandomize.Checked = prefsManager.GetRandomizeFlagByScreen(screenNum); - } + MultiScreenMode multiScreenMode = Preferences.MultiScreen; - private void ArrangeScreenTabs() - { - switch (prefsManager.MultiScreenMode) - { - case PreferencesManager.MultiScreenModeItem.Span: - RemoveExtraTabPages(); - screenTabControl.TabPages[0].Text = "Composite Screen"; - screenUserControls = new List() { prefsByScreenUserControl1 }; - LoadValuesForTab(0); - break; - case PreferencesManager.MultiScreenModeItem.Mirror: - RemoveExtraTabPages(); - screenTabControl.TabPages[0].Text = "Each Screen"; - screenUserControls = new List() { prefsByScreenUserControl1 }; - LoadValuesForTab(0); - break; - case PreferencesManager.MultiScreenModeItem.Separate: - for (int i = 0; i < Screen.AllScreens.Length; i++) - { - TabPage tabPage = null; - - if (i >= screenTabControl.TabPages.Count) - { - tabPage = new TabPage(); - screenTabControl.TabPages.Add(tabPage); - - if (i > 0) - { - var prefsByScreenUserControl = new PrefsByScreenUserControl - { - Name = string.Format("prefsByScreenUserControl{0}", i + 1), - Location = new Point(0, 0), //prefsByScreenUserControl1.Location, - Size = prefsByScreenUserControl1.Size, - Anchor = prefsByScreenUserControl1.Anchor, - BackColor = prefsByScreenUserControl1.BackColor - }; - prefsByScreenUserControl.lvUrls.ContextMenuStrip = - prefsByScreenUserControl1.ContextMenuStrip; - screenUserControls.Add(prefsByScreenUserControl); - tabPage.Controls.Add(prefsByScreenUserControl); - } - } - else if (screenTabControl.TabPages.Count == 1) - { - tabPage = screenTabControl.TabPages[0]; - screenUserControls = - new List() { prefsByScreenUserControl1 }; - } - - LoadValuesForTab(i); - string primaryIndicator = string.Empty; - if (Screen.AllScreens[i].Primary) primaryIndicator = " (main)"; - tabPage.Text = string.Format("Screen {0}{1}", i + 1, primaryIndicator); - } - - break; - } - } + // The Checked event will determine what to show in the tabs + _radioButtonMirrorScreens.Checked = multiScreenMode == MultiScreenMode.Mirror; + _radioButtonSeparateScreens.Checked = multiScreenMode == MultiScreenMode.Separate; + _radioButtonSpanScreens.Checked = multiScreenMode == MultiScreenMode.Span; - private void RemoveExtraTabPages() - { - while (screenTabControl.TabPages.Count > 1) - { - screenTabControl.TabPages.RemoveAt(screenTabControl.TabPages.Count - 1); - } + //_flowLayoutPanelMultiScreenMode.Enabled = Screen.AllScreens.Length > 1; } - private void SetMultiScreenButtonFromMode() - { - switch (prefsManager.MultiScreenMode) - { - case PreferencesManager.MultiScreenModeItem.Span: - spanScreensButton.Checked = true; - break; - case PreferencesManager.MultiScreenModeItem.Mirror: - mirrorScreensButton.Checked = true; - break; - case PreferencesManager.MultiScreenModeItem.Separate: - separateScreensButton.Checked = true; - break; - } - } - private void setMultiScreenModeFromButtonState() + private void RadioButtonMultiScreenMode_Checked(object sender, EventArgs e) { - if (spanScreensButton.Checked) - { - prefsManager.MultiScreenMode = PreferencesManager.MultiScreenModeItem.Span; - } - else if (mirrorScreensButton.Checked) + if (sender is not RadioButton radioButton || !radioButton.Checked) { - prefsManager.MultiScreenMode = PreferencesManager.MultiScreenModeItem.Mirror; + return; } - else + + MultiScreenMode multiScreenMode = radioButton.Name switch { - prefsManager.MultiScreenMode = PreferencesManager.MultiScreenModeItem.Separate; - } + nameof(_radioButtonMirrorScreens) => MultiScreenMode.Mirror, + nameof(_radioButtonSeparateScreens) => MultiScreenMode.Separate, + nameof(_radioButtonSpanScreens) => MultiScreenMode.Span, + _ => throw new IndexOutOfRangeException("Unexpected radio button."), + }; - prefsManager.ResetEffectiveScreensList(); - } + // Save it to the registry + Preferences.MultiScreen = multiScreenMode; - private void readBackValuesFromUI() - { - for (var i = 0; i < screenUserControls.Count; i++) + int totalTabs = multiScreenMode switch { - var currentPrefsUserControl = screenUserControls[i]; - List urls = (from ListViewItem lvUrlsItem in currentPrefsUserControl.lvUrls.Items - select lvUrlsItem.Text).ToList(); - prefsManager.SetUrlsForScreen(i, urls); - prefsManager.SetRotationIntervalForScreen(i, - (int)currentPrefsUserControl.nudRotationInterval.Value); - prefsManager.SetRandomizeFlagForScreen(i, currentPrefsUserControl.cbRandomize.Checked); - prefsManager.CloseOnActivity = cbCloseOnActivity.Checked; - } - } + MultiScreenMode.Mirror or MultiScreenMode.Span => 1, + MultiScreenMode.Separate => Screen.AllScreens.Length, + _ => throw new IndexOutOfRangeException("Unrecognized MultiScreenMode value.") + }; - private void loadUrlsForTabToControl(int screenNum, PrefsByScreenUserControl currentPrefsUserControl) - { - currentPrefsUserControl.lvUrls.Items.Clear(); + string tabTextSuffix = multiScreenMode switch + { + MultiScreenMode.Mirror => " (Mirror)", + MultiScreenMode.Span => " (Composite)", + MultiScreenMode.Separate => "", + _ => throw new IndexOutOfRangeException("Unrecognized MultiScreenMode value.") + }; - var urls = prefsManager.GetUrlsByScreen(screenNum); + _tabControlScreens.TabPages.Clear(); - foreach (var url in urls) + for (int tabNumber = 0; tabNumber < totalTabs; tabNumber++) { - currentPrefsUserControl.lvUrls.Items.Add(url); + TabPage tab = new TabPage + { + Text = $"Display {tabNumber + 1}{tabTextSuffix}" // Matches registry key name + }; + + var currentUserControl = new PrefsByScreenUserControl + { + AutoSize = true, + BackColor = Color.White, + Dock = DockStyle.Fill, + Name = $"_prefsByScreenUserControl{tabNumber}", + TabIndex = 5 + }; + + ScreenInformation currentScreen = Preferences.Screens[tabNumber]; + + foreach (string url in currentScreen.URLs) + { + currentUserControl._listViewURLs.Items.Add(url); + } + + currentUserControl._numericUpDownRotationInterval.Value = currentScreen.RotationInterval; + currentUserControl._checkBoxShuffle.Checked = currentScreen.Shuffle; + + tab.Controls.Add(currentUserControl); + _tabControlScreens.TabPages.Add(tab); } } - protected override void OnClosed(EventArgs e) + /// + /// Opens the project website in a new default browser tab. + /// + private void LinkLabelProjectURL_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { - if (DialogResult == DialogResult.OK) + ProcessStartInfo startInfo = new ProcessStartInfo() { - readBackValuesFromUI(); - prefsManager.SavePreferences(); - } - - base.OnClosed(e); + FileName = "cmd", + Arguments = $"/c start {Webpage}", + CreateNoWindow = true + }; + Process.Start(startInfo); } - private void llProjectLocationUrl_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - System.Diagnostics.Process.Start(llProjectLocationUrl.Text); - } - - private void okButton_Click(object sender, EventArgs e) + /// + /// Saves the selected settings and closes the window. + /// + private void ButtonOK_Click(object sender, EventArgs e) { + Save(); Close(); } - private void cancelButton_Click(object sender, EventArgs e) + /// + /// Closes the window without saving the settings. + /// + private void ButtonCancel_Click(object sender, EventArgs e) { Close(); } - private void anyMultiScreenModeButton_Click(object sender, EventArgs e) + /// + /// Read the data from the form and save it in the registry. + /// + private void Save() { - readBackValuesFromUI(); - setMultiScreenModeFromButtonState(); - ArrangeScreenTabs(); + Preferences.CloseOnMouseMovement = _checkBoxCloseOnMouseMovement.Checked; + + if (_radioButtonSpanScreens.Checked) + { + Preferences.MultiScreen = MultiScreenMode.Span; + } + else if (_radioButtonMirrorScreens.Checked) + { + Preferences.MultiScreen = MultiScreenMode.Mirror; + } + else // default + { + Preferences.MultiScreen = MultiScreenMode.Separate; + } + + int screenNumber = 0; + foreach (TabPage tab in _tabControlScreens.TabPages) + { + if (tab.Controls[0] is PrefsByScreenUserControl userControl) + { + userControl.Save(screenNumber); + screenNumber++; + } + else + { + throw new KeyNotFoundException("PrefsByScreenUserControl instance not found in tab."); + } + } } } } diff --git a/PreferencesForm.resx b/PreferencesForm.resx deleted file mode 100644 index c13c2e3..0000000 --- a/PreferencesForm.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - \ No newline at end of file diff --git a/PreferencesManager.cs b/PreferencesManager.cs deleted file mode 100644 index 56a2c79..0000000 --- a/PreferencesManager.cs +++ /dev/null @@ -1,354 +0,0 @@ -namespace pl.polidea.lab.Web_Page_Screensaver -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Drawing; - using System.Linq; - using System.Windows.Forms; - using Microsoft.Win32; - - public class PreferencesManager - { - private const string MULTISCREEN_PREF = "MultiScreenMode"; - private const string URL_PREF = "Url"; - private const string INTERVAL_PREF = "RotationInterval"; - private const string RANDOMIZE_PREF = "RandomOrder"; - private const string CLOSE_ON_ACTIVITY_PREF = "CloseOnActivity"; - - private const string SCREEN_SPECIFIC_PREF_NAME_FORMATSTRING = "{0}Screen{1}"; - - private const string MULTISCREEN_PREF_DEFAULT = "Separate"; - private const string URL_PREF_PRIMARYSCREEN_DEFAULT = "https://www.google.com/trends/hottrends/visualize?nrow=5&ncol=5 https://screensaver.twingly.com/"; - private const string URL_PREF_NONPRIMARYSCREEN_DEFAULT = ""; - private const string INTERVAL_PREF_DEFAULT = "30"; - private const string RANDOMIZE_PREF_DEFAULT = "False"; - private const string CLOSE_ON_ACTIVITY_PREF_DEFAULT = "True"; - - private static RegistryKey reg = Registry.CurrentUser.CreateSubKey(Program.KEY); - - public PreferencesManager() - { - LoadPreferences(); - } - - private List effectiveScreensListField; - public List EffectiveScreensList - { - get - { - if (effectiveScreensListField == null) - { - effectiveScreensListField = new List(); - switch (MultiScreenMode) - { - case MultiScreenModeItem.Span: - Rectangle enclosingRect = FindEnclosingRect(Screen.AllScreens.Select(r => r.Bounds).ToList()); - effectiveScreensListField.Add( - new BasicScreenInfo { ScreenNum = 0, Bounds = enclosingRect, IsPrimary = true }); - break; - - case MultiScreenModeItem.Mirror: - for (int i = 0; i < Screen.AllScreens.Length; i++) - { - effectiveScreensListField.Add( - new BasicScreenInfo - { - ScreenNum = i, - Bounds = Screen.AllScreens[i].Bounds, - IsPrimary = true - }); - } - break; - - case MultiScreenModeItem.Separate: - for (int i = 0; i < Screen.AllScreens.Length; i++) - { - effectiveScreensListField.Add( - new BasicScreenInfo - { - ScreenNum = i, - Bounds = Screen.AllScreens[i].Bounds, - IsPrimary = Screen.AllScreens[i].Primary - }); - } - break; - } - } - return effectiveScreensListField; - } - } - - public void ResetEffectiveScreensList() - { - effectiveScreensListField = null; - } - - private int? realPrimaryScreenNumField; - private int RealPrimaryScreenNum() - { - if (realPrimaryScreenNumField == null) - { - realPrimaryScreenNumField = 0; - for (int i = 0; i < Screen.AllScreens.Length; i++) - { - if (!Screen.AllScreens[i].Primary) continue; - realPrimaryScreenNumField = i; - break; - } - } - - return (int)realPrimaryScreenNumField; - } - - public bool CloseOnActivity { get; set; } - public MultiScreenModeItem MultiScreenMode { get; set; } - public enum MultiScreenModeItem - { - Span, - Mirror, - Separate - } - - public class BasicScreenInfo - { - public int ScreenNum { get; set; } - public Rectangle Bounds { get; set; } - public bool IsPrimary { get; set; } - } - - // TODO: the URLs handling mostly works, but it is overcomplicted and there is a fundamental issue with ordering: - // specifically, if the user has a single-screen view of what is actually stored as multiple screens underneath, - // and they order a later-screen item before an earlier screen item, those items will still wind up in screen- - // order whe reading back for single-screen view. - // options: 1) retro-fit more ordering stuff onto screen URLS, 2) make the URLS list just one list again, and - // add another list that specifies which screen each URL is for. (i.e. rewrite URL list handling completely). - // 2. is actually the better option. - private List> urlsByScreen; - public List GetUrlsByScreen(int screenNum) - { - int startAtScreenNum = MultiScreenMode == MultiScreenModeItem.Mirror ? 0 : screenNum; - // special treatment for URLs for the 'last' effective screen - // this can happen either due to actual screen removal as noted in the LoadUrlsAllScreens() method, - // OR because we are in Span mode, making just one effective screen, - // OR we want to treat multiple screens as one (mirror mode). - if (MultiScreenMode == MultiScreenModeItem.Mirror || EffectiveScreensList.Count < urlsByScreen.Count && startAtScreenNum == EffectiveScreensList.Count-1) - { - // for the GET operation, the last effective screen has the URLS - // for additional screens in prefs appended to it's list. - List urlsList = urlsByScreen[startAtScreenNum].ToList(); - var urlsForRestOfScreens = urlsByScreen.GetRange(startAtScreenNum + 1, urlsByScreen.Count - startAtScreenNum - 1); - foreach (var additionalScreenUrls in urlsForRestOfScreens) - { - urlsList.AddRange(additionalScreenUrls); - } - return urlsList; - } - else - { - return urlsByScreen[startAtScreenNum].ToList(); - } - } - public void SetUrlsForScreen(int screenNum, List providedUrlsList) - { - int startAtScreenNum = MultiScreenMode == MultiScreenModeItem.Mirror ? 0 : screenNum; - // special treatment for URLs for the 'last' effective screen - // this can happen either due to physical screen changes as noted in the LoadUrlsAllScreens() method, - // OR because we are in Span or Mirror mode, making just one effective screen. - if (MultiScreenMode == MultiScreenModeItem.Mirror || EffectiveScreensList.Count < urlsByScreen.Count && startAtScreenNum == EffectiveScreensList.Count - 1) - { - // For the SET operation, we want any URLS that came to the last effective screen - // from later screens in prefs to go back where they came from rather than directly - // to the screen number specified. - // at the same time, we want any NEW urls to go to either the screenNum provided, - // or to the primary screen if that is one of the screens in the ones we are considering. - - // we only care about Url lists from this screen up. - // This screen, whatever it is, is always RELATIVE screen 0. - var relativeScreenUrlsList = - urlsByScreen.GetRange(startAtScreenNum, urlsByScreen.Count - startAtScreenNum); - // make a deep copy that we can manipulate independantly of the actual list. - var originalsUnaccountedFor = relativeScreenUrlsList.Select(t => new List(t)).ToList(); - // then delete all that actual entries in the actual set to fill in below. - foreach (var urlsList in relativeScreenUrlsList) - { - urlsList.RemoveRange(0, urlsList.Count); - } - - int defaultRelativeScreenNumForNewUrls = Math.Max(0, RealPrimaryScreenNum()-startAtScreenNum); - - foreach (var url in providedUrlsList) - { - // find where it exists in the unaccounted for lists - int relativeScreenNumForThisUrl; - for (relativeScreenNumForThisUrl = 0; relativeScreenNumForThisUrl < originalsUnaccountedFor.Count; relativeScreenNumForThisUrl++) - { - if (originalsUnaccountedFor[relativeScreenNumForThisUrl].Contains(url)) - { - // remove from further consideration, and use this relative screen number - originalsUnaccountedFor[relativeScreenNumForThisUrl].Remove(url); - break; - } - } - if (relativeScreenNumForThisUrl == originalsUnaccountedFor.Count) - { - // not found - use default - relativeScreenNumForThisUrl = defaultRelativeScreenNumForNewUrls; - } - - relativeScreenUrlsList[relativeScreenNumForThisUrl].Add(url); - } - } - else - // normal case for normal screen nums is MUCH simpler: - { - urlsByScreen[screenNum] = providedUrlsList; - } - } - - private List rotationIntervalsByScreen; - public int GetRotationIntervalByScreen(int screenNum) - { - return rotationIntervalsByScreen[TranslateScreenNumToScreenPrefNum(screenNum)]; - } - public void SetRotationIntervalForScreen(int screenNum, int value) - { - rotationIntervalsByScreen[TranslateScreenNumToScreenPrefNum(screenNum)] = value; - } - - private List randomizeFlagByScreen; - public bool GetRandomizeFlagByScreen(int screenNum) - { - return randomizeFlagByScreen[TranslateScreenNumToScreenPrefNum(screenNum)]; - } - public void SetRandomizeFlagForScreen(int screenNum, bool randomizeSetting) - { - randomizeFlagByScreen[TranslateScreenNumToScreenPrefNum(screenNum)] = randomizeSetting; - } - - private int TranslateScreenNumToScreenPrefNum(int screenNum) - { - // if the screen they're asking for is an effective primary, - // then the actual set of prefs to use is the real primary screen's set, - // regardless of the actual number they asked for. - return EffectiveScreensList[screenNum].IsPrimary ? RealPrimaryScreenNum() : screenNum; - } - - public void SavePreferences() - { - reg.SetValue(MULTISCREEN_PREF, MultiScreenMode); - reg.SetValue(CLOSE_ON_ACTIVITY_PREF, CloseOnActivity); - SaveUrlsAllScreens(); - SavePrefAllScreens(INTERVAL_PREF, rotationIntervalsByScreen); - SavePrefAllScreens(RANDOMIZE_PREF, randomizeFlagByScreen); - reg.Close(); - } - - private void LoadPreferences() - { - MultiScreenMode = (MultiScreenModeItem)Enum.Parse(typeof(MultiScreenModeItem), (string)reg.GetValue(MULTISCREEN_PREF, MULTISCREEN_PREF_DEFAULT)); - CloseOnActivity = bool.Parse((string)reg.GetValue(CLOSE_ON_ACTIVITY_PREF, CLOSE_ON_ACTIVITY_PREF_DEFAULT)); - urlsByScreen = LoadUrlsAllScreens(); - rotationIntervalsByScreen = LoadPrefAllScreens(INTERVAL_PREF, INTERVAL_PREF_DEFAULT, INTERVAL_PREF_DEFAULT); - randomizeFlagByScreen = LoadPrefAllScreens(RANDOMIZE_PREF, RANDOMIZE_PREF_DEFAULT, RANDOMIZE_PREF_DEFAULT); - } - - private List> LoadUrlsAllScreens() - { - List strings = LoadPrefAllScreens(URL_PREF, URL_PREF_PRIMARYSCREEN_DEFAULT, URL_PREF_NONPRIMARYSCREEN_DEFAULT); - var allUrls = strings.Select(stringValue => string.IsNullOrWhiteSpace(stringValue) - ? new List() - : stringValue.Split(' ').ToList()) - .ToList(); - - // special case for URLs, so that we don't lose any if/when the user physically removes a screen - // (this happens frequently eg if you remote desktop to your machine, or you undock your laptop) - // if there are more screens stored in the prefs than there are actual screens, append any extras. - // actually dealing appropriately with the extra lists of URLs is handled by the GetUrlsByScreen() - // and SetUrlsByScreen() methods. - const string TempDefaultValue = "DEFAULT VALUE"; - int i = allUrls.Count; - string nextScreenUrlsPrefResult = LoadPrefByScreen(i, URL_PREF, TempDefaultValue, TempDefaultValue); - while (nextScreenUrlsPrefResult != TempDefaultValue) - { - allUrls.Add( - string.IsNullOrWhiteSpace(nextScreenUrlsPrefResult) - ? new List() - : nextScreenUrlsPrefResult.Split(' ').ToList()); - nextScreenUrlsPrefResult = LoadPrefByScreen(++i, URL_PREF, TempDefaultValue, TempDefaultValue); - } - - return allUrls; - } - - private List LoadPrefAllScreens(string prefBaseName, string primaryScreenPrefDefaultValue, string nonPrimaryScreenPrefDefaultValue) - { - List myList = new List(); - for (int i = 0; i < Screen.AllScreens.Length; i++) - { - myList.Add(LoadPrefByScreen(i, prefBaseName, primaryScreenPrefDefaultValue, nonPrimaryScreenPrefDefaultValue)); - } - return myList; - } - - private void SaveUrlsAllScreens() - { - SavePrefAllScreens(URL_PREF, urlsByScreen.Select(urlList => String.Join(" ", urlList)).ToList()); - } - - private void SavePrefAllScreens(string preferenceName, List prefsList) - { - for (int i = 0; i < prefsList.Count(); i++) - { - reg.SetValue(ScreenSpecificPrefName(preferenceName, i), prefsList[i]); - } - } - - private T LoadPrefByScreen(int screenNum, string prefBaseName, string primaryScreenPrefDefaultValue, string nonPrimaryScreenPrefDefaultValue) - { - string screenSpecificPrefEntryName = ScreenSpecificPrefName(prefBaseName, screenNum); - object regValue = reg.GetValue(screenSpecificPrefEntryName); - if (regValue == null) - { - // no screen-specific entry exists. - // for backward compatibility, if the current tab is only one, or else for the primary screen only, - // look for the non-screen-specific pref setting, and if found, move it from there. - // This is a one-off preferences upgrade. - - if (Screen.AllScreens.Length == 1 || (screenNum < Screen.AllScreens.Length && Screen.AllScreens[screenNum].Primary)) - { - if (reg.GetValueNames().Contains(prefBaseName)) - { - regValue = reg.GetValue(prefBaseName); - reg.DeleteValue(prefBaseName); - reg.SetValue(screenSpecificPrefEntryName, (T)Convert.ChangeType(regValue, typeof(T))); - } - else - { - regValue = (T)Convert.ChangeType(primaryScreenPrefDefaultValue, typeof(T)); - } - } - else - { - regValue = (T)Convert.ChangeType(nonPrimaryScreenPrefDefaultValue, typeof(T)); - } - } - - return (T)Convert.ChangeType(regValue, typeof(T)); - } - - private static string ScreenSpecificPrefName(string prefBaseName, int screenNum) - { - return string.Format(SCREEN_SPECIFIC_PREF_NAME_FORMATSTRING, prefBaseName, screenNum); - } - - private static Rectangle FindEnclosingRect(List rectangles) - { - return Rectangle.FromLTRB( - rectangles.Min(r => r.Left), - rectangles.Min(r => r.Top), - rectangles.Max(r => r.Right), - rectangles.Max(r => r.Bottom)); - } - } -} \ No newline at end of file diff --git a/PrefsByScreenUserControl.Designer.cs b/PrefsByScreenUserControl.Designer.cs index d58b32e..f5f6a63 100644 --- a/PrefsByScreenUserControl.Designer.cs +++ b/PrefsByScreenUserControl.Designer.cs @@ -1,11 +1,11 @@ -namespace Web_Page_Screensaver +namespace WebPageScreensaver { - partial class PrefsByScreenUserControl + internal partial class PrefsByScreenUserControl { /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private System.ComponentModel.IContainer _components = null; /// /// Clean up any resources being used. @@ -13,15 +13,13 @@ partial class PrefsByScreenUserControl /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { - if (disposing && (components != null)) + if (disposing && _components != null) { - components.Dispose(); + _components.Dispose(); } base.Dispose(disposing); } - #region Component Designer generated code - /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. @@ -29,159 +27,239 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - this.nudRotationInterval = new System.Windows.Forms.NumericUpDown(); - this.label3 = new System.Windows.Forms.Label(); - this.cbRandomize = new System.Windows.Forms.CheckBox(); - this.lvUrls = new System.Windows.Forms.ListView(); - this.addUrlButton = new System.Windows.Forms.Button(); - this.upButton = new System.Windows.Forms.Button(); - this.urlButtonsTooltip = new System.Windows.Forms.ToolTip(this.components); - this.downButton = new System.Windows.Forms.Button(); - this.deleteButton = new System.Windows.Forms.Button(); - ((System.ComponentModel.ISupportInitialize)(this.nudRotationInterval)).BeginInit(); + this._numericUpDownRotationInterval = new System.Windows.Forms.NumericUpDown(); + this._labelSecondsToDisplay = new System.Windows.Forms.Label(); + this._checkBoxShuffle = new System.Windows.Forms.CheckBox(); + this._listViewURLs = new System.Windows.Forms.ListView(); + this._buttonAddURL = new System.Windows.Forms.Button(); + this._buttonUp = new System.Windows.Forms.Button(); + this._toolTipURLButtons = new System.Windows.Forms.ToolTip(this.components); + this._buttonDeleteURL = new System.Windows.Forms.Button(); + this._buttonDown = new System.Windows.Forms.Button(); + this._tableLayoutPanelMain = new System.Windows.Forms.TableLayoutPanel(); + this._tableLayoutPanelMainTop = new System.Windows.Forms.TableLayoutPanel(); + this._tableLayoutPanelMainBottom = new System.Windows.Forms.TableLayoutPanel(); + ((System.ComponentModel.ISupportInitialize)(this._numericUpDownRotationInterval)).BeginInit(); + this._tableLayoutPanelMain.SuspendLayout(); + this._tableLayoutPanelMainTop.SuspendLayout(); + this._tableLayoutPanelMainBottom.SuspendLayout(); this.SuspendLayout(); // - // nudRotationInterval + // _numericUpDownRotationInterval // - this.nudRotationInterval.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.nudRotationInterval.Location = new System.Drawing.Point(10, 275); - this.nudRotationInterval.Margin = new System.Windows.Forms.Padding(4); - this.nudRotationInterval.Maximum = new decimal(new int[] { + this._numericUpDownRotationInterval.Anchor = System.Windows.Forms.AnchorStyles.Right; + this._numericUpDownRotationInterval.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._numericUpDownRotationInterval.Location = new System.Drawing.Point(98, 6); + this._numericUpDownRotationInterval.Margin = new System.Windows.Forms.Padding(6); + this._numericUpDownRotationInterval.Maximum = new decimal(new int[] { 999, 0, 0, 0}); - this.nudRotationInterval.Name = "nudRotationInterval"; - this.nudRotationInterval.Size = new System.Drawing.Size(53, 22); - this.nudRotationInterval.TabIndex = 6; - this.nudRotationInterval.Value = new decimal(new int[] { + this._numericUpDownRotationInterval.Name = "_numericUpDownRotationInterval"; + this._numericUpDownRotationInterval.Size = new System.Drawing.Size(50, 23); + this._numericUpDownRotationInterval.TabIndex = 12; + this._numericUpDownRotationInterval.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this._numericUpDownRotationInterval.Value = new decimal(new int[] { 30, 0, 0, 0}); // - // label3 - // - this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(71, 277); - this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(188, 17); - this.label3.TabIndex = 7; - this.label3.Text = "Seconds to display each site"; - // - // cbRandomize - // - this.cbRandomize.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.cbRandomize.AutoSize = true; - this.cbRandomize.Location = new System.Drawing.Point(10, 247); - this.cbRandomize.Margin = new System.Windows.Forms.Padding(4); - this.cbRandomize.Name = "cbRandomize"; - this.cbRandomize.Size = new System.Drawing.Size(160, 21); - this.cbRandomize.TabIndex = 5; - this.cbRandomize.Text = "Shuffle display order"; - this.cbRandomize.UseVisualStyleBackColor = true; - // - // lvUrls - // - this.lvUrls.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.lvUrls.HideSelection = false; - this.lvUrls.LabelEdit = true; - this.lvUrls.Location = new System.Drawing.Point(3, 3); - this.lvUrls.Name = "lvUrls"; - this.lvUrls.Size = new System.Drawing.Size(272, 187); - this.lvUrls.TabIndex = 0; - this.lvUrls.UseCompatibleStateImageBehavior = false; - this.lvUrls.View = System.Windows.Forms.View.List; - // - // addUrlButton - // - this.addUrlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.addUrlButton.Location = new System.Drawing.Point(3, 197); - this.addUrlButton.Margin = new System.Windows.Forms.Padding(4); - this.addUrlButton.Name = "addUrlButton"; - this.addUrlButton.Size = new System.Drawing.Size(77, 28); - this.addUrlButton.TabIndex = 11; - this.addUrlButton.Text = "Add"; - this.addUrlButton.UseVisualStyleBackColor = true; - this.addUrlButton.Click += new System.EventHandler(this.addUrlButton_Click); - // - // upButton - // - this.upButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.upButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 6F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.upButton.Location = new System.Drawing.Point(251, 197); - this.upButton.Margin = new System.Windows.Forms.Padding(0); - this.upButton.Name = "upButton"; - this.upButton.Size = new System.Drawing.Size(24, 28); - this.upButton.TabIndex = 3; - this.upButton.Text = "▲"; - this.urlButtonsTooltip.SetToolTip(this.upButton, "Move selected URLs up"); - this.upButton.UseVisualStyleBackColor = true; - this.upButton.Click += new System.EventHandler(this.MoveAllSelectedUrlsUp_Click); - // - // downButton - // - this.downButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.downButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 6F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.downButton.Location = new System.Drawing.Point(251, 225); - this.downButton.Margin = new System.Windows.Forms.Padding(0); - this.downButton.Name = "downButton"; - this.downButton.Size = new System.Drawing.Size(24, 28); - this.downButton.TabIndex = 12; - this.downButton.Text = "▼"; - this.urlButtonsTooltip.SetToolTip(this.downButton, "Move selected URLs down"); - this.downButton.UseVisualStyleBackColor = true; - this.downButton.Click += new System.EventHandler(this.MoveAllSelectedUrlsDown_Click); - // - // deleteButton - // - this.deleteButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom; - this.deleteButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 6F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.deleteButton.ForeColor = System.Drawing.Color.Red; - this.deleteButton.Location = new System.Drawing.Point(146, 197); - this.deleteButton.Margin = new System.Windows.Forms.Padding(0); - this.deleteButton.Name = "deleteButton"; - this.deleteButton.Size = new System.Drawing.Size(24, 28); - this.deleteButton.TabIndex = 13; - this.deleteButton.Text = "X"; - this.urlButtonsTooltip.SetToolTip(this.deleteButton, "DELETE selected URLs"); - this.deleteButton.UseVisualStyleBackColor = true; - this.deleteButton.Click += new System.EventHandler(this.DeleteAllSelectedUrls_Click); + // _labelSecondsToDisplay + // + this._labelSecondsToDisplay.Anchor = System.Windows.Forms.AnchorStyles.Left; + this._labelSecondsToDisplay.AutoSize = true; + this._labelSecondsToDisplay.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._labelSecondsToDisplay.Location = new System.Drawing.Point(160, 10); + this._labelSecondsToDisplay.Margin = new System.Windows.Forms.Padding(6); + this._labelSecondsToDisplay.Name = "_labelSecondsToDisplay"; + this._labelSecondsToDisplay.Size = new System.Drawing.Size(154, 15); + this._labelSecondsToDisplay.Text = "Seconds to display each site"; + // + // _checkBoxShuffle + // + this._checkBoxShuffle.Anchor = System.Windows.Forms.AnchorStyles.Left; + this._checkBoxShuffle.AutoSize = true; + this._checkBoxShuffle.CheckAlign = System.Drawing.ContentAlignment.TopLeft; + this._checkBoxShuffle.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._checkBoxShuffle.Location = new System.Drawing.Point(6, 8); + this._checkBoxShuffle.Margin = new System.Windows.Forms.Padding(6); + this._checkBoxShuffle.Name = "_checkBoxShuffle"; + this._checkBoxShuffle.Size = new System.Drawing.Size(63, 19); + this._checkBoxShuffle.TabIndex = 11; + this._checkBoxShuffle.Text = "Shuffle"; + this._checkBoxShuffle.TextAlign = System.Drawing.ContentAlignment.TopLeft; + this._checkBoxShuffle.UseVisualStyleBackColor = true; + // + // _listViewURLs + // + this._listViewURLs.Dock = System.Windows.Forms.DockStyle.Fill; + this._listViewURLs.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._listViewURLs.FullRowSelect = true; + this._listViewURLs.GridLines = true; + this._listViewURLs.HideSelection = false; + this._listViewURLs.LabelEdit = true; + this._listViewURLs.Location = new System.Drawing.Point(6, 41); + this._listViewURLs.Margin = new System.Windows.Forms.Padding(6); + this._listViewURLs.Name = "_listViewURLs"; + this._listViewURLs.Size = new System.Drawing.Size(308, 78); + this._listViewURLs.TabIndex = 10; + this._listViewURLs.UseCompatibleStateImageBehavior = false; + this._listViewURLs.View = System.Windows.Forms.View.List; + // + // _buttonAddURL + // + this._buttonAddURL.Anchor = System.Windows.Forms.AnchorStyles.Right; + this._buttonAddURL.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._buttonAddURL.Location = new System.Drawing.Point(6, 6); + this._buttonAddURL.Margin = new System.Windows.Forms.Padding(6); + this._buttonAddURL.Name = "_buttonAddURL"; + this._buttonAddURL.Size = new System.Drawing.Size(75, 23); + this._buttonAddURL.TabIndex = 6; + this._buttonAddURL.Text = "Add URL"; + this._buttonAddURL.UseVisualStyleBackColor = true; + this._buttonAddURL.Click += new System.EventHandler(this.ButtonAddURL_Click); + // + // _buttonUp + // + this._buttonUp.Anchor = System.Windows.Forms.AnchorStyles.Right; + this._buttonUp.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._buttonUp.Location = new System.Drawing.Point(256, 6); + this._buttonUp.Margin = new System.Windows.Forms.Padding(6); + this._buttonUp.Name = "_buttonUp"; + this._buttonUp.Size = new System.Drawing.Size(23, 23); + this._buttonUp.TabIndex = 8; + this._buttonUp.Text = "▲"; + this._toolTipURLButtons.SetToolTip(this._buttonUp, "Move selected URLs up"); + this._buttonUp.UseVisualStyleBackColor = true; + this._buttonUp.Click += new System.EventHandler(this.ButtonUp_Click); + // + // _buttonDeleteURL + // + this._buttonDeleteURL.Anchor = System.Windows.Forms.AnchorStyles.Left; + this._buttonDeleteURL.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._buttonDeleteURL.ForeColor = System.Drawing.Color.Black; + this._buttonDeleteURL.Location = new System.Drawing.Point(93, 6); + this._buttonDeleteURL.Margin = new System.Windows.Forms.Padding(6); + this._buttonDeleteURL.Name = "_buttonDeleteURL"; + this._buttonDeleteURL.Size = new System.Drawing.Size(75, 23); + this._buttonDeleteURL.TabIndex = 7; + this._buttonDeleteURL.Text = "Delete URL"; + this._toolTipURLButtons.SetToolTip(this._buttonDeleteURL, "DELETE selected URLs"); + this._buttonDeleteURL.UseVisualStyleBackColor = true; + this._buttonDeleteURL.Click += new System.EventHandler(this.ButtonDeleteURL_Click); + // + // _buttonDown + // + this._buttonDown.Anchor = System.Windows.Forms.AnchorStyles.Left; + this._buttonDown.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this._buttonDown.Location = new System.Drawing.Point(291, 6); + this._buttonDown.Margin = new System.Windows.Forms.Padding(6); + this._buttonDown.Name = "_buttonDown"; + this._buttonDown.Size = new System.Drawing.Size(23, 23); + this._buttonDown.TabIndex = 9; + this._buttonDown.Text = "▼"; + this._toolTipURLButtons.SetToolTip(this._buttonDown, "Move selected URLs down"); + this._buttonDown.UseVisualStyleBackColor = true; + this._buttonDown.Click += new System.EventHandler(this.ButtonDown_Click); + // + // _tableLayoutPanelMain + // + this._tableLayoutPanelMain.AutoSize = true; + this._tableLayoutPanelMain.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._tableLayoutPanelMain.ColumnCount = 1; + this._tableLayoutPanelMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMain.Controls.Add(this._tableLayoutPanelMainTop, 0, 0); + this._tableLayoutPanelMain.Controls.Add(this._listViewURLs, 0, 1); + this._tableLayoutPanelMain.Controls.Add(this._tableLayoutPanelMainBottom, 0, 2); + this._tableLayoutPanelMain.Dock = System.Windows.Forms.DockStyle.Fill; + this._tableLayoutPanelMain.Location = new System.Drawing.Point(0, 0); + this._tableLayoutPanelMain.Margin = new System.Windows.Forms.Padding(0); + this._tableLayoutPanelMain.Name = "_tableLayoutPanelMain"; + this._tableLayoutPanelMain.RowCount = 3; + this._tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F)); + this._tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F)); + this._tableLayoutPanelMain.Size = new System.Drawing.Size(320, 160); + // + // _tableLayoutPanelMainTop + // + this._tableLayoutPanelMainTop.AutoSize = true; + this._tableLayoutPanelMainTop.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._tableLayoutPanelMainTop.ColumnCount = 4; + this._tableLayoutPanelMainTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 87F)); + this._tableLayoutPanelMainTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMainTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 35F)); + this._tableLayoutPanelMainTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 35F)); + this._tableLayoutPanelMainTop.Controls.Add(this._buttonAddURL, 0, 0); + this._tableLayoutPanelMainTop.Controls.Add(this._buttonDown, 3, 0); + this._tableLayoutPanelMainTop.Controls.Add(this._buttonUp, 2, 0); + this._tableLayoutPanelMainTop.Controls.Add(this._buttonDeleteURL, 1, 0); + this._tableLayoutPanelMainTop.Dock = System.Windows.Forms.DockStyle.Fill; + this._tableLayoutPanelMainTop.Location = new System.Drawing.Point(0, 0); + this._tableLayoutPanelMainTop.Margin = new System.Windows.Forms.Padding(0); + this._tableLayoutPanelMainTop.Name = "_tableLayoutPanelMainTop"; + this._tableLayoutPanelMainTop.RowCount = 1; + this._tableLayoutPanelMainTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMainTop.Size = new System.Drawing.Size(320, 35); + // + // _tableLayoutPanelMainBottom + // + this._tableLayoutPanelMainBottom.AutoSize = true; + this._tableLayoutPanelMainBottom.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this._tableLayoutPanelMainBottom.ColumnCount = 3; + this._tableLayoutPanelMainBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMainBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanelMainBottom.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this._tableLayoutPanelMainBottom.Controls.Add(this._checkBoxShuffle, 0, 0); + this._tableLayoutPanelMainBottom.Controls.Add(this._labelSecondsToDisplay, 2, 0); + this._tableLayoutPanelMainBottom.Controls.Add(this._numericUpDownRotationInterval, 1, 0); + this._tableLayoutPanelMainBottom.Dock = System.Windows.Forms.DockStyle.Fill; + this._tableLayoutPanelMainBottom.Location = new System.Drawing.Point(0, 125); + this._tableLayoutPanelMainBottom.Margin = new System.Windows.Forms.Padding(0); + this._tableLayoutPanelMainBottom.Name = "_tableLayoutPanelMainBottom"; + this._tableLayoutPanelMainBottom.RowCount = 1; + this._tableLayoutPanelMainBottom.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this._tableLayoutPanelMainBottom.Size = new System.Drawing.Size(320, 35); // // PrefsByScreenUserControl // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSize = true; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.BackColor = System.Drawing.Color.White; - this.Controls.Add(this.deleteButton); - this.Controls.Add(this.downButton); - this.Controls.Add(this.upButton); - this.Controls.Add(this.nudRotationInterval); - this.Controls.Add(this.label3); - this.Controls.Add(this.cbRandomize); - this.Controls.Add(this.lvUrls); - this.Controls.Add(this.addUrlButton); + this.Controls.Add(this._tableLayoutPanelMain); + this.Margin = new System.Windows.Forms.Padding(0); + this.MinimumSize = new System.Drawing.Size(320, 160); this.Name = "PrefsByScreenUserControl"; - this.Size = new System.Drawing.Size(279, 309); - ((System.ComponentModel.ISupportInitialize)(this.nudRotationInterval)).EndInit(); + this.Size = new System.Drawing.Size(320, 160); + ((System.ComponentModel.ISupportInitialize)(this._numericUpDownRotationInterval)).EndInit(); + this._tableLayoutPanelMain.ResumeLayout(false); + this._tableLayoutPanelMain.PerformLayout(); + this._tableLayoutPanelMainTop.ResumeLayout(false); + this._tableLayoutPanelMainBottom.ResumeLayout(false); + this._tableLayoutPanelMainBottom.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } - #endregion - public System.Windows.Forms.NumericUpDown nudRotationInterval; - private System.Windows.Forms.Label label3; - public System.Windows.Forms.CheckBox cbRandomize; - public System.Windows.Forms.ListView lvUrls; - private System.Windows.Forms.ToolTip urlButtonsTooltip; - private System.Windows.Forms.Button addUrlButton; - private System.Windows.Forms.Button upButton; - private System.Windows.Forms.Button downButton; - private System.Windows.Forms.Button deleteButton; + private System.Windows.Forms.TableLayoutPanel _tableLayoutPanelMain; + + private System.Windows.Forms.TableLayoutPanel _tableLayoutPanelMainTop; + private System.Windows.Forms.Button _buttonAddURL; + private System.Windows.Forms.Button _buttonDeleteURL; + private System.Windows.Forms.Button _buttonUp; + + public System.Windows.Forms.ListView _listViewURLs; + + private System.Windows.Forms.TableLayoutPanel _tableLayoutPanelMainBottom; + public System.Windows.Forms.CheckBox _checkBoxShuffle; + public System.Windows.Forms.NumericUpDown _numericUpDownRotationInterval; + private System.Windows.Forms.Label _labelSecondsToDisplay; + + private System.Windows.Forms.ToolTip _toolTipURLButtons; + private System.ComponentModel.IContainer components; + private System.Windows.Forms.Button _buttonDown; } } diff --git a/PrefsByScreenUserControl.cs b/PrefsByScreenUserControl.cs index ca4e4d8..fa289dd 100644 --- a/PrefsByScreenUserControl.cs +++ b/PrefsByScreenUserControl.cs @@ -1,37 +1,43 @@ using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Data; using System.Linq; -using System.Text; using System.Windows.Forms; -namespace Web_Page_Screensaver +namespace WebPageScreensaver { - using pl.polidea.lab.Web_Page_Screensaver; - - public partial class PrefsByScreenUserControl : UserControl + internal partial class PrefsByScreenUserControl : UserControl { public PrefsByScreenUserControl() { InitializeComponent(); } - private void MoveAllSelectedUrlsDown_Click(object sender, EventArgs e) + /// + /// Saves the selected preferences for a specific screen. + /// This method must be called by the general Save method of the Preferences window, and must pass each available screen number. + /// + /// The specific screen number for which these preferences must be saved. + public void Save(int screenNumber) + { + ScreenInformation currentScreen = Preferences.Screens[screenNumber]; + currentScreen.URLs = (from ListViewItem item in _listViewURLs.Items.Cast() select item.Text); + currentScreen.RotationInterval = (int)_numericUpDownRotationInterval.Value; + currentScreen.Shuffle = _checkBoxShuffle.Checked; + } + + private void ButtonDown_Click(object sender, EventArgs e) { // TODO: make button grey out when none selected OR when all selected ones are in a bunch at the bottom. bool gapFound = false; // scan from the bottom up, but don't start moving selected items down until // we find an unselected gap to move items(s) down in to. - for (int i = lvUrls.Items.Count - 1; i >= 0; i--) + for (int i = _listViewURLs.Items.Count - 1; i >= 0; i--) { - if (lvUrls.Items[i].Selected) + if (_listViewURLs.Items[i].Selected) { if (gapFound) { - Swap(lvUrls.Items, i, i + 1); + Swap(_listViewURLs.Items, i, i + 1); } } else @@ -43,23 +49,23 @@ private void MoveAllSelectedUrlsDown_Click(object sender, EventArgs e) // 'select'ing the list makes sure the selections of items within it are being displayed. // Otherwise the button becomes the 'selected' control and the selections within the list // are invisible or hard to see. - lvUrls.Select(); + _listViewURLs.Select(); } - private void MoveAllSelectedUrlsUp_Click(object sender, EventArgs e) + private void ButtonUp_Click(object sender, EventArgs e) { // TODO: make button grey out when none selected OR when all selected ones are in a bunch at the top. bool gapFound = false; // scan through for all selected, but don't start moving selected items up until // we find an unselected gap to move items(s) up in to. - for (int i = 0; i < lvUrls.Items.Count; i++) + for (int i = 0; i < _listViewURLs.Items.Count; i++) { - if (lvUrls.Items[i].Selected) + if (_listViewURLs.Items[i].Selected) { if (gapFound) { - Swap(lvUrls.Items, i, i - 1); + Swap(_listViewURLs.Items, i, i - 1); } } else @@ -71,26 +77,26 @@ private void MoveAllSelectedUrlsUp_Click(object sender, EventArgs e) // 'select'ing the list makes sure the selections of items within it are being displayed. // Otherwise the button becomes the 'selected' control and the selections within the list // are invisible or hard to see. - lvUrls.Select(); + _listViewURLs.Select(); } - private void DeleteAllSelectedUrls_Click(object sender, EventArgs e) + private void ButtonDeleteURL_Click(object sender, EventArgs e) { // TODO: undo capability? // TODO: make button grey out when no selection. // work from the bottom up, deleting any we find - for (int i = lvUrls.Items.Count - 1; i >= 0; i--) + for (int i = _listViewURLs.Items.Count - 1; i >= 0; i--) { - if (lvUrls.Items[i].Selected) + if (_listViewURLs.Items[i].Selected) { - lvUrls.Items[i].Remove(); + _listViewURLs.Items[i].Remove(); } } } - private void addUrlButton_Click(object sender, EventArgs e) + private void ButtonAddURL_Click(object sender, EventArgs e) { - ListViewItem item = lvUrls.Items.Add(String.Empty); + ListViewItem item = _listViewURLs.Items.Add(string.Empty); item.BeginEdit(); } diff --git a/PrefsByScreenUserControl.resx b/PrefsByScreenUserControl.resx deleted file mode 100644 index 42c4e49..0000000 --- a/PrefsByScreenUserControl.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - \ No newline at end of file diff --git a/Program.cs b/Program.cs index 577a025..1157d9a 100644 --- a/Program.cs +++ b/Program.cs @@ -1,71 +1,82 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Windows.Forms; -using Microsoft.Win32; -using System.IO; -namespace pl.polidea.lab.Web_Page_Screensaver +namespace WebPageScreensaver { - using System.Collections.Generic; - using System.Drawing; - static class Program { - public static readonly string KEY = "Software\\Web-Page-Screensaver"; - + /// + /// The main entry point for the application. + /// [STAThread] static void Main(string[] args) { - // Set version of embedded browser (http://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version) - var exeName = Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); - Registry.SetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", exeName, 0x2AF8, RegistryValueKind.DWord); + if (Process.GetCurrentProcess().MainModule is not ProcessModule) + { + throw new NullReferenceException("Current process main module is null."); + } + Application.SetHighDpiMode(HighDpiMode.PerMonitorV2); // Helps respect the specified window sizes Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); + Application.SetCompatibleTextRenderingDefault(true); // Prevents seeing tiny unexpected fonts - if (args.Length > 0 && args[0].ToLower().Contains("/p")) - return; + // Argument verification: + // - The arguments /C, /P and /S are required by Windows Control Panel. + // - More than 1 argument, or passing the wrong argument, will exit the program - if (args.Length > 0 && args[0].ToLower().Contains("/c")) + // Passing no arguments is interpreted as using "/C" + switch (args.Length) { - Application.Run(new PreferencesForm()); - } - else - { - var formsList = new List(); - var screens = (new PreferencesManager()).EffectiveScreensList; - foreach (var screen in screens) - { - var screensaverForm = new ScreensaverForm(screen.ScreenNum) - { - Location = new Point(screen.Bounds.Left, screen.Bounds.Top), - Size = new Size(screen.Bounds.Width, screen.Bounds.Height) - }; + case 0: + ShowPreferences(); + break; - FormStartPosition x = screensaverForm.StartPosition; - - formsList.Add(screensaverForm); - } + case 1: + switch (args[0].ToUpperInvariant()) + { + case "/C": // Configure + ShowPreferences(); + break; + case "/P": // Preview + case "/S": // Show + ShowScreenSaver(); + break; + default: + Console.WriteLine($"Unrecognized argument: {args[0]}"); + break; + } + break; - Application.Run(new MultiFormContext(formsList)); + default: + Console.WriteLine("Unexpected number of arguments."); + break; } } - } - public class MultiFormContext : ApplicationContext - { - public MultiFormContext(List forms) + /// + /// Show the screensaver preferences window. + /// + private static void ShowPreferences() { - foreach (var form in forms) - { - form.FormClosed += (s, args) => - { - //When we have closed any form, - //end the program. - ExitThread(); - }; + Application.Run(new PreferencesForm()); + } - form.Show(); + /// + /// Shows the screensaver form in all the screens. + /// + private static void ShowScreenSaver() + { + var forms = new List(); + + foreach ((int _, ScreenInformation info) in Preferences.Screens) + { + var form = new ScreensaverForm(info); + forms.Add(form); } + + Application.Run(new MultiFormContext(forms)); } } } diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs deleted file mode 100644 index 702d1e3..0000000 --- a/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Web-Page-Screensaver")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Web-Page-Screensaver")] -[assembly: AssemblyCopyright("Copyright © 2010")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("07b0594f-48cb-454d-bc88-116fe5170e3c")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] diff --git a/Properties/PublishProfiles/PublishX64.pubxml b/Properties/PublishProfiles/PublishX64.pubxml new file mode 100644 index 0000000..bd8b373 --- /dev/null +++ b/Properties/PublishProfiles/PublishX64.pubxml @@ -0,0 +1,19 @@ + + + + + Release + x64 + Publish\Release\x64\ + FileSystem + net5.0 + win-x64 + true + True + True + True + True + + \ No newline at end of file diff --git a/Properties/PublishProfiles/PublishX86.pubxml b/Properties/PublishProfiles/PublishX86.pubxml new file mode 100644 index 0000000..cd39b55 --- /dev/null +++ b/Properties/PublishProfiles/PublishX86.pubxml @@ -0,0 +1,19 @@ + + + + + Release + x86 + Publish\Release\x86\ + FileSystem + net5.0 + win-x86 + true + True + True + True + True + + \ No newline at end of file diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs deleted file mode 100644 index fdca2fd..0000000 --- a/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Web_Page_Screensaver.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Web_Page_Screensaver.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/Properties/Resources.resx b/Properties/Resources.resx deleted file mode 100644 index ffecec8..0000000 --- a/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs deleted file mode 100644 index 3455aec..0000000 --- a/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Web_Page_Screensaver.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/Properties/Settings.settings b/Properties/Settings.settings deleted file mode 100644 index abf36c5..0000000 --- a/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..0a634ee --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WebPageScreensaver": { + "commandName": "Project", + "commandLineArgs": "" + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index b784a8b..e3e71b5 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,69 @@ -# web-page-screensaver +# Web Page Screensaver -Display a web page as your screensaver +Display webpages as your screensaver. + +Inspired by its predecesor [cwc/web-page-screensaver](https://github.com/cwc/web-page-screensaver) (_Achived_). + +## Binaries + +Version|32-bit|64-bit +---|---|--- +| 2.0.2-Alpha | Download | Download | + _Due to 10MB size limit by GitHub (the generated files are ~130MB), need to find an alternative way to publish these._ + +_Workaround: Follow the [debugging instructions](#Debugging) and generate the files yourself._ + + +## Installation instructions + +* Install the [dependencies](#Dependencies). +* Download The *.scr for your architecture. +* Right click the *.scr file. You have three options to choose from: + * Select `Test` if you want to preview it in full screen. Note: Press ESC to exit the screensaver. + * Select `Configure` to modify the screensaver settings. You should see this Window: + + ![Screenshot](screenshot.png) + + * Select `Install` if you want it to be added to your list of Windows screensavers. The Windows `Screen Saver Settings` window will pop up with this screensaver selected. ## Dependencies -[.NET Framework 4.6](https://www.microsoft.com/en-us/download/details.aspx?id=48130) +Whether you are just installing it or building it, you need the following dependencies: + +* .NET 5.0 (>= Preview 8) Desktop Runtime for Windows: https://dotnet.microsoft.com/download/dotnet/5.0 +* Microsoft Edge Insider (Canary): https://www.microsoftedgeinsider.com/en-us/download/ +* Windows 10. + +## Fixes and improvements + +### 2.0.2-Alpha +* TFM is now targeting net5.0-windows (due to WinForms). +* Upgraded Microsoft.Web.WebView2 to 1.0.774.44. + +### 2.0.1-Alpha +* Upgrade to .NET 5.0. +* Use Edge (WebView2) instead of Internet Explorer. + +## Known issues + +### 2.0.1-Alpha + +* The WinForms theme does not look nice in the published single-file binary. It looks fine when debugging or when building normally (not publishing). It may be caused by the trimming process, which removes what it thinks are unnecessary UI dependencies. +* After installing the *.scr, it's not possible to open the Settings window directly from the Windows Screen Saver Settings button. The workaround is to open the settings by directly double clicking on the *.scr file and configuring the screen saver from there. +* Close on mouse movement does not work because Edge is capturing the mouse movement events, preventing the screensaver from detecting them. The workaround is to press the Esc key. +* Publishing does not yet convert the generated *.exe to *.scr. The extension needs to be changed manually. +* Can't host the final *.scr files in GitHub due to the large size. Workaround is to build it yourself. + +## Contributing + +Issues and PRs are welcome. -## Usage (Windows 7 & up) +## Debugging -1. Find Web-Page-Screensaver.scr on your computer, right click it -2. Select "Install" to install, or "Test" to test it out without installing -3. If installing, the Screen Saver Settings dialog will pop up with the correct screen saver selected -4. Use the `Settings...` button in the same dialog to change the web page(s) displayed by the screen saver +* Install the [dependencies](#Dependencies). +* Clone the repo. +* Build with `dotnet build`. +* To debug from Visual Studio, edit the [launchSettings.json](Properties/launch.json) file and set the `"commandLineArgs"` value to: + * `"/p"` if you want to debug the screensaver itself. + * `"/c"` if you want to debug the settings window. +* Generate a single *.exe by publishing the project using the *.pubxml files in the `Properties/PublishProfiles` folder. Then rename the *.exe to *.scr. diff --git a/ScreenInformation.cs b/ScreenInformation.cs new file mode 100644 index 0000000..f77a977 --- /dev/null +++ b/ScreenInformation.cs @@ -0,0 +1,62 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; + +namespace WebPageScreensaver +{ + internal class ScreenInformation + { + private const string URLsName = "URLs"; + private const string RotationIntervalName = "IntervalRotation"; + private const string ShuffleName = "Shuffle"; + + public ScreenInformation(RegistryKey rootKey, int screenNumber, MultiScreenMode multiScreenMode) + { + RootKey = rootKey; + Bounds = multiScreenMode switch + { + MultiScreenMode.Span => FindEnclosingRectangle(), + MultiScreenMode.Mirror or MultiScreenMode.Separate => Screen.AllScreens[screenNumber].Bounds, + _ => throw new IndexOutOfRangeException("Unrecognized MultiScreenMode value.") + }; + } + + public RegistryKey RootKey { get; private set; } + + public Rectangle Bounds { get; set; } + + public IEnumerable URLs + { + get => RootKey + .GetOrCreateValue(URLsName, "https://dotnet.microsoft.com/ https://code.visualstudio.com/" /* default */) + .Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + set => RootKey.SetValue(URLsName, string.Join(' ', value)); + } + + public int RotationInterval + { + get => int.Parse(RootKey.GetOrCreateValue(RotationIntervalName, 10 /* default */)); + set => RootKey.SetValue(RotationIntervalName, value); + } + + public bool Shuffle + { + get => bool.Parse(RootKey.GetOrCreateValue(ShuffleName, true /* default */)); + set => RootKey.SetValue(ShuffleName, value); + } + + private static Rectangle FindEnclosingRectangle() + { + IEnumerable bounds = Screen.AllScreens.Select(r => r.Bounds); + return Rectangle.FromLTRB( + bounds.Min(r => r.Left), + bounds.Min(r => r.Top), + bounds.Max(r => r.Right), + bounds.Max(r => r.Bottom)); + } + } +} diff --git a/ScreensaverForm.Designer.cs b/ScreensaverForm.Designer.cs index bdec2a6..1a907bb 100644 --- a/ScreensaverForm.Designer.cs +++ b/ScreensaverForm.Designer.cs @@ -1,11 +1,11 @@ -namespace pl.polidea.lab.Web_Page_Screensaver +namespace WebPageScreensaver { partial class ScreensaverForm { /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private System.ComponentModel.IContainer _components = null; /// /// Clean up any resources being used. @@ -13,9 +13,9 @@ partial class ScreensaverForm /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { - if (disposing && (components != null)) + if (disposing && (_components != null)) { - components.Dispose(); + _components.Dispose(); } base.Dispose(disposing); } @@ -28,51 +28,30 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.webBrowser = new System.Windows.Forms.WebBrowser(); - this.closeButton = new System.Windows.Forms.Button(); + this._webBrowser = new Microsoft.Web.WebView2.WinForms.WebView2(); this.SuspendLayout(); // - // webBrowser + // _webBrowser // - this.webBrowser.Dock = System.Windows.Forms.DockStyle.Fill; - this.webBrowser.Location = new System.Drawing.Point(0, 0); - this.webBrowser.Margin = new System.Windows.Forms.Padding(4); - this.webBrowser.MinimumSize = new System.Drawing.Size(27, 25); - this.webBrowser.Name = "webBrowser"; - this.webBrowser.ScriptErrorsSuppressed = true; - this.webBrowser.Size = new System.Drawing.Size(379, 322); - this.webBrowser.TabIndex = 0; - // - // closeButton - // - this.closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.closeButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.closeButton.Location = new System.Drawing.Point(323, 15); - this.closeButton.Margin = new System.Windows.Forms.Padding(4); - this.closeButton.Name = "closeButton"; - this.closeButton.Size = new System.Drawing.Size(40, 28); - this.closeButton.TabIndex = 1; - this.closeButton.Text = "X"; - this.closeButton.UseVisualStyleBackColor = true; - this.closeButton.Visible = false; - this.closeButton.Click += new System.EventHandler(this.closeButton_Click); + this._webBrowser.Dock = System.Windows.Forms.DockStyle.Fill; + this._webBrowser.Margin = new System.Windows.Forms.Padding(0); + this._webBrowser.Name = "_webBrowser"; + this._webBrowser.Source = new System.Uri("about:blank", System.UriKind.Absolute); + this._webBrowser.TabIndex = 0; + this._webBrowser.TabStop = false; + this._webBrowser.ZoomFactor = 1D; // // ScreensaverForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.Black; - this.ClientSize = new System.Drawing.Size(379, 322); - this.Controls.Add(this.closeButton); - this.Controls.Add(this.webBrowser); + this.Controls.Add(this._webBrowser); this.ForeColor = System.Drawing.Color.White; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - this.Margin = new System.Windows.Forms.Padding(4); + this.Margin = new System.Windows.Forms.Padding(0); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "ScreensaverForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; - this.Text = "Form1"; this.Load += new System.EventHandler(this.ScreensaverForm_Load); this.ResumeLayout(false); @@ -80,8 +59,6 @@ private void InitializeComponent() #endregion - private System.Windows.Forms.WebBrowser webBrowser; - private System.Windows.Forms.Button closeButton; + private Microsoft.Web.WebView2.WinForms.WebView2 _webBrowser; } } - diff --git a/ScreensaverForm.cs b/ScreensaverForm.cs index 4f63bed..fc89a8d 100644 --- a/ScreensaverForm.cs +++ b/ScreensaverForm.cs @@ -1,193 +1,120 @@ using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Data; using System.Drawing; using System.Linq; -using System.Text; using System.Windows.Forms; -using Microsoft.Win32; -using System.Diagnostics; -namespace pl.polidea.lab.Web_Page_Screensaver +namespace WebPageScreensaver { - public partial class ScreensaverForm : Form + internal partial class ScreensaverForm : Form { - private DateTime StartTime; - private Timer timer; - private int currentSiteIndex = -1; - private GlobalUserEventHandler userEventHandler; - private bool shuffleOrder; - private List urls; + private int _currentURLIndex; - private PreferencesManager prefsManager = new PreferencesManager(); + private readonly Timer _timer; + private readonly bool _closeOnMouseMovement; + private readonly int _rotationInterval; + private readonly bool _shuffle; + private readonly List _urls; + private readonly Size _savedSize; + private readonly Point _savedLocation; - private int screenNum; - - [ThreadStatic] - private static Random random; - - public ScreensaverForm(int? screenNumber = null) + public ScreensaverForm(ScreenInformation screen) { - userEventHandler = new GlobalUserEventHandler(); - userEventHandler.Event += new GlobalUserEventHandler.UserEvent(HandleUserActivity); + _currentURLIndex = 0; - if (screenNumber == null) screenNum = prefsManager.EffectiveScreensList.FindIndex(s => s.IsPrimary); - else screenNum = (int)screenNumber; + _closeOnMouseMovement = Preferences.CloseOnMouseMovement; + _rotationInterval = screen.RotationInterval; + _shuffle = screen.Shuffle; + _urls = screen.URLs.ToList(); - InitializeComponent(); + _savedSize = new Size(screen.Bounds.Width, screen.Bounds.Height); + _savedLocation = new Point(screen.Bounds.Left, screen.Bounds.Top); Cursor.Hide(); + InitializeComponent(); + + // Manually change size and location, since the `InitializeComponent` code tends to get autoreplaced by the Designer + this.SuspendLayout(); + this._webBrowser.Size = _savedSize; + this._webBrowser.Location = _savedLocation; + this.ClientSize = _savedSize; + this.Location = _savedLocation; + this.ResumeLayout(false); + + _timer = new Timer(); } - public List Urls + private async void ScreensaverForm_Load(object sender, EventArgs e) { - get + if (_webBrowser == null) { - if (urls == null) - { - urls = prefsManager.GetUrlsByScreen(screenNum); - } - - return urls; + throw new NullReferenceException("webBrowser should have been initialized by now."); } - } + await _webBrowser.EnsureCoreWebView2Async(); - private void ScreensaverForm_Load(object sender, EventArgs e) - { - if (Urls.Any()) + if (_urls.Any()) { - if (Urls.Count > 1) + if (_shuffle) { - // Shuffle the URLs if necessary - shuffleOrder = prefsManager.GetRandomizeFlagByScreen(screenNum); - if (shuffleOrder) + Random random = new Random(); + int n = _urls.Count; + while (n > 1) { - random = new Random(); - - int n = urls.Count; - while (n > 1) - { - n--; - int k = random.Next(n + 1); - var value = urls[k]; - urls[k] = urls[n]; - urls[n] = value; - } + n--; + int k = random.Next(n + 1); + var value = _urls[k]; + _urls[k] = _urls[n]; + _urls[n] = value; } - - // Set up timer to rotate to the next URL - timer = new Timer(); - timer.Interval = prefsManager.GetRotationIntervalByScreen(screenNum) * 1000; - timer.Tick += (s, ee) => RotateSite(); - timer.Start(); } - // Display the first site in the list - RotateSite(); + _timer.Interval = _rotationInterval * 1000; + _timer.Tick += (s, ee) => RotateSite(); + _timer.Start(); - StartTime = DateTime.Now; + RotateSite(); // First call, second one will be done _rotationInterval seconds later by _timer } else { - webBrowser.Visible = false; + _webBrowser.Visible = false; } } - private void BrowseTo(string url) + private void RotateSite() { - // Disable the user event handler while navigating - Application.RemoveMessageFilter(userEventHandler); - - if (string.IsNullOrWhiteSpace(url)) - { - webBrowser.Visible = false; - } - else + if (_currentURLIndex >= _urls.Count) { - webBrowser.Visible = true; - try - { - Debug.WriteLine($"Navigating: {url}"); - webBrowser.Navigate(url); - } - catch - { - // This can happen if IE pops up a window that isn't closed before the next call to Navigate() - } + _currentURLIndex = 0; } - Application.AddMessageFilter(userEventHandler); + BrowseTo(_urls[_currentURLIndex]); + _currentURLIndex++; } - private void RotateSite() + private void BrowseTo(string url) { - currentSiteIndex++; - - if (currentSiteIndex >= Urls.Count) - { - currentSiteIndex = 0; - } - - var url = Urls[currentSiteIndex]; - - BrowseTo(url); + _webBrowser.Visible = true; + _webBrowser.CoreWebView2.Navigate(url); } - private void HandleUserActivity() + private void WebBrowser_MouseMove(object sender, EventArgs e) { - if (StartTime.AddSeconds(1) > DateTime.Now) return; - - if (prefsManager.CloseOnActivity) + if (_closeOnMouseMovement) { Close(); } - else - { - closeButton.Visible = true; - Cursor.Show(); - } - } - - private void closeButton_Click(object sender, EventArgs e) - { - Close(); } - } - public class GlobalUserEventHandler : IMessageFilter - { - public delegate void UserEvent(); - - private const int WM_MOUSEMOVE = 0x0200; - private const int WM_MBUTTONDBLCLK = 0x209; - private const int WM_KEYDOWN = 0x100; - private const int WM_KEYUP = 0x101; - - // screensavers and especially multi-window apps can get spurrious WM_MOUSEMOVE events - // that don't actually involve any movement (cursor chnages and some mouse driver software - // can generate them, for example) - so we record the actual mouse position and compare against it for actual movement. - private Point? lastMousePos; - - public event UserEvent Event; - - public bool PreFilterMessage(ref Message m) + /// + /// Allows capturing the ESC key to close the form. + /// + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { - if ((m.Msg == WM_MOUSEMOVE) && (this.lastMousePos == null)) - { - this.lastMousePos = Cursor.Position; - } - - if (((m.Msg == WM_MOUSEMOVE) && (Cursor.Position != this.lastMousePos)) - || (m.Msg > WM_MOUSEMOVE && m.Msg <= WM_MBUTTONDBLCLK) || m.Msg == WM_KEYDOWN || m.Msg == WM_KEYUP) + if (keyData == Keys.Escape) { - - if (Event != null) - { - Event(); - } + Close(); + return true; } - // Always allow message to continue to the next filter control - return false; + return base.ProcessCmdKey(ref msg, keyData); } } } \ No newline at end of file diff --git a/ThreeScreensSetUp.reg b/ThreeScreensSetUp.reg deleted file mode 100644 index 0b69bc9..0000000 Binary files a/ThreeScreensSetUp.reg and /dev/null differ diff --git a/Web-Page-Screensaver.csproj b/Web-Page-Screensaver.csproj deleted file mode 100644 index 7fdcffd..0000000 --- a/Web-Page-Screensaver.csproj +++ /dev/null @@ -1,141 +0,0 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F} - WinExe - Properties - Web_Page_Screensaver - Web-Page-Screensaver - v4.0 - 512 - - - - - 3.5 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - - - true - bin\Settings\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - true - bin\Debug-Prefs\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - - - Form - - - PreferencesForm.cs - - - UserControl - - - PrefsByScreenUserControl.cs - - - Form - - - ScreensaverForm.cs - - - - - PreferencesForm.cs - - - PrefsByScreenUserControl.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - Designer - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - if $(ConfigurationName) == Release move $(TargetPath) $(TargetDir)$(TargetName).scr - - - \ No newline at end of file diff --git a/Web-Page-Screensaver.sln b/Web-Page-Screensaver.sln deleted file mode 100644 index 78c42bb..0000000 --- a/Web-Page-Screensaver.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.16 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web-Page-Screensaver", "Web-Page-Screensaver.csproj", "{3E640398-E4D5-4AC8-A200-7AD96E7CC77F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug-Prefs|Any CPU = Debug-Prefs|Any CPU - Release|Any CPU = Release|Any CPU - Settings|Any CPU = Settings|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug-Prefs|Any CPU.ActiveCfg = Debug-Prefs|Any CPU - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug-Prefs|Any CPU.Build.0 = Debug-Prefs|Any CPU - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Release|Any CPU.Build.0 = Release|Any CPU - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Settings|Any CPU.ActiveCfg = Settings|Any CPU - {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Settings|Any CPU.Build.0 = Settings|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/WebPageScreensaver.csproj b/WebPageScreensaver.csproj new file mode 100644 index 0000000..d67e0c0 --- /dev/null +++ b/WebPageScreensaver.csproj @@ -0,0 +1,25 @@ + + + + WinExe + net5.0-windows + true + enable + WebPageScreensaver.Program + WebPageScreensaver + WebPageScreensaver + 2.0.2-Alpha + true + true + x64;x86 + + + + + + + + + + + diff --git a/WebPageScreensaver.sln b/WebPageScreensaver.sln new file mode 100644 index 0000000..992a734 --- /dev/null +++ b/WebPageScreensaver.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28705.295 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebPageScreensaver", "WebPageScreensaver.csproj", "{3E640398-E4D5-4AC8-A200-7AD96E7CC77F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug|x64.ActiveCfg = Debug|x64 + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug|x64.Build.0 = Debug|x64 + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug|x86.ActiveCfg = Debug|x64 + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Debug|x86.Build.0 = Debug|x64 + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Release|x64.ActiveCfg = Release|x64 + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Release|x64.Build.0 = Release|x64 + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Release|x86.ActiveCfg = Release|x86 + {3E640398-E4D5-4AC8-A200-7AD96E7CC77F}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A5437866-76AE-4B0D-AE55-81697D5D1414} + EndGlobalSection +EndGlobal diff --git a/app.config b/app.config deleted file mode 100644 index fcd0c93..0000000 --- a/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..10efc3e Binary files /dev/null and b/screenshot.png differ