diff --git a/src/CodingWithCalvin.BreakpointNotifier/BreakpointNotifierPackage.cs b/src/CodingWithCalvin.BreakpointNotifier/BreakpointNotifierPackage.cs index 0f5b765..7e4778c 100644 --- a/src/CodingWithCalvin.BreakpointNotifier/BreakpointNotifierPackage.cs +++ b/src/CodingWithCalvin.BreakpointNotifier/BreakpointNotifierPackage.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.InteropServices; using System.Threading; +using CodingWithCalvin.BreakpointNotifier.Options; using CodingWithCalvin.Otel4Vsix; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -12,6 +13,7 @@ namespace CodingWithCalvin.BreakpointNotifier [InstalledProductRegistration(Vsix.Name, Vsix.Description, Vsix.Version)] [Guid("136f3004-4048-4dd9-bd6d-7ff910b2c900")] [ProvideAutoLoad(UIContextGuids80.SolutionExists, PackageAutoLoadFlags.BackgroundLoad)] + [ProvideOptionPage(typeof(GeneralOptions), "Breakpoint Notifier", "General", 0, 0, true)] public sealed class BreakpointNotifierPackage : AsyncPackage { protected override async Task InitializeAsync( @@ -35,7 +37,7 @@ IProgress progress builder.Initialize(); - DebuggerEvents.Initialize(); + DebuggerEvents.Initialize(this); } protected override void Dispose(bool disposing) diff --git a/src/CodingWithCalvin.BreakpointNotifier/CodingWithCalvin.BreakpointNotifier.csproj b/src/CodingWithCalvin.BreakpointNotifier/CodingWithCalvin.BreakpointNotifier.csproj index 50645ab..f9409d6 100644 --- a/src/CodingWithCalvin.BreakpointNotifier/CodingWithCalvin.BreakpointNotifier.csproj +++ b/src/CodingWithCalvin.BreakpointNotifier/CodingWithCalvin.BreakpointNotifier.csproj @@ -10,6 +10,7 @@ + diff --git a/src/CodingWithCalvin.BreakpointNotifier/DebuggerEvents.cs b/src/CodingWithCalvin.BreakpointNotifier/DebuggerEvents.cs index f87578e..1e37321 100644 --- a/src/CodingWithCalvin.BreakpointNotifier/DebuggerEvents.cs +++ b/src/CodingWithCalvin.BreakpointNotifier/DebuggerEvents.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Windows.Forms; +using CodingWithCalvin.BreakpointNotifier.Options; using CodingWithCalvin.Otel4Vsix; using Microsoft; +using Microsoft.Toolkit.Uwp.Notifications; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Debugger.Interop; using Microsoft.VisualStudio.Shell; @@ -12,10 +14,14 @@ namespace CodingWithCalvin.BreakpointNotifier { public sealed class DebuggerEvents : IVsDebuggerEvents, IDebugEventCallback2 { - private DebuggerEvents() + private readonly BreakpointNotifierPackage _package; + + private DebuggerEvents(BreakpointNotifierPackage package) { ThreadHelper.ThrowIfNotOnUIThread(); + _package = package; + var debugger = (IVsDebugger) ServiceProvider.GlobalProvider.GetService(typeof(IVsDebugger)); Assumes.Present(debugger); @@ -23,9 +29,9 @@ private DebuggerEvents() debugger.AdviseDebugEventCallback(this); } - public static DebuggerEvents Initialize() + public static DebuggerEvents Initialize(BreakpointNotifierPackage package) { - return new DebuggerEvents(); + return new DebuggerEvents(package); } public int OnModeChange(DBGMODE dbgmodeNew) @@ -43,6 +49,8 @@ public int Event( ref Guid riidEvent, uint dwAttrib) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (pEvent is IDebugBreakpointEvent2) { using var activity = VsixTelemetry.StartCommandActivity("BreakpointNotifier.BreakpointHit"); @@ -50,7 +58,7 @@ public int Event( try { VsixTelemetry.LogInformation("Breakpoint hit detected"); - MessageBox.Show("Breakpoint Hit!"); + ShowNotification(); } catch (Exception ex) { @@ -64,5 +72,32 @@ public int Event( return VSConstants.S_OK; } + + private void ShowNotification() + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var style = GetNotificationStyle(); + + if (style == NotificationStyle.MessageBox || style == NotificationStyle.Both) + { + MessageBox.Show("Breakpoint Hit!"); + } + + if (style == NotificationStyle.Toast || style == NotificationStyle.Both) + { + new ToastContentBuilder() + .AddText("Breakpoint Hit!") + .Show(); + } + } + + private NotificationStyle GetNotificationStyle() + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var options = _package.GetDialogPage(typeof(GeneralOptions)) as GeneralOptions; + return options?.Style ?? NotificationStyle.Toast; + } } } diff --git a/src/CodingWithCalvin.BreakpointNotifier/Options/GeneralOptions.cs b/src/CodingWithCalvin.BreakpointNotifier/Options/GeneralOptions.cs new file mode 100644 index 0000000..0966d57 --- /dev/null +++ b/src/CodingWithCalvin.BreakpointNotifier/Options/GeneralOptions.cs @@ -0,0 +1,27 @@ +using System.ComponentModel; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.Shell; + +namespace CodingWithCalvin.BreakpointNotifier.Options +{ + public enum NotificationStyle + { + [Description("Message Box")] + MessageBox, + + [Description("Toast Notification")] + Toast, + + [Description("Both")] + Both + } + + [ComVisible(true)] + public class GeneralOptions : DialogPage + { + [Category("Notification")] + [DisplayName("Notification Style")] + [Description("Choose how breakpoint notifications are displayed. Toast notifications are less intrusive and don't steal focus.")] + public NotificationStyle Style { get; set; } = NotificationStyle.Toast; + } +}