/// <summary> /// Setup the Bitmap scaling (for icons) /// </summary> private void SetupBitmapScaleHandler() { ContextMenuDpiHandler = contextMenu.AttachDpiHandler(); var dpiChangeSubscription = DpiHandler.OnDpiChangeInfo.Subscribe(info => { switch (info.DpiChangeEventType) { case DpiChangeEventTypes.Before: // Change the ImageScalingSize before setting the bitmaps var width = DpiHandler.ScaleWithDpi(coreConfiguration.IconSize.Width, info.NewDpi); var size = new Size(width, width); contextMenu.SuspendLayout(); contextMenu.ImageScalingSize = size; contextmenu_quicksettings.Size = new Size(170, width + 8); break; case DpiChangeEventTypes.After: // Redraw the form contextMenu.ResumeLayout(true); contextMenu.Refresh(); notifyIcon.Icon = GreenshotResources.GetGreenshotIcon(); break; } }); var contextMenuResourceScaleHandler = BitmapScaleHandler.WithComponentResourceManager(ContextMenuDpiHandler, GetType(), (bitmap, dpi) => bitmap.ScaleIconForDisplaying(dpi)); contextMenuResourceScaleHandler.AddTarget(contextmenu_capturewindow, "contextmenu_capturewindow.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_capturearea, "contextmenu_capturearea.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_capturelastregion, "contextmenu_capturelastregion.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_capturefullscreen, "contextmenu_capturefullscreen.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_captureclipboard, "contextmenu_captureclipboard.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_openfile, "contextmenu_openfile.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_settings, "contextmenu_settings.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_help, "contextmenu_help.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_donate, "contextmenu_donate.Image"); contextMenuResourceScaleHandler.AddTarget(contextmenu_exit, "contextmenu_exit.Image"); // this is special handling, for the icons which come from the executables var exeBitmapScaleHandler = BitmapScaleHandler.Create <string>(ContextMenuDpiHandler, (path, dpi) => PluginUtils.GetCachedExeIcon(path, 0, dpi >= 120), (bitmap, dpi) => bitmap.ScaleIconForDisplaying(dpi)); exeBitmapScaleHandler.AddTarget(contextmenu_captureie, PluginUtils.GetExePath("iexplore.exe")); // Add cleanup Application.ApplicationExit += (sender, args) => { dpiChangeSubscription.Dispose(); ContextMenuDpiHandler.Dispose(); contextMenuResourceScaleHandler.Dispose(); exeBitmapScaleHandler.Dispose(); }; }
/// <summary> /// This method will create and show the destination picker menu /// </summary> /// <param name="addDynamics">Boolean if the dynamic values also need to be added</param> /// <param name="surface">The surface which can be exported</param> /// <param name="captureDetails">Details for the surface</param> /// <param name="destinations">The list of destinations to show</param> /// <returns></returns> protected ExportInformation ShowPickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable <IDestination> destinations) { var menu = new ContextMenuStrip { Tag = null, TopLevel = true }; var dpiHandler = menu.AttachDpiHandler(); var bitmapScaleHandler = BitmapScaleHandler.Create <IDestination>( dpiHandler, (destination, dpi) => destination.GetDisplayIcon(dpi), (bitmap, d) => bitmap.ScaleIconForDisplaying(d)); dpiHandler.OnDpiChanged.Subscribe(dpi => { var width = DpiHandler.ScaleWithDpi(CoreConfiguration.IconSize.Width, dpi); var size = new Size(width, width); menu.ImageScalingSize = size; }); // Generate an empty ExportInformation object, for when nothing was selected. var exportInformation = new ExportInformation("", GreenshotLanguage.SettingsDestinationPicker); menu.Closing += (source, eventArgs) => { Log.Debug().WriteLine("Close reason: {0}", eventArgs.CloseReason); switch (eventArgs.CloseReason) { case ToolStripDropDownCloseReason.AppFocusChange: if (menu.Tag == null) { // Do not allow the close if the tag is not set, this means the user clicked somewhere else. eventArgs.Cancel = true; } else { Log.Debug().WriteLine("Letting the menu 'close' as the tag is set to '{0}'", menu.Tag); } break; case ToolStripDropDownCloseReason.ItemClicked: case ToolStripDropDownCloseReason.CloseCalled: // The ContextMenuStrip can be "closed" for these reasons. break; case ToolStripDropDownCloseReason.Keyboard: // Dispose as the close is clicked if (!captureDetails.HasDestination("Editor")) { surface.Dispose(); surface = null; } break; default: eventArgs.Cancel = true; break; } }; menu.MouseEnter += (sender, args) => { // in case the menu has been unfocused, focus again so that dropdown menus will still open on mouseenter if (!menu.ContainsFocus) { menu.Focus(); } }; foreach (var destination in destinations) { // Fix foreach loop variable for the delegate var item = destination.GetMenuItem(addDynamics, menu, async(sender, e) => { var toolStripMenuItem = sender as ToolStripMenuItem; var clickedDestination = (IDestination)toolStripMenuItem?.Tag; if (clickedDestination == null) { return; } menu.Tag = clickedDestination.Designation; // Export exportInformation = await clickedDestination.ExportCaptureAsync(true, surface, captureDetails); if (exportInformation != null && exportInformation.ExportMade) { Log.Info().WriteLine("Export to {0} success, closing menu", exportInformation.DestinationDescription); // close menu menu.Close(); menu.Dispose(); // Cleanup surface, only if there is no editor in the destinations and we didn't export to the editor if (!captureDetails.HasDestination("Editor") && !"Editor".Equals(clickedDestination.Designation)) { surface.Dispose(); surface = null; } } else { Log.Info().WriteLine("Export cancelled or failed, showing menu again"); // Make sure a click besides the menu don't close it. menu.Tag = null; // This prevents the problem that the context menu shows in the task-bar ShowMenuAtCursor(menu); } }, bitmapScaleHandler ); if (item != null) { menu.Items.Add(item); } } // Close menu.Items.Add(new ToolStripSeparator()); var closeItem = new ToolStripMenuItem(GreenshotLanguage.Close) { Image = GreenshotResources.GetBitmap("Close.Image") }; closeItem.Click += (sender, args) => { // This menu entry is the close itself, we can dispose the surface menu.Close(); menu.Dispose(); // Only dispose if there is a destination which keeps the capture if (captureDetails.HasDestination("Editor")) { return; } surface.Dispose(); surface = null; }; menu.Items.Add(closeItem); ShowMenuAtCursor(menu); return(exportInformation); }