From 586a0497d60b4b58fb39f22e70b8756ca3bd4d0a Mon Sep 17 00:00:00 2001 From: Chris Kaczor Date: Sat, 22 Apr 2023 09:05:41 -0400 Subject: [PATCH] Remove WinForms references and start on installer --- Application/App.xaml.cs | 3 - Application/FeedCenter.csproj | 290 +++++------- Application/MainWindow/FeedCreation.cs | 4 +- Application/MainWindow/MainWindow.xaml.cs | 12 +- Application/MainWindow/Timer.cs | 43 +- Application/MainWindow/WindowHandler.cs | 20 +- Application/NotificationIcon.cs | 58 +-- Application/SqlSettingsProvider.cs | 116 ----- Bootstrapper/Bootstrapper.wixproj | 45 +- Bootstrapper/Bundle.wxs | 67 ++- Bootstrapper/packages.config | 5 - Setup/Product.wxs | 538 ++++++++++++++-------- Setup/Setup.wixproj | 43 +- Setup/packages.config | 4 - 14 files changed, 572 insertions(+), 676 deletions(-) delete mode 100644 Application/SqlSettingsProvider.cs delete mode 100644 Bootstrapper/packages.config delete mode 100644 Setup/packages.config diff --git a/Application/App.xaml.cs b/Application/App.xaml.cs index ce588b1..ab1115f 100644 --- a/Application/App.xaml.cs +++ b/Application/App.xaml.cs @@ -106,9 +106,6 @@ public partial class App if (!IsDebugBuild) Current.SetStartWithWindows(Settings.Default.StartWithWindows); - // Initialize the window - mainWindow.Initialize(); - // Run the app app.Run(mainWindow); } diff --git a/Application/FeedCenter.csproj b/Application/FeedCenter.csproj index 905fe3f..550a776 100644 --- a/Application/FeedCenter.csproj +++ b/Application/FeedCenter.csproj @@ -1,192 +1,108 @@  - - net70-windows - x86 - WinExe - false - - - - - \\server\d\FeedCenter\ - true - Unc - false - Foreground - 7 - Days - false - false - true - Feed Center - Feed Center - true - Publish.html - false - 215 - 0.1.0.%2a - false - true - true - false - true - true - true - - - - + + net70-windows + WinExe + false + false + true + true + false - - - - - Resources\Application.ico - - - LocalIntranet - - - false - - - Properties\app.manifest - - - bin\Debug\FeedCenter.exe.CodeAnalysisLog.xml - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - false - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - false - true - - - bin\Release\FeedCenter.exe.CodeAnalysisLog.xml - MinimumRecommendedRules.ruleset - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets - ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - - - bin\x64\Debug\ - MinimumRecommendedRules.ruleset - false - false - - - bin\x64\Release\ - MinimumRecommendedRules.ruleset - - - - EntityModelCodeGenerator - Model.Designer.cs - - - - - - - - - False - Microsoft .NET Framework 4.5 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 4.5 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NU1701 - - - - NU1701 - - - - - - - - - - - - - - True - True - Resources.resx - - - True - True - Settings.settings - - - - - PublicResXFileCodeGenerator - Resources.Designer.cs - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - if not exist "$(TargetDir)x86" md "$(TargetDir)x86" - xcopy /s /y "$(PkgMicrosoft_SqlServer_Compact)\NativeBinaries\x86\*.*" "$(TargetDir)x86" - if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64" - xcopy /s /y "$(PkgMicrosoft_SqlServer_Compact)\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" - - + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NU1701 + + + + NU1701 + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + xcopy /s /y /i "$(PkgMicrosoft_SqlServer_Compact)\NativeBinaries\x86\*.*" "$(TargetDir)x86" + xcopy /s /y /i "$(PkgMicrosoft_SqlServer_Compact)\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" + + Resources\Application.ico + \ No newline at end of file diff --git a/Application/MainWindow/FeedCreation.cs b/Application/MainWindow/FeedCreation.cs index ca805c4..18d3407 100644 --- a/Application/MainWindow/FeedCreation.cs +++ b/Application/MainWindow/FeedCreation.cs @@ -86,7 +86,7 @@ public partial class MainWindow _database.SaveChanges(() => _database.Feeds.Add(feed)); // Show a tip - NotificationIcon.ShowBalloonTip(string.Format(Properties.Resources.FeedAddedNotification, feed.Name), System.Windows.Forms.ToolTipIcon.Info); + NotificationIcon.ShowBalloonTip(string.Format(Properties.Resources.FeedAddedNotification, feed.Name), H.NotifyIcon.Core.NotificationIcon.Info); _currentFeed = feed; @@ -104,7 +104,7 @@ public partial class MainWindow var dialogResult = feedForm.Display(feed, this); // Display the new feed form - if (!dialogResult.HasValue || !dialogResult.Value) + if (!dialogResult.HasValue || !dialogResult.Value) return; // Add the feed to the feed table diff --git a/Application/MainWindow/MainWindow.xaml.cs b/Application/MainWindow/MainWindow.xaml.cs index 8140253..00508f3 100644 --- a/Application/MainWindow/MainWindow.xaml.cs +++ b/Application/MainWindow/MainWindow.xaml.cs @@ -34,6 +34,14 @@ public partial class MainWindow : IDisposable GC.SuppressFinalize(this); } + protected override void OnSourceInitialized(EventArgs e) + { + base.OnSourceInitialized(e); + + // Initialize the window + Initialize(); + } + protected override async void OnClosed(EventArgs e) { base.OnClosed(e); @@ -207,9 +215,7 @@ public partial class MainWindow : IDisposable private void InitializeDisplay() { // Get the last category (defaulting to none) - _currentCategory = - _database.Categories.FirstOrDefault(category => - category.Id.ToString() == Settings.Default.LastCategoryID); + _currentCategory = _database.Categories.FirstOrDefault(category => category.Id.ToString() == Settings.Default.LastCategoryID); DisplayCategory(); // Get the current feed list to match the category diff --git a/Application/MainWindow/Timer.cs b/Application/MainWindow/Timer.cs index 02d14c0..b50a277 100644 --- a/Application/MainWindow/Timer.cs +++ b/Application/MainWindow/Timer.cs @@ -1,6 +1,7 @@ using FeedCenter.Properties; using System; -using System.Windows.Forms; +using System.Timers; +using System.Windows.Threading; namespace FeedCenter; @@ -9,11 +10,14 @@ public partial class MainWindow private Timer _mainTimer; private DateTime _lastFeedRead; private DateTime _lastFeedDisplay; + private Dispatcher _dispatcher; private void InitializeTimer() { + _dispatcher = Dispatcher.CurrentDispatcher; + _mainTimer = new Timer { Interval = 1000 }; - _mainTimer.Tick += HandleMainTimerTick; + _mainTimer.Elapsed += HandleMainTimerElapsed; } private void TerminateTimer() @@ -33,26 +37,29 @@ public partial class MainWindow _mainTimer.Stop(); } - private void HandleMainTimerTick(object sender, EventArgs e) + private void HandleMainTimerElapsed(object sender, EventArgs e) { - // If the background worker is busy then don't do anything - if (_feedReadWorker.IsBusy) - return; + _dispatcher.Invoke(() => + { + // If the background worker is busy then don't do anything + if (_feedReadWorker.IsBusy) + return; - // Stop the timer for now - StopTimer(); + // Stop the timer for now + StopTimer(); - // Move to the next feed if the scroll interval has expired and the mouse isn't hovering - if (LinkTextList.IsMouseOver) - _lastFeedDisplay = DateTime.Now; - else if (DateTime.Now - _lastFeedDisplay >= Settings.Default.FeedScrollInterval) - NextFeed(); + // Move to the next feed if the scroll interval has expired and the mouse isn't hovering + if (LinkTextList.IsMouseOver) + _lastFeedDisplay = DateTime.Now; + else if (DateTime.Now - _lastFeedDisplay >= Settings.Default.FeedScrollInterval) + NextFeed(); - // Check to see if we should try to read the feeds - if (DateTime.Now - _lastFeedRead >= Settings.Default.FeedCheckInterval) - ReadFeeds(); + // Check to see if we should try to read the feeds + if (DateTime.Now - _lastFeedRead >= Settings.Default.FeedCheckInterval) + ReadFeeds(); - // Get the timer going again - StartTimer(); + // Get the timer going again + StartTimer(); + }); } } \ No newline at end of file diff --git a/Application/MainWindow/WindowHandler.cs b/Application/MainWindow/WindowHandler.cs index 4087654..ad3d4ae 100644 --- a/Application/MainWindow/WindowHandler.cs +++ b/Application/MainWindow/WindowHandler.cs @@ -112,28 +112,28 @@ public partial class MainWindow { var windowInteropHelper = new WindowInteropHelper(this); - var screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle); + var screen = WpfScreenHelper.Screen.FromHandle(windowInteropHelper.Handle); - var rectangle = new System.Drawing.Rectangle + var rectangle = new Rect { - X = (int) Left, - Y = (int) Top, - Width = (int) Width, - Height = (int) Height + X = Left, + Y = Top, + Width = Width, + Height = Height }; var borderThickness = new Thickness(); - if (rectangle.Right != screen.WorkingArea.Right) + if (!rectangle.Right.Equals(screen.WorkingArea.Right)) borderThickness.Right = 1; - if (rectangle.Left != screen.WorkingArea.Left) + if (!rectangle.Left.Equals(screen.WorkingArea.Left)) borderThickness.Left = 1; - if (rectangle.Top != screen.WorkingArea.Top) + if (!rectangle.Top.Equals(screen.WorkingArea.Top)) borderThickness.Top = 1; - if (rectangle.Bottom != screen.WorkingArea.Bottom) + if (!rectangle.Bottom.Equals(screen.WorkingArea.Bottom)) borderThickness.Bottom = 1; WindowBorder.BorderThickness = borderThickness; diff --git a/Application/NotificationIcon.cs b/Application/NotificationIcon.cs index 32a3c8b..9288bb5 100644 --- a/Application/NotificationIcon.cs +++ b/Application/NotificationIcon.cs @@ -1,49 +1,61 @@ using FeedCenter.Properties; -using System.Windows.Forms; +using H.NotifyIcon; +using System.Windows.Controls; namespace FeedCenter; internal static class NotificationIcon { - private static MainWindow _mainForm; - private static NotifyIcon _notificationIcon; + private static MainWindow _mainWindow; + private static TaskbarIcon _notificationIcon; + private static MenuItem _lockMenuItem; - public static void Initialize(MainWindow mainForm) + public static void Initialize(MainWindow mainWindow) { // Store the main window - _mainForm = mainForm; + _mainWindow = mainWindow; // Create the notification icon - _notificationIcon = new NotifyIcon { Icon = Resources.Application }; - _notificationIcon.DoubleClick += HandleNotificationIconDoubleClick; + _notificationIcon = new TaskbarIcon { Icon = Resources.Application }; + _notificationIcon.TrayMouseDoubleClick += HandleNotificationIconDoubleClick; // Setup the menu - var contextMenuStrip = new ContextMenuStrip(); + var contextMenu = new ContextMenu(); - var toolStripMenuItem = new ToolStripMenuItem(Resources.NotificationIconContextMenuLocked, null, HandleLockWindowClicked) { Checked = Settings.Default.WindowLocked }; - contextMenuStrip.Items.Add(toolStripMenuItem); + _lockMenuItem = new MenuItem() + { + Header = Resources.NotificationIconContextMenuLocked, + IsChecked = Settings.Default.WindowLocked + }; + _lockMenuItem.Click += HandleLockWindowClicked; + contextMenu.Items.Add(_lockMenuItem); - contextMenuStrip.Items.Add(new ToolStripSeparator()); + contextMenu.Items.Add(new Separator()); - contextMenuStrip.Items.Add(Resources.NotificationIconContextMenuExit, null, HandleContextMenuExitClick); + var menuItem = new MenuItem() + { + Header = Resources.NotificationIconContextMenuExit + }; + menuItem.Click += HandleContextMenuExitClick; + contextMenu.Items.Add(menuItem); // Set the menu into the icon - _notificationIcon.ContextMenuStrip = contextMenuStrip; + _notificationIcon.ContextMenu = contextMenu; // Show the icon - _notificationIcon.Visible = true; + _notificationIcon.ForceCreate(false); } private static void HandleNotificationIconDoubleClick(object sender, System.EventArgs e) { // Bring the main form to the front - _mainForm.Activate(); + _mainWindow.Activate(); } private static void HandleContextMenuExitClick(object sender, System.EventArgs e) { // Close the main form - _mainForm.Close(); + _mainWindow.Close(); } private static void HandleLockWindowClicked(object sender, System.EventArgs e) @@ -52,26 +64,20 @@ internal static class NotificationIcon Settings.Default.WindowLocked = !Settings.Default.WindowLocked; // Refresh the menu choice - ((ToolStripMenuItem) sender).Checked = Settings.Default.WindowLocked; + _lockMenuItem.IsChecked = Settings.Default.WindowLocked; } public static void Dispose() { // Get rid of the icon - _notificationIcon.Visible = false; _notificationIcon.Dispose(); _notificationIcon = null; - _mainForm = null; + _mainWindow = null; } - public static void ShowBalloonTip(string text, ToolTipIcon icon) + public static void ShowBalloonTip(string text, H.NotifyIcon.Core.NotificationIcon icon) { - ShowBalloonTip(text, icon, Settings.Default.BalloonTipTimeout); - } - - private static void ShowBalloonTip(string text, ToolTipIcon icon, int timeout) - { - _notificationIcon.ShowBalloonTip(timeout, Resources.ApplicationDisplayName, text, icon); + _notificationIcon.ShowNotification(Resources.ApplicationDisplayName, text, icon); } } \ No newline at end of file diff --git a/Application/SqlSettingsProvider.cs b/Application/SqlSettingsProvider.cs deleted file mode 100644 index 118e90c..0000000 --- a/Application/SqlSettingsProvider.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using System.Configuration; -using System.Windows.Forms; -using System.Collections.Specialized; -using Microsoft.Win32; - -namespace FeedCenter -{ - class RegistrySettingsProvider : SettingsProvider - { - public RegistrySettingsProvider() - { - - } - - public override string ApplicationName - { - get { return Application.ProductName; } - set { } - } - - public override void Initialize(string name, NameValueCollection col) - { - base.Initialize(this.ApplicationName, col); - } - - // SetPropertyValue is invoked when ApplicationSettingsBase.Save is called - // ASB makes sure to pass each provider only the values marked for that provider - - // though in this sample, since the entire settings class was marked with a SettingsProvider - // attribute, all settings in that class map to this provider - public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals) - { - // Iterate through the settings to be stored - // Only IsDirty=true properties should be included in propvals - foreach (SettingsPropertyValue propval in propvals) - { - // NOTE: this provider allows setting to both user- and application-scoped - // settings. The default provider for ApplicationSettingsBase - - // LocalFileSettingsProvider - is read-only for application-scoped setting. This - // is an example of a policy that a provider may need to enforce for implementation, - // security or other reasons. - GetRegKey(propval.Property).SetValue(propval.Name, propval.SerializedValue); - } - } - - public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props) - { - - // Create new collection of values - SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); - - // Iterate through the settings to be retrieved - foreach (SettingsProperty setting in props) - { - SettingsPropertyValue value = new SettingsPropertyValue(setting); - value.IsDirty = false; - value.SerializedValue = GetRegKey(setting).GetValue(setting.Name); - values.Add(value); - } - return values; - } - - // Helper method: fetches correct registry subkey. - // HKLM is used for settings marked as application-scoped. - // HKLU is used for settings marked as user-scoped. - private RegistryKey GetRegKey(SettingsProperty prop) - { - RegistryKey regKey; - - if (IsUserScoped(prop)) - { - regKey = Registry.CurrentUser; - } - else - { - regKey = Registry.LocalMachine; - } - - regKey = regKey.CreateSubKey(GetSubKeyPath()); - return regKey; - - } - - // Helper method: walks the "attribute bag" for a given property - // to determine if it is user-scoped or not. - // Note that this provider does not enforce other rules, such as - // - unknown attributes - // - improper attribute combinations (e.g. both user and app - this implementation - // would say true for user-scoped regardless of existence of app-scoped) - private bool IsUserScoped(SettingsProperty prop) - { - foreach (DictionaryEntry d in prop.Attributes) - { - Attribute a = (Attribute) d.Value; - if (a.GetType() == typeof(UserScopedSettingAttribute)) - return true; - } - return false; - } - - // Builds a key path based on the CompanyName, ProductName, and ProductVersion attributes in - // the AssemblyInfo file (editable directly or within the Project Properties UI) - private string GetSubKeyPath() - { - return "Software\\" + Application.CompanyName + "\\" + Application.ProductName + "\\" + Application.ProductVersion; - } - - - - - - } -} \ No newline at end of file diff --git a/Bootstrapper/Bootstrapper.wixproj b/Bootstrapper/Bootstrapper.wixproj index 1c2d8fc..f9af1d9 100644 --- a/Bootstrapper/Bootstrapper.wixproj +++ b/Bootstrapper/Bootstrapper.wixproj @@ -1,42 +1,16 @@ - - + + - Debug - x86 3.9 - 5e5c13a5-635e-4310-a653-0f9760f46935 - 2.0 FeedCenterSetup Bundle - $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets - $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets OnOutputUpdated - bin\$(Configuration)\ - obj\$(Configuration)\ Debug - - bin\$(Configuration)\ - obj\$(Configuration)\ - - - - - - ..\packages\WixBalExtensionExt.1.0.0.49\lib\WixBalExtensionExt.dll - WixBalExtensionExt - - - ..\packages\WixFileVersionExtension.1.0.0.3\lib\WixFileVersionExtension.dll - WixFileVersionExtension - - - $(WixExtDir)\WixNetFxExtension.dll - WixNetFxExtension - + @@ -56,19 +30,8 @@ INSTALLFOLDER - - - - + - \ No newline at end of file diff --git a/Bootstrapper/Bundle.wxs b/Bootstrapper/Bundle.wxs index f9c970c..5afbc5e 100644 --- a/Bootstrapper/Bundle.wxs +++ b/Bootstrapper/Bundle.wxs @@ -1,31 +1,56 @@ - - + - - - + + + + + Version="$(var.ProductVersion)" + Manufacturer="$(var.CompanyName)" + UpgradeCode="5e5c13a5-635e-4310-a653-0f9760f46935" + Compressed="no"> - - - + + + + - - + + + + + + + + + SourceFile="$(var.Setup.TargetPath)" + Compressed="yes" /> \ No newline at end of file diff --git a/Bootstrapper/packages.config b/Bootstrapper/packages.config deleted file mode 100644 index 75654f0..0000000 --- a/Bootstrapper/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Setup/Product.wxs b/Setup/Product.wxs index ebbc0a9..5520622 100644 --- a/Setup/Product.wxs +++ b/Setup/Product.wxs @@ -1,219 +1,359 @@ - - - - - - - - - + - + + + + - + + - + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + - - - + + + + - - - - - - - - - - - - + + + + + + - - - + + + + - + + + + + + - - - - - - + + + + - - - + + + + + - + + + + + - - - - - - + + + + + - - - + - - - - - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + \ No newline at end of file diff --git a/Setup/Setup.wixproj b/Setup/Setup.wixproj index 3b4c678..88ae3ac 100644 --- a/Setup/Setup.wixproj +++ b/Setup/Setup.wixproj @@ -1,46 +1,19 @@ - - + - Debug - x86 3.9 - dfb3fe30-18ea-4216-8d92-11df9c8d50f1 - 2.0 - Setup - Package - $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets - $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets - bin\$(Configuration)\ - obj\$(Configuration)\ Debug ICE91 - bin\$(Configuration)\ - obj\$(Configuration)\ ICE91 true - - - - - ..\packages\WixFileVersionExtension.1.0.0.3\lib\WixFileVersionExtension.dll - WixFileVersionExtension - - - $(WixExtDir)\WixUtilExtension.dll - WixUtilExtension - - - $(WixExtDir)\WixNetFxExtension.dll - WixNetFxExtension - + @@ -52,16 +25,4 @@ INSTALLFOLDER - - - - - \ No newline at end of file diff --git a/Setup/packages.config b/Setup/packages.config deleted file mode 100644 index 6dadc06..0000000 --- a/Setup/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file