diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..f399b08bb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,78 @@ +# EditorConfig is awesome:http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Don't use tabs for indentation. +[*] +indent_style = space +# (Please don't specify an indent_size here; that has too many unintended consequences.) + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# Xml config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# Dotnet code style settings: +[*.{cs,vb}] +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# Use language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Suggest more modern language features when available +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion + +# CSharp code style settings: +[*.cs] +# Prefer "var" everywhere +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Prefer method-like constructs to have a block body +csharp_style_expression_bodied_methods = false:none +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_operators = false:none + +# Prefer property-like constructs to have an expression-body +csharp_style_expression_bodied_properties = true:none +csharp_style_expression_bodied_indexers = true:none +csharp_style_expression_bodied_accessors = true:none + +# Suggest more modern language features when available +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Newline settings +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..638637e24 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at getgreenshot@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..abf5e0f03 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,18 @@ +The general rule we follow is "use Visual Studio defaults". + +1. We use [Allman style](http://en.wikipedia.org/wiki/Indent_style#Allman_style) braces, where each brace begins on a new line. A single line statement block can go without braces but the block must be properly indented on its own line and it must not be nested in other statement blocks that use braces (See issue [381](https://github.com/dotnet/corefx/issues/381) for examples). +2. We use four spaces of indentation (no tabs). +3. We use `_camelCase` for internal and private fields and use `readonly` where possible. Prefix instance fields with `_`, static fields with `s_` and thread static fields with `t_`. When used on static fields, `readonly` should come after `static` (e.g. `static readonly` not `readonly static`). +4. We avoid `this.` unless absolutely necessary. +5. We always specify the visibility, even if it's the default (e.g. `private string _foo` not `string _foo`). Visibility should be the first modifier (e.g. `public abstract` not `abstract public`). +6. Namespace imports should be specified at the top of the file, *outside* of `namespace` declarations and should be sorted alphabetically. +7. Avoid more than one empty line at any time. For example, do not have two blank lines between members of a type. +8. Avoid spurious free spaces. For example avoid `if (someVar == 0)...`, where the dots mark the spurious free spaces. Consider enabling "View White Space (Ctrl+E, S)" if using Visual Studio, to aid detection. +9. If a file happens to differ in style from these guidelines (e.g. private members are named `m_member` rather than `_member`), the existing style in that file takes precedence. +10. We only use `var` when it's obvious what the variable type is (e.g. `var stream = new FileStream(...)` not `var stream = OpenStandardInput()`). +11. We use language keywords instead of BCL types (e.g. `int, string, float` instead of `Int32, String, Single`, etc) for both type references as well as method calls (e.g. `int.Parse` instead of `Int32.Parse`). See issue [391](https://github.com/dotnet/corefx/issues/391) for examples. +12. We use PascalCasing to name all our constant local variables and fields. The only exception is for interop code where the constant value should exactly match the name and value of the code you are calling via interop. +13. We use ```nameof(...)``` instead of ```"..."``` whenever possible and relevant. +14. Fields should be specified at the top within type declarations. +15. When including non-ASCII characters in the source code use Unicode escape sequences (\uXXXX) instead of literal characters. Literal non-ASCII characters occasionally get garbled by a tool or editor. +16. Do not use labels (e.g. for goto). diff --git a/Directory.Build.props b/Directory.Build.props index 1a2e9d3a4..a15044b52 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -65,17 +65,17 @@ - - $(Box_ClientId) + + $(Box13_ClientId) - - $(Box_ClientSecret) + + $(Box13_ClientSecret) - - $(DropBox_ClientId) + + $(DropBox13_ClientId) - - $(DropBox_ClientSecret) + + $(DropBox13_ClientSecret) $(Flickr_ClientId) @@ -83,11 +83,11 @@ $(Flickr_ClientSecret) - - $(Imgur_ClientId) + + $(Imgur13_ClientId) - - $(Imgur_ClientSecret) + + $(Imgur13_ClientSecret) $(Photobucket_ClientId) diff --git a/Greenshot.sln b/Greenshot.sln index 27df62d85..f815631e2 100644 --- a/Greenshot.sln +++ b/Greenshot.sln @@ -14,10 +14,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Gree {697CF066-9077-4F22-99D9-D989CCE7282B} = {697CF066-9077-4F22-99D9-D989CCE7282B} {47F23C86-604E-4CC3-8767-B3D4088F30BB} = {47F23C86-604E-4CC3-8767-B3D4088F30BB} {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50} = {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50} - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02} = {D61E6ECE-E0B6-4467-B492-F08A06BA8F02} {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12} = {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12} {1893A2E4-A78A-4713-A8E7-E70058DABEE0} = {1893A2E4-A78A-4713-A8E7-E70058DABEE0} - {C6988EE8-2FEE-4349-9F09-F9628A0D8965} = {C6988EE8-2FEE-4349-9F09-F9628A0D8965} EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotPlugin", "GreenshotPlugin\GreenshotPlugin.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}" @@ -30,20 +28,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotImgurPlugin", "Gre EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotJiraPlugin", "GreenshotJiraPlugin\GreenshotJiraPlugin.csproj", "{19FEEF09-313F-43C7-819D-F1BCA782B08B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotOCRPlugin", "GreenshotOCRPlugin\GreenshotOCRPlugin.csproj", "{C6988EE8-2FEE-4349-9F09-F9628A0D8965}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotOCRCommand", "GreenshotOCRCommand\GreenshotOCRCommand.csproj", "{D61E6ECE-E0B6-4467-B492-F08A06BA8F02}" - ProjectSection(ProjectDependencies) = postProject - {C6988EE8-2FEE-4349-9F09-F9628A0D8965} = {C6988EE8-2FEE-4349-9F09-F9628A0D8965} - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotBoxPlugin", "GreenshotBoxPlugin\GreenshotBoxPlugin.csproj", "{697CF066-9077-4F22-99D9-D989CCE7282B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotDropboxPlugin", "GreenshotDropboxPlugin\GreenshotDropboxPlugin.csproj", "{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotFlickrPlugin", "GreenshotFlickrPlugin\GreenshotFlickrPlugin.csproj", "{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotPicasaPlugin", "GreenshotPicasaPlugin\GreenshotPicasaPlugin.csproj", "{1893A2E4-A78A-4713-A8E7-E70058DABEE0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotGooglePhotosPlugin", "GreenshotGooglePhotosPlugin\GreenshotGooglePhotosPlugin.csproj", "{1893A2E4-A78A-4713-A8E7-E70058DABEE0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotOfficePlugin", "GreenshotOfficePlugin\GreenshotOfficePlugin.csproj", "{92599C09-FF29-4ABD-B6E6-C48ECD781BAB}" EndProject @@ -51,6 +42,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotPhotobucketPlugin" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreenshotWin10Plugin", "GreenshotWin10Plugin\GreenshotWin10Plugin.csproj", "{9801F62C-540F-4BFE-9211-6405DEDE563B}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{82987F1E-D7E6-4C44-B934-981D366E4672}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + azure-pipelines.yml = azure-pipelines.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -107,22 +104,6 @@ Global {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|Any CPU.Build.0 = Release|Any CPU {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|x86.ActiveCfg = Release|Any CPU {19FEEF09-313F-43C7-819D-F1BCA782B08B}.Release|x86.Build.0 = Release|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|x86.ActiveCfg = Debug|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Debug|x86.Build.0 = Debug|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|Any CPU.Build.0 = Release|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|x86.ActiveCfg = Release|Any CPU - {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|x86.Build.0 = Release|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|x86.ActiveCfg = Debug|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|x86.Build.0 = Debug|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|Any CPU.Build.0 = Release|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|x86.ActiveCfg = Release|Any CPU - {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Release|x86.Build.0 = Release|Any CPU {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|Any CPU.Build.0 = Debug|Any CPU {697CF066-9077-4F22-99D9-D989CCE7282B}.Debug|x86.ActiveCfg = Debug|Any CPU diff --git a/Greenshot/Configuration/LanguageKeys.cs b/Greenshot/Configuration/LanguageKeys.cs index 022f141f1..a668218eb 100644 --- a/Greenshot/Configuration/LanguageKeys.cs +++ b/Greenshot/Configuration/LanguageKeys.cs @@ -25,219 +25,56 @@ namespace Greenshot.Configuration { [SuppressMessage("ReSharper", "InconsistentNaming")] public enum LangKey { none, - about_bugs, - about_donations, - about_host, - about_icons, - about_license, - about_title, - about_translation, - application_title, - bugreport_cancel, - bugreport_info, - bugreport_title, - clipboard_error, - clipboard_inuse, - colorpicker_alpha, - colorpicker_apply, - colorpicker_blue, - colorpicker_green, - colorpicker_htmlcolor, - colorpicker_recentcolors, - colorpicker_red, - colorpicker_title, - colorpicker_transparent, - config_unauthorizedaccess_write, - contextmenu_about, - contextmenu_capturearea, - contextmenu_captureclipboard, - contextmenu_capturefullscreen, - contextmenu_capturefullscreen_all, + contextmenu_capturefullscreen_all, contextmenu_capturefullscreen_left, contextmenu_capturefullscreen_top, contextmenu_capturefullscreen_right, contextmenu_capturefullscreen_bottom, - contextmenu_capturelastregion, - contextmenu_capturewindow, - contextmenu_donate, - contextmenu_exit, - contextmenu_help, - contextmenu_openfile, - contextmenu_quicksettings, - contextmenu_settings, - contextmenu_captureie, - contextmenu_openrecentcapture, - editor_align_bottom, - editor_align_center, - editor_align_horizontal, - editor_align_middle, - editor_align_left, - editor_align_right, - editor_align_top, - editor_align_vertical, - editor_arrange, - editor_arrowheads, - editor_arrowheads_both, - editor_arrowheads_end, - editor_arrowheads_none, - editor_arrowheads_start, - editor_backcolor, - editor_blur_radius, - editor_bold, - editor_brightness, - editor_cancel, - editor_clipboardfailed, - editor_close, + contextmenu_captureie, + editor_clipboardfailed, editor_close_on_save, editor_close_on_save_title, - editor_confirm, - editor_copyimagetoclipboard, - editor_copypathtoclipboard, editor_copytoclipboard, - editor_crop, - editor_cursortool, editor_cuttoclipboard, editor_deleteelement, editor_downonelevel, editor_downtobottom, - editor_drawarrow, - editor_drawellipse, - editor_drawhighlighter, - editor_drawline, - editor_drawfreehand, - editor_drawrectangle, - editor_drawtextbox, editor_duplicate, - editor_edit, editor_email, - editor_file, - editor_fontsize, - editor_forecolor, - editor_highlight_area, - editor_highlight_grayscale, - editor_highlight_mode, - editor_highlight_text, - editor_highlight_magnify, - editor_pixel_size, editor_imagesaved, - editor_italic, - editor_load_objects, - editor_magnification_factor, - editor_match_capture_size, - editor_obfuscate, - editor_obfuscate_blur, - editor_obfuscate_mode, - editor_obfuscate_pixelize, - editor_object, - editor_opendirinexplorer, - editor_pastefromclipboard, - editor_preview_quality, - editor_print, - editor_save, - editor_save_objects, - editor_saveas, - editor_selectall, - editor_senttoprinter, - editor_shadow, - editor_torn_edge, - editor_border, - editor_grayscale, - editor_effects, - editor_storedtoclipboard, - editor_thickness, editor_title, editor_uponelevel, editor_uptotop, - editor_autocrop, editor_undo, editor_redo, - editor_insertwindow, editor_resetsize, error, error_multipleinstances, - error_nowriteaccess, error_openfile, error_openlink, error_save, error_save_invalid_chars, - help_title, - jpegqualitydialog_choosejpegquality, - qualitydialog_dontaskagain, - qualitydialog_title, - settings_reducecolors, print_error, - printoptions_allowcenter, - printoptions_allowenlarge, - printoptions_allowrotate, - printoptions_allowshrink, - printoptions_colors, - printoptions_dontaskagain, - printoptions_pagelayout, - printoptions_printcolor, - printoptions_printgrayscale, - printoptions_printmonochrome, - printoptions_timestamp, - printoptions_inverted, - printoptions_title, quicksettings_destination_file, - settings_alwaysshowqualitydialog, - settings_alwaysshowprintoptionsdialog, - settings_applicationsettings, - settings_autostartshortcut, - settings_capture, - settings_capture_mousepointer, - settings_capture_windows_interactive, - settings_copypathtoclipboard, settings_destination, settings_destination_clipboard, settings_destination_editor, - settings_destination_email, - settings_destination_file, settings_destination_fileas, settings_destination_printer, settings_destination_picker, - settings_editor, settings_filenamepattern, - settings_general, - settings_iecapture, - settings_jpegquality, - settings_qualitysettings, - settings_language, settings_message_filenamepattern, - settings_output, - settings_playsound, - settings_plugins, - settings_plugins_name, - settings_plugins_version, - settings_plugins_createdby, - settings_plugins_dllpath, - settings_preferredfilesettings, - settings_primaryimageformat, - settings_printer, settings_printoptions, - settings_registerhotkeys, - settings_showflashlight, - settings_storagelocation, - settings_title, settings_tooltip_filenamepattern, settings_tooltip_language, settings_tooltip_primaryimageformat, - settings_tooltip_registerhotkeys, settings_tooltip_storagelocation, settings_visualization, - settings_shownotify, - settings_waittime, - settings_windowscapture, settings_window_capture_mode, - settings_network, - settings_checkperiod, - settings_usedefaultproxy, tooltip_firststart, warning, warning_hotkeys, - hotkeys, wait_ie_capture, - update_found, - exported_to + update_found } } diff --git a/Greenshot/Controls/MenuStripEx.cs b/Greenshot/Controls/MenuStripEx.cs index 31aa8f190..7dda22931 100644 --- a/Greenshot/Controls/MenuStripEx.cs +++ b/Greenshot/Controls/MenuStripEx.cs @@ -28,8 +28,6 @@ namespace Greenshot.Controls { /// See: http://blogs.msdn.com/b/rickbrew/archive/2006/01/09/511003.aspx /// public class MenuStripEx : MenuStrip { - private const int WM_MOUSEACTIVATE = 0x21; - private enum NativeConstants : uint { MA_ACTIVATE = 1, MA_ACTIVATEANDEAT = 2, diff --git a/Greenshot/Destinations/EditorDestination.cs b/Greenshot/Destinations/EditorDestination.cs index 415607640..220359238 100644 --- a/Greenshot/Destinations/EditorDestination.cs +++ b/Greenshot/Destinations/EditorDestination.cs @@ -40,10 +40,12 @@ namespace Greenshot.Destinations { private readonly IImageEditor editor; private static readonly Image greenshotIcon = GreenshotResources.GetGreenshotIcon().ToBitmap(); - public EditorDestination() { - } - - public EditorDestination(IImageEditor editor) { + public EditorDestination() + { + // Do not remove, is needed for the framework + } + + public EditorDestination(IImageEditor editor) { this.editor = editor; } diff --git a/Greenshot/Drawing/CursorContainer.cs b/Greenshot/Drawing/CursorContainer.cs index 15078bd76..7b3078510 100644 --- a/Greenshot/Drawing/CursorContainer.cs +++ b/Greenshot/Drawing/CursorContainer.cs @@ -105,10 +105,6 @@ namespace Greenshot.Drawing { cursor.DrawStretched(graphics, Bounds); } - public override Size DefaultSize { - get { - return cursor.Size; - } - } + public override Size DefaultSize => cursor?.Size ?? new Size(16, 16); } } diff --git a/Greenshot/Drawing/DrawableContainer.cs b/Greenshot/Drawing/DrawableContainer.cs index 60eb1e98d..bc0973300 100644 --- a/Greenshot/Drawing/DrawableContainer.cs +++ b/Greenshot/Drawing/DrawableContainer.cs @@ -548,23 +548,11 @@ namespace Greenshot.Drawing return ScaleHelper.ShapeAngleRoundBehavior.Instance; } - public virtual bool HasContextMenu { - get { - return true; - } - } + public virtual bool HasContextMenu => true; - public virtual bool HasDefaultSize { - get { - return false; - } - } + public virtual bool HasDefaultSize => false; - public virtual Size DefaultSize { - get { - throw new NotSupportedException("Object doesn't have a default size"); - } - } + public virtual Size DefaultSize => throw new NotSupportedException("Object doesn't have a default size"); /// /// Allows to override the initializing of the fields, so we can actually have our own defaults diff --git a/Greenshot/Drawing/FilterContainer.cs b/Greenshot/Drawing/FilterContainer.cs index 9ea6bc1a1..631cbed33 100644 --- a/Greenshot/Drawing/FilterContainer.cs +++ b/Greenshot/Drawing/FilterContainer.cs @@ -30,17 +30,13 @@ namespace Greenshot.Drawing { /// /// empty container for filter-only elements /// - [Serializable()] + [Serializable] public abstract class FilterContainer : DrawableContainer { public enum PreparedFilterMode {OBFUSCATE, HIGHLIGHT}; public enum PreparedFilter {BLUR, PIXELIZE, TEXT_HIGHTLIGHT, AREA_HIGHLIGHT, GRAYSCALE, MAGNIFICATION}; - - public PreparedFilter Filter { - get { return (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); } - } - - public FilterContainer(Surface parent) : base(parent) { + + public FilterContainer(Surface parent) : base(parent) { Init(); } diff --git a/Greenshot/Drawing/IconContainer.cs b/Greenshot/Drawing/IconContainer.cs index b35ce28ff..6d5c90986 100644 --- a/Greenshot/Drawing/IconContainer.cs +++ b/Greenshot/Drawing/IconContainer.cs @@ -62,7 +62,7 @@ namespace Greenshot.Drawing { Width = value.Width; Height = value.Height; } - get { return icon; } + get => icon; } /** @@ -78,27 +78,32 @@ namespace Greenshot.Drawing { base.Dispose(disposing); } - public void Load(string filename) { - if (File.Exists(filename)) - { - using Icon fileIcon = new Icon(filename); - Icon = fileIcon; - Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); - } + public void Load(string filename) + { + if (!File.Exists(filename)) + { + return; + } + using Icon fileIcon = new Icon(filename); + Icon = fileIcon; + Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); } - public override void Draw(Graphics graphics, RenderMode rm) { - if (icon != null) { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.NearestNeighbor; - graphics.CompositingQuality = CompositingQuality.Default; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.DrawIcon(icon, Bounds); + public override void Draw(Graphics graphics, RenderMode rm) + { + if (icon == null) + { + return; } + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.InterpolationMode = InterpolationMode.NearestNeighbor; + graphics.CompositingQuality = CompositingQuality.Default; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.DrawIcon(icon, Bounds); } public override bool HasDefaultSize => true; - public override Size DefaultSize => icon.Size; + public override Size DefaultSize => icon?.Size ?? new Size(16,16); } } diff --git a/Greenshot/Drawing/ImageContainer.cs b/Greenshot/Drawing/ImageContainer.cs index fee072aa1..5840c9507 100644 --- a/Greenshot/Drawing/ImageContainer.cs +++ b/Greenshot/Drawing/ImageContainer.cs @@ -77,11 +77,14 @@ namespace Greenshot.Drawing { AddField(GetType(), FieldType.SHADOW, false); } - protected void BitmapContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) { - if (sender.Equals(this)) { - if (FieldType.SHADOW.Equals(e.Field.FieldType)) { - ChangeShadowField(); - } + protected void BitmapContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) + { + if (!sender.Equals(this)) + { + return; + } + if (FieldType.SHADOW.Equals(e.Field.FieldType)) { + ChangeShadowField(); } } @@ -189,12 +192,14 @@ namespace Greenshot.Drawing { /// This checks if a shadow is already generated /// /// - private void CheckShadow(bool shadow) { - if (shadow && _shadowBitmap == null) - { - using var matrix = new Matrix(); - _shadowBitmap = ImageHelper.ApplyEffect(image, new DropShadowEffect(), matrix); - } + private void CheckShadow(bool shadow) + { + if (!shadow || _shadowBitmap != null) + { + return; + } + using var matrix = new Matrix(); + _shadowBitmap = ImageHelper.ApplyEffect(image, new DropShadowEffect(), matrix); } /// @@ -202,25 +207,28 @@ namespace Greenshot.Drawing { /// /// /// - public override void Draw(Graphics graphics, RenderMode rm) { - if (image != null) { - bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + public override void Draw(Graphics graphics, RenderMode rm) + { + if (image == null) + { + return; + } + bool shadow = GetFieldValueAsBool(FieldType.SHADOW); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - if (shadow) { - CheckShadow(true); - graphics.DrawImage(_shadowBitmap, Bounds); - } else { - graphics.DrawImage(image, Bounds); - } + if (shadow) { + CheckShadow(true); + graphics.DrawImage(_shadowBitmap, Bounds); + } else { + graphics.DrawImage(image, Bounds); } } public override bool HasDefaultSize => true; - public override Size DefaultSize => image.Size; + public override Size DefaultSize => image?.Size ?? new Size(32, 32); } } diff --git a/Greenshot/Drawing/LineContainer.cs b/Greenshot/Drawing/LineContainer.cs index eac855644..93b76ad89 100644 --- a/Greenshot/Drawing/LineContainer.cs +++ b/Greenshot/Drawing/LineContainer.cs @@ -34,9 +34,7 @@ namespace Greenshot.Drawing { /// [Serializable()] public class LineContainer : DrawableContainer { - public static readonly int MAX_CLICK_DISTANCE_TOLERANCE = 10; - - public LineContainer(Surface parent) : base(parent) { + public LineContainer(Surface parent) : base(parent) { Init(); } diff --git a/Greenshot/Drawing/RoundedRectangle.cs b/Greenshot/Drawing/RoundedRectangle.cs deleted file mode 100644 index a5d4ea6a0..000000000 --- a/Greenshot/Drawing/RoundedRectangle.cs +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace Greenshot.Drawing { - /// - /// TODO: currently this is only used in the capture form, we might move this code directly to there! - /// - public abstract class RoundedRectangle { - [Flags] - public enum RectangleCorners { - None = 0, TopLeft = 1, TopRight = 2, - BottomLeft = 4, BottomRight = 8, - All = TopLeft | TopRight | BottomLeft | BottomRight - } - - public static GraphicsPath Create2(int x, int y, int width, int height, int radius) { - GraphicsPath gp = new GraphicsPath(); - gp.AddLine(x + radius, y, x + width - radius * 2, y); // Line - gp.AddArc(x + width - radius * 2, y, radius * 2, radius * 2, 270, 90); // Corner - gp.AddLine(x + width, y + radius, x + width, y + height - radius * 2); // Line - gp.AddArc(x + width - radius * 2, y + height - radius * 2, radius * 2, radius * 2, 0, 90); // Corner - gp.AddLine(x + width - radius * 2, y + height, x + radius, y + height); // Line - gp.AddArc(x, y + height - radius * 2, radius * 2, radius * 2, 90, 90); // Corner - gp.AddLine(x, y + height - radius * 2, x, y + radius); // Line - gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); // Corner - gp.CloseFigure(); - - return gp; - } - - public static GraphicsPath Create(int x, int y, int width, int height, int radius, RectangleCorners corners) { - int xw = x + width; - int yh = y + height; - int xwr = xw - radius; - int yhr = yh - radius; - int xr = x + radius; - int yr = y + radius; - int r2 = radius * 2; - int xwr2 = xw - r2; - int yhr2 = yh - r2; - - GraphicsPath p = new GraphicsPath(); - p.StartFigure(); - - //Top Left Corner - if ((RectangleCorners.TopLeft & corners) == RectangleCorners.TopLeft) { - p.AddArc(x, y, r2, r2, 180, 90); - } else { - p.AddLine(x, yr, x, y); - p.AddLine(x, y, xr, y); - } - - //Top Edge - p.AddLine(xr, y, xwr, y); - - //Top Right Corner - if ((RectangleCorners.TopRight & corners) == RectangleCorners.TopRight) { - p.AddArc(xwr2, y, r2, r2, 270, 90); - } else { - p.AddLine(xwr, y, xw, y); - p.AddLine(xw, y, xw, yr); - } - - //Right Edge - p.AddLine(xw, yr, xw, yhr); - - //Bottom Right Corner - if ((RectangleCorners.BottomRight & corners) == RectangleCorners.BottomRight) { - p.AddArc(xwr2, yhr2, r2, r2, 0, 90); - } else { - p.AddLine(xw, yhr, xw, yh); - p.AddLine(xw, yh, xwr, yh); - } - - //Bottom Edge - p.AddLine(xwr, yh, xr, yh); - - //Bottom Left Corner - if ((RectangleCorners.BottomLeft & corners) == RectangleCorners.BottomLeft) { - p.AddArc(x, yhr2, r2, r2, 90, 90); - } else { - p.AddLine(xr, yh, x, yh); - p.AddLine(x, yh, x, yhr); - } - - //Left Edge - p.AddLine(x, yhr, x, yr); - - p.CloseFigure(); - return p; - } - - public static GraphicsPath Create(Rectangle rect, int radius, RectangleCorners corners) { - return Create(rect.X, rect.Y, rect.Width, rect.Height, radius, corners); - } - - public static GraphicsPath Create(int x, int y, int width, int height, int radius) { - return Create(x, y, width, height, radius, RectangleCorners.All); - } - - public static GraphicsPath Create(Rectangle rect, int radius) { - return Create(rect.X, rect.Y, rect.Width, rect.Height, radius); - } - - public static GraphicsPath Create(int x, int y, int width, int height) { - return Create(x, y, width, height, 5); - } - - public static GraphicsPath Create(Rectangle rect) { - return Create(rect.X, rect.Y, rect.Width, rect.Height); - } - } -} diff --git a/Greenshot/Drawing/TextContainer.cs b/Greenshot/Drawing/TextContainer.cs index fda883f16..9d3838580 100644 --- a/Greenshot/Drawing/TextContainer.cs +++ b/Greenshot/Drawing/TextContainer.cs @@ -598,9 +598,15 @@ namespace Greenshot.Drawing DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font); } + /// + /// Convert the StringFormat information into a TextFormatFlags + /// This is important for the rending to work, have it aligned to the correct place + /// + /// StringFormat + /// TextFormatFlags private static TextFormatFlags ConvertStringFormat(StringFormat stringFormat) { - TextFormatFlags flags = TextFormatFlags.Default; + var flags = TextFormatFlags.TextBoxControl | TextFormatFlags.WordBreak; if (stringFormat == null) { return flags; @@ -683,14 +689,7 @@ namespace Greenshot.Drawing drawingRectange.Inflate(-textOffset, -textOffset); } - if (stringFormat != null) - { - TextRenderer.DrawText(graphics, text, font, drawingRectange, fontColor, ConvertStringFormat(stringFormat)); - } - else - { - TextRenderer.DrawText(graphics, text, font, drawingRectange, fontColor); - } + TextRenderer.DrawText(graphics, text, font, drawingRectange, fontColor, ConvertStringFormat(stringFormat)); } public override bool ClickableAt(int x, int y) diff --git a/Greenshot/Forms/AboutForm.Designer.cs b/Greenshot/Forms/AboutForm.Designer.cs index f68fd69ee..4112df177 100644 --- a/Greenshot/Forms/AboutForm.Designer.cs +++ b/Greenshot/Forms/AboutForm.Designer.cs @@ -21,6 +21,7 @@ using System.Windows.Forms; using Greenshot.Helpers; +using GreenshotPlugin.Core; namespace Greenshot.Forms { partial class AboutForm { diff --git a/Greenshot/Forms/CaptureForm.cs b/Greenshot/Forms/CaptureForm.cs index bf21382e8..3cc04ebf6 100644 --- a/Greenshot/Forms/CaptureForm.cs +++ b/Greenshot/Forms/CaptureForm.cs @@ -905,7 +905,7 @@ namespace Greenshot.Forms { // horizontal ruler if (fixedRect.Width > hSpace + 3) { - using GraphicsPath p = RoundedRectangle.Create2( + using GraphicsPath p = CreateRoundedRectangle( fixedRect.X + (fixedRect.Width / 2 - hSpace / 2) + 3, fixedRect.Y - dist - 7, measureWidth.Width - 3, @@ -923,7 +923,7 @@ namespace Greenshot.Forms { // vertical ruler if (fixedRect.Height > vSpace + 3) { - using GraphicsPath p = RoundedRectangle.Create2( + using GraphicsPath p = CreateRoundedRectangle( fixedRect.X - measureHeight.Width + 1, fixedRect.Y + (fixedRect.Height / 2 - vSpace / 2) + 2, measureHeight.Width - 3, @@ -990,7 +990,7 @@ namespace Greenshot.Forms { string xy = _cursorPos.X + " x " + _cursorPos.Y; using Font f = new Font(FontFamily.GenericSansSerif, 8); Size xySize = TextRenderer.MeasureText(xy, f); - using GraphicsPath gp = RoundedRectangle.Create2(_cursorPos.X + 5, _cursorPos.Y + 5, xySize.Width - 3, xySize.Height, 3); + using GraphicsPath gp = CreateRoundedRectangle(_cursorPos.X + 5, _cursorPos.Y + 5, xySize.Width - 3, xySize.Height, 3); using (Brush bgBrush = new SolidBrush(Color.FromArgb(200, 217, 240, 227))) { graphics.FillPath(bgBrush, gp); } @@ -1014,5 +1014,21 @@ namespace Greenshot.Forms { DrawZoom(graphics, sourceRectangle, destinationRectangle); } } + + private static GraphicsPath CreateRoundedRectangle(int x, int y, int width, int height, int radius) + { + var gp = new GraphicsPath(); + gp.AddLine(x + radius, y, x + width - radius * 2, y); // Line + gp.AddArc(x + width - radius * 2, y, radius * 2, radius * 2, 270, 90); // Corner + gp.AddLine(x + width, y + radius, x + width, y + height - radius * 2); // Line + gp.AddArc(x + width - radius * 2, y + height - radius * 2, radius * 2, radius * 2, 0, 90); // Corner + gp.AddLine(x + width - radius * 2, y + height, x + radius, y + height); // Line + gp.AddArc(x, y + height - radius * 2, radius * 2, radius * 2, 90, 90); // Corner + gp.AddLine(x, y + height - radius * 2, x, y + radius); // Line + gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); // Corner + gp.CloseFigure(); + + return gp; + } } } diff --git a/Greenshot/Forms/ColorDialog.cs b/Greenshot/Forms/ColorDialog.cs index f69c8f2fc..b93c01258 100644 --- a/Greenshot/Forms/ColorDialog.cs +++ b/Greenshot/Forms/ColorDialog.cs @@ -59,8 +59,6 @@ namespace Greenshot.Forms { set { PreviewColor(value, this); } } - public IList RecentColors => EditorConfig.RecentColors; - private void CreateColorPalette(int x, int y, int w, int h) { CreateColorButtonColumn(255, 0, 0, x, y, w, h, 11); x += w; diff --git a/Greenshot/Forms/ImageEditorForm.cs b/Greenshot/Forms/ImageEditorForm.cs index a9fe79239..de5022634 100644 --- a/Greenshot/Forms/ImageEditorForm.cs +++ b/Greenshot/Forms/ImageEditorForm.cs @@ -73,12 +73,7 @@ namespace Greenshot.Forms { /// private readonly Fraction[] ZOOM_VALUES = new Fraction[] { (1, 4), (1, 2), (2, 3), (3, 4), (1 ,1), (2, 1), (3, 1), (4, 1), (6, 1) }; - /// - /// An Implementation for the IImageEditor, this way Plugins have access to the HWND handles wich can be used with Win32 API calls. - /// - public IWin32Window WindowHandle => this; - - public static List Editors { + public static List Editors { get { try { EditorList.Sort((e1, e2) => string.Compare(e1.Surface.CaptureDetails.Title, e2.Surface.CaptureDetails.Title, StringComparison.Ordinal)); @@ -517,14 +512,6 @@ namespace Greenshot.Forms { public ICaptureDetails CaptureDetails => _surface.CaptureDetails; - public ToolStripMenuItem GetPluginMenuItem() { - return pluginToolStripMenuItem; - } - - public ToolStripMenuItem GetFileMenuItem() { - return fileStripMenuItem; - } - private void BtnSaveClick(object sender, EventArgs e) { string destinationDesignation = FileDestination.DESIGNATION; if (_surface.LastSaveFullPath == null) { diff --git a/Greenshot/Forms/MainForm.cs b/Greenshot/Forms/MainForm.cs index 4053b41f5..fb35500b6 100644 --- a/Greenshot/Forms/MainForm.cs +++ b/Greenshot/Forms/MainForm.cs @@ -486,12 +486,7 @@ namespace Greenshot.Forms { } } - /// - /// Main context menu - /// - public ContextMenuStrip MainMenu => contextMenu; - - protected override void WndProc(ref Message m) { + protected override void WndProc(ref Message m) { if (HotkeyControl.HandleMessages(ref m)) { return; } @@ -923,7 +918,7 @@ namespace Greenshot.Forms { private void ShowThumbnailOnEnter(object sender, EventArgs e) { if (sender is not ToolStripMenuItem captureWindowItem) return; - WindowDetails window = captureWindowItem.Tag as WindowDetails; + var window = captureWindowItem.Tag as WindowDetails; if (_thumbnailForm == null) { _thumbnailForm = new ThumbnailForm(); } @@ -944,29 +939,39 @@ namespace Greenshot.Forms { _thumbnailForm = null; } + /// + /// Create the "capture window from list" list + /// + /// ToolStripMenuItem + /// EventHandler public void AddCaptureWindowMenuItems(ToolStripMenuItem menuItem, EventHandler eventHandler) { menuItem.DropDownItems.Clear(); // check if thumbnailPreview is enabled and DWM is enabled bool thumbnailPreview = _conf.ThumnailPreview && DWM.IsDwmEnabled; - foreach(WindowDetails window in WindowDetails.GetTopLevelWindows()) { - + foreach(var window in WindowDetails.GetTopLevelWindows()) { + if (LOG.IsDebugEnabled) + { + LOG.Debug(window.ToString()); + } string title = window.Text; - if (title != null) { - if (title.Length > _conf.MaxMenuItemLength) { - title = title.Substring(0, Math.Min(title.Length, _conf.MaxMenuItemLength)); - } - ToolStripItem captureWindowItem = menuItem.DropDownItems.Add(title); - captureWindowItem.Tag = window; - captureWindowItem.Image = window.DisplayIcon; - captureWindowItem.Click += eventHandler; - // Only show preview when enabled - if (thumbnailPreview) { - captureWindowItem.MouseEnter += ShowThumbnailOnEnter; - captureWindowItem.MouseLeave += HideThumbnailOnLeave; - } - } - } + if (string.IsNullOrEmpty(title)) + { + continue; + } + if (title.Length > _conf.MaxMenuItemLength) { + title = title.Substring(0, Math.Min(title.Length, _conf.MaxMenuItemLength)); + } + ToolStripItem captureWindowItem = menuItem.DropDownItems.Add(title); + captureWindowItem.Tag = window; + captureWindowItem.Image = window.DisplayIcon; + captureWindowItem.Click += eventHandler; + // Only show preview when enabled + if (thumbnailPreview) { + captureWindowItem.MouseEnter += ShowThumbnailOnEnter; + captureWindowItem.MouseLeave += HideThumbnailOnLeave; + } + } } private void CaptureAreaToolStripMenuItemClick(object sender, EventArgs e) { diff --git a/Greenshot/Forms/ToolStripMenuSelectList.cs b/Greenshot/Forms/ToolStripMenuSelectList.cs index 4ddfe7cdd..e61cb58b2 100644 --- a/Greenshot/Forms/ToolStripMenuSelectList.cs +++ b/Greenshot/Forms/ToolStripMenuSelectList.cs @@ -22,7 +22,6 @@ using GreenshotPlugin.Core; using System; using System.Collections; -using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using GreenshotPlugin.IniFile; @@ -57,77 +56,8 @@ namespace Greenshot.Forms { Image = _defaultImage; } public ToolStripMenuSelectList() : this(null,false) {} - public ToolStripMenuSelectList(object identifier) : this(identifier,false) {} - /// - /// gets or sets the currently checked item - /// - public ToolStripMenuSelectListItem CheckedItem { - - get { - IEnumerator items = DropDownItems.GetEnumerator(); - while (items.MoveNext()) { - ToolStripMenuSelectListItem tsmi = (ToolStripMenuSelectListItem)items.Current; - if (tsmi != null && tsmi.Checked) { - return tsmi; - } - } - return null; - } - set { - IEnumerator items = DropDownItems.GetEnumerator(); - while (items.MoveNext()) { - ToolStripMenuSelectListItem tsmi = (ToolStripMenuSelectListItem)items.Current; - if (tsmi != null && !_multiCheckAllowed && !tsmi.Equals(value)) { - tsmi.Checked = false; - } else if (tsmi != null && tsmi.Equals(value)) { - tsmi.Checked = true; - } - } - } - } - - /// - /// gets or sets the currently checked items - /// - public ToolStripMenuSelectListItem[] CheckedItems { - get { - List sel = new List(); - IEnumerator items = DropDownItems.GetEnumerator(); - while(items.MoveNext()) { - ToolStripMenuSelectListItem tsmi = (ToolStripMenuSelectListItem)items.Current; - if (tsmi != null && tsmi.Checked) { - sel.Add(tsmi); - } - } - return sel.ToArray(); - } - set { - if (!_multiCheckAllowed) { - throw new ArgumentException("Writing to checkedItems is only allowed in multi-check mode. Either set allowMultiCheck to true or use set SelectedItem instead of SelectedItems."); - } - IEnumerator items = DropDownItems.GetEnumerator(); - IEnumerator sel = value.GetEnumerator(); - while (items.MoveNext()) { - var toolStripMenuSelectListItem = (ToolStripMenuSelectListItem)items.Current; - if (toolStripMenuSelectListItem == null) - { - continue; - } - while (sel.MoveNext()) - { - toolStripMenuSelectListItem.Checked = toolStripMenuSelectListItem.Equals(sel.Current); - if (!_multiCheckAllowed && !toolStripMenuSelectListItem.Equals(sel.Current)) { - toolStripMenuSelectListItem.Checked = false; - } else if (toolStripMenuSelectListItem.Equals(value)) { - toolStripMenuSelectListItem.Checked = true; - } - } - } - } - } - - private void ItemCheckStateChanged(object sender, EventArgs e) { + private void ItemCheckStateChanged(object sender, EventArgs e) { if (_updateInProgress) { return; } @@ -172,44 +102,8 @@ namespace Greenshot.Forms { DropDownItems.Add(toolStripMenuSelectListItem); } - /// - /// adds an item to the select list - /// - /// the label to be displayed - /// the icon to be displayed - public void AddItem(string label, Image image) { - AddItem(label, image, null, false); - } - /// - /// adds an item to the select list - /// - /// the label to be displayed - /// the data to be returned when an item is queried - public void AddItem(string label, object data) { - AddItem(label, null, data, false); - } - - /// - /// adds an item to the select list - /// - /// the label to be displayed - public void AddItem(string label) { - AddItem(label, null, null, false); - } - - - /// - /// adds an item to the select list - /// - /// the label to be displayed - /// the icon to be displayed - /// whether the item is initially checked - public void AddItem(string label, Image image, bool isChecked) { - AddItem(label, image, null, isChecked); - } - - /// + /// /// adds an item to the select list /// /// the label to be displayed @@ -219,16 +113,7 @@ namespace Greenshot.Forms { AddItem(label, null, data, isChecked); } - /// - /// adds an item to the select list - /// - /// the label to be displayed - /// whether the item is initially checked - public void AddItem(string label, bool isChecked) { - AddItem(label, null, null, isChecked); - } - - /// + /// /// unchecks all items of the list /// public void UncheckAll() { diff --git a/Greenshot/Helpers/CaptureHelper.cs b/Greenshot/Helpers/CaptureHelper.cs index 19acda012..813a18b4f 100644 --- a/Greenshot/Helpers/CaptureHelper.cs +++ b/Greenshot/Helpers/CaptureHelper.cs @@ -970,7 +970,7 @@ namespace Greenshot.Helpers { // The following, to be precise the HideApp, causes the app to close as described in BUG-1620 // Added check for metro (Modern UI) apps, which might be maximized and cover the screen. - //foreach(WindowDetails app in WindowDetails.GetMetroApps()) { + //foreach(WindowDetails app in WindowDetails.GetAppWindows()) { // if (app.Maximised) { // app.HideApp(); // } diff --git a/Greenshot/Helpers/EnvironmentInfo.cs b/Greenshot/Helpers/EnvironmentInfo.cs deleted file mode 100644 index cc88802aa..000000000 --- a/Greenshot/Helpers/EnvironmentInfo.cs +++ /dev/null @@ -1,855 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.UnmanagedHelpers; -using Microsoft.Win32; - -namespace Greenshot.Helpers -{ - /// - /// Description of EnvironmentInfo. - /// - public static class EnvironmentInfo - { - private static bool? _isWindows; - - public static bool IsWindows - { - get - { - if (_isWindows.HasValue) - { - return _isWindows.Value; - } - _isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); - return _isWindows.Value; - } - } - - public static bool IsNet45OrNewer() - { - // Class "ReflectionContext" exists from .NET 4.5 onwards. - return Type.GetType("System.Reflection.ReflectionContext", false) != null; - } - - public static string GetGreenshotVersion(bool shortVersion = false) - { - var executingAssembly = Assembly.GetExecutingAssembly(); - - // Use assembly version - string greenshotVersion = executingAssembly.GetName().Version.ToString(); - - // Use AssemblyFileVersion if available - var assemblyFileVersionAttribute = executingAssembly.GetCustomAttribute(); - if (!string.IsNullOrEmpty(assemblyFileVersionAttribute?.Version)) - { - var assemblyFileVersion = new Version(assemblyFileVersionAttribute.Version); - greenshotVersion = assemblyFileVersion.ToString(3); - } - - if (!shortVersion) - { - // Use AssemblyInformationalVersion if available - var informationalVersionAttribute = executingAssembly.GetCustomAttribute(); - if (!string.IsNullOrEmpty(informationalVersionAttribute?.InformationalVersion)) - { - greenshotVersion = informationalVersionAttribute.InformationalVersion; - } - } - - return greenshotVersion.Replace("+", " - "); - } - - public static string EnvironmentToString(bool newline) - { - StringBuilder environment = new StringBuilder(); - environment.Append("Software version: " + GetGreenshotVersion()); - if (IniConfig.IsPortable) { - environment.Append(" Portable"); - } - environment.Append(" (" + OsInfo.Bits + " bit)"); - - if (newline) - { - environment.AppendLine(); - } - else - { - environment.Append(", "); - } - environment.Append(".NET runtime version: " + Environment.Version); - if (IsNet45OrNewer()) - { - environment.Append("+"); - - } - if (newline) - { - environment.AppendLine(); - } - else - { - environment.Append(", "); - } - environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz")); - - if (IsWindows) - { - if (newline) - { - environment.AppendLine(); - } - else - { - environment.Append(", "); - } - - environment.Append($"OS: {OsInfo.Name}"); - if (!string.IsNullOrEmpty(OsInfo.Edition)) - { - environment.Append($" {OsInfo.Edition}"); - - } - if (!string.IsNullOrEmpty(OsInfo.ServicePack)) - { - environment.Append($" {OsInfo.ServicePack}"); - - } - environment.Append($" x{OsInfo.Bits}"); - environment.Append($" {OsInfo.VersionString}"); - if (newline) - { - environment.AppendLine(); - } - else - { - environment.Append(", "); - } - // Get some important information for fixing GDI related Problems - environment.AppendFormat("GDI object count: {0}", User32.GetGuiResourcesGDICount()); - if (newline) - { - environment.AppendLine(); - } - else - { - environment.Append(", "); - } - environment.AppendFormat("User object count: {0}", User32.GetGuiResourcesUserCount()); - } - else - { - if (newline) - { - environment.AppendLine(); - } - else - { - environment.Append(", "); - } - environment.AppendFormat("OS: {0}", Environment.OSVersion.Platform); - } - if (newline) - { - environment.AppendLine(); - } - else - { - environment.Append(", "); - } - // TODO: Is this needed? - // environment.AppendFormat("Surface count: {0}", Surface.Count); - - return environment.ToString(); - } - - public static string ExceptionToString(Exception ex) - { - if (ex == null) - return "null\r\n"; - - StringBuilder report = new StringBuilder(); - - report.AppendLine("Exception: " + ex.GetType()); - report.AppendLine("Message: " + ex.Message); - if (ex.Data.Count > 0) - { - report.AppendLine(); - report.AppendLine("Additional Information:"); - foreach (object key in ex.Data.Keys) - { - object data = ex.Data[key]; - if (data != null) - { - report.AppendLine(key + " : " + data); - } - } - } - if (ex is ExternalException externalException) - { - // e.g. COMException - report.AppendLine().AppendLine("ErrorCode: 0x" + externalException.ErrorCode.ToString("X")); - } - - report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace); - - if (ex is ReflectionTypeLoadException reflectionTypeLoadException) - { - report.AppendLine().AppendLine("LoaderExceptions: "); - foreach (Exception cbE in reflectionTypeLoadException.LoaderExceptions) - { - report.AppendLine(cbE.Message); - } - } - - if (ex.InnerException != null) - { - report.AppendLine("--- InnerException: ---"); - report.AppendLine(ExceptionToString(ex.InnerException)); - } - return report.ToString(); - } - - public static string BuildReport(Exception exception) - { - StringBuilder exceptionText = new StringBuilder(); - exceptionText.AppendLine(EnvironmentToString(true)); - exceptionText.AppendLine(ExceptionToString(exception)); - exceptionText.AppendLine("Configuration dump:"); - - return exceptionText.ToString(); - } - } - - /// - /// Provides detailed information about the host operating system. - /// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/ - /// - public static class OsInfo - { - /// - /// Determines if the current application is 32 or 64-bit. - /// - public static int Bits => IntPtr.Size * 8; - - private static string _sEdition; - - /// - /// Gets the edition of the operating system running on this computer. - /// - public static string Edition - { - get - { - if (_sEdition != null) - { - return _sEdition; //***** RETURN *****// - } - - string edition = string.Empty; - - OperatingSystem osVersion = Environment.OSVersion; - OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create(); - - if (GetVersionEx(ref osVersionInfo)) - { - int majorVersion = osVersion.Version.Major; - int minorVersion = osVersion.Version.Minor; - byte productType = osVersionInfo.ProductType; - ushort suiteMask = osVersionInfo.SuiteMask; - - if (majorVersion == 4) - { - if (productType == VER_NT_WORKSTATION) - { - // Windows NT 4.0 Workstation - edition = "Workstation"; - } - else if (productType == VER_NT_SERVER) - { - edition = (suiteMask & VER_SUITE_ENTERPRISE) != 0 ? "Enterprise Server" : "Standard Server"; - } - } - - else if (majorVersion == 5) - { - if (productType == VER_NT_WORKSTATION) - { - if ((suiteMask & VER_SUITE_PERSONAL) != 0) - { - // Windows XP Home Edition - edition = "Home"; - } - else - { - // Windows XP / Windows 2000 Professional - edition = "Professional"; - } - } - else if (productType == VER_NT_SERVER) - { - if (minorVersion == 0) - { - if ((suiteMask & VER_SUITE_DATACENTER) != 0) - { - // Windows 2000 Datacenter Server - edition = "Datacenter Server"; - } - else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) - { - // Windows 2000 Advanced Server - edition = "Advanced Server"; - } - else - { - // Windows 2000 Server - edition = "Server"; - } - } - else - { - if ((suiteMask & VER_SUITE_DATACENTER) != 0) - { - // Windows Server 2003 Datacenter Edition - edition = "Datacenter"; - } - else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) - { - // Windows Server 2003 Enterprise Edition - edition = "Enterprise"; - } - else if ((suiteMask & VER_SUITE_BLADE) != 0) - { - // Windows Server 2003 Web Edition - edition = "Web Edition"; - } - else - { - // Windows Server 2003 Standard Edition - edition = "Standard"; - } - } - } - } - - else if (majorVersion == 6) - { - if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.ServicePackMajor, osVersionInfo.ServicePackMinor, out var ed)) - { - switch (ed) - { - case PRODUCT_BUSINESS: - edition = "Business"; - break; - case PRODUCT_BUSINESS_N: - edition = "Business N"; - break; - case PRODUCT_CLUSTER_SERVER: - edition = "HPC Edition"; - break; - case PRODUCT_DATACENTER_SERVER: - edition = "Datacenter Server"; - break; - case PRODUCT_DATACENTER_SERVER_CORE: - edition = "Datacenter Server (core installation)"; - break; - case PRODUCT_ENTERPRISE: - edition = "Enterprise"; - break; - case PRODUCT_ENTERPRISE_N: - edition = "Enterprise N"; - break; - case PRODUCT_ENTERPRISE_SERVER: - edition = "Enterprise Server"; - break; - case PRODUCT_ENTERPRISE_SERVER_CORE: - edition = "Enterprise Server (core installation)"; - break; - case PRODUCT_ENTERPRISE_SERVER_CORE_V: - edition = "Enterprise Server without Hyper-V (core installation)"; - break; - case PRODUCT_ENTERPRISE_SERVER_IA64: - edition = "Enterprise Server for Itanium-based Systems"; - break; - case PRODUCT_ENTERPRISE_SERVER_V: - edition = "Enterprise Server without Hyper-V"; - break; - case PRODUCT_HOME_BASIC: - edition = "Home Basic"; - break; - case PRODUCT_HOME_BASIC_N: - edition = "Home Basic N"; - break; - case PRODUCT_HOME_PREMIUM: - edition = "Home Premium"; - break; - case PRODUCT_HOME_PREMIUM_N: - edition = "Home Premium N"; - break; - case PRODUCT_HYPERV: - edition = "Microsoft Hyper-V Server"; - break; - case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT: - edition = "Windows Essential Business Management Server"; - break; - case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING: - edition = "Windows Essential Business Messaging Server"; - break; - case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY: - edition = "Windows Essential Business Security Server"; - break; - case PRODUCT_SERVER_FOR_SMALLBUSINESS: - edition = "Windows Essential Server Solutions"; - break; - case PRODUCT_SERVER_FOR_SMALLBUSINESS_V: - edition = "Windows Essential Server Solutions without Hyper-V"; - break; - case PRODUCT_SMALLBUSINESS_SERVER: - edition = "Windows Small Business Server"; - break; - case PRODUCT_STANDARD_SERVER: - edition = "Standard Server"; - break; - case PRODUCT_STANDARD_SERVER_CORE: - edition = "Standard Server (core installation)"; - break; - case PRODUCT_STANDARD_SERVER_CORE_V: - edition = "Standard Server without Hyper-V (core installation)"; - break; - case PRODUCT_STANDARD_SERVER_V: - edition = "Standard Server without Hyper-V"; - break; - case PRODUCT_STARTER: - edition = "Starter"; - break; - case PRODUCT_STORAGE_ENTERPRISE_SERVER: - edition = "Enterprise Storage Server"; - break; - case PRODUCT_STORAGE_EXPRESS_SERVER: - edition = "Express Storage Server"; - break; - case PRODUCT_STORAGE_STANDARD_SERVER: - edition = "Standard Storage Server"; - break; - case PRODUCT_STORAGE_WORKGROUP_SERVER: - edition = "Workgroup Storage Server"; - break; - case PRODUCT_UNDEFINED: - edition = "Unknown product"; - break; - case PRODUCT_ULTIMATE: - edition = "Ultimate"; - break; - case PRODUCT_ULTIMATE_N: - edition = "Ultimate N"; - break; - case PRODUCT_WEB_SERVER: - edition = "Web Server"; - break; - case PRODUCT_WEB_SERVER_CORE: - edition = "Web Server (core installation)"; - break; - } - } - } - } - - _sEdition = edition; - return edition; - } - } - - private static string _name; - /// - /// Gets the name of the operating system running on this computer. - /// - public static string Name - { - get - { - if (_name != null) - { - return _name; //***** RETURN *****// - } - - string name = "unknown"; - - OperatingSystem osVersion = Environment.OSVersion; - OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create(); - if (GetVersionEx(ref osVersionInfo)) - { - int majorVersion = osVersion.Version.Major; - int minorVersion = osVersion.Version.Minor; - byte productType = osVersionInfo.ProductType; - ushort suiteMask = osVersionInfo.SuiteMask; - switch (osVersion.Platform) - { - case PlatformID.Win32Windows: - if (majorVersion == 4) - { - string csdVersion = osVersionInfo.ServicePackVersion; - switch (minorVersion) - { - case 0: - if (csdVersion == "B" || csdVersion == "C") - { - name = "Windows 95 OSR2"; - } - else - { - name = "Windows 95"; - } - break; - case 10: - name = csdVersion == "A" ? "Windows 98 Second Edition" : "Windows 98"; - break; - case 90: - name = "Windows Me"; - break; - } - } - break; - case PlatformID.Win32NT: - switch (majorVersion) - { - case 3: - name = "Windows NT 3.51"; - break; - case 4: - switch (productType) - { - case 1: - name = "Windows NT 4.0"; - break; - case 3: - name = "Windows NT 4.0 Server"; - break; - } - break; - case 5: - switch (minorVersion) - { - case 0: - name = "Windows 2000"; - break; - case 1: - name = suiteMask switch - { - 0x0200 => "Windows XP Professional", - _ => "Windows XP" - }; - break; - case 2: - name = suiteMask switch - { - 0x0200 => "Windows XP Professional x64", - 0x0002 => "Windows Server 2003 Enterprise", - 0x0080 => "Windows Server 2003 Data Center", - 0x0400 => "Windows Server 2003 Web Edition", - 0x8000 => "Windows Home Server", - _ => "Windows Server 2003" - }; - break; - } - break; - case 6: - switch (minorVersion) - { - case 0: - name = productType switch - { - 3 => "Windows Server 2008", - _ => "Windows Vista" - }; - break; - case 1: - name = productType switch - { - 3 => "Windows Server 2008 R2", - _ => "Windows 7" - }; - break; - case 2: - name = "Windows 8"; - break; - case 3: - name = "Windows 8.1"; - break; - } - break; - case 10: - string releaseId = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", "").ToString(); - name = $"Windows 10 {releaseId}"; - break; - } - break; - } - } - - _name = name; - return name; - } - } - - [DllImport("Kernel32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool GetProductInfo( - int osMajorVersion, - int osMinorVersion, - int spMajorVersion, - int spMinorVersion, - out int edition); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private unsafe struct OSVERSIONINFOEX - { - /// - /// The size of this data structure, in bytes. Set this member to sizeof(OSVERSIONINFOEX). - /// - private int _dwOSVersionInfoSize; - - private readonly int _dwMajorVersion; - private readonly int _dwMinorVersion; - private readonly int _dwBuildNumber; - private readonly int _dwPlatformId; - private fixed char _szCSDVersion[128]; - private readonly short _wServicePackMajor; - private readonly short _wServicePackMinor; - private readonly ushort _wSuiteMask; - private readonly byte _wProductType; - private readonly byte _wReserved; - - /// - /// The major version number of the operating system. - /// - public int MajorVersion => _dwMajorVersion; - - /// - /// The minor version number of the operating system. - /// - public int MinorVersion => _dwMinorVersion; - - /// - /// The build number of the operating system. - /// - public int BuildNumber => _dwBuildNumber; - - /// - /// The operating system platform. This member can be VER_PLATFORM_WIN32_NT (2). - /// - public int PlatformId => _dwPlatformId; - - /// - /// A null-terminated string, such as "Service Pack 3", that indicates the latest Service Pack installed on the system. - /// If no Service Pack has been installed, the string is empty. - /// - public string ServicePackVersion - { - get - { - fixed (char* servicePackVersion = _szCSDVersion) - { - return new string(servicePackVersion); - } - - } - } - - /// - /// The major version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the - /// major version number is 3. - /// If no Service Pack has been installed, the value is zero. - /// - public short ServicePackMajor => _wServicePackMajor; - - /// - /// The minor version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the - /// minor version number is 0. - /// - public short ServicePackMinor => _wServicePackMinor; - - /// - /// A bit mask that identifies the product suites available on the system. This member can be a combination of the - /// following values. - /// - public ushort SuiteMask => _wSuiteMask; - - /// - /// Any additional information about the system. - /// - public byte ProductType => _wProductType; - - /// - /// Factory for an empty OsVersionInfoEx - /// - /// OSVERSIONINFOEX - public static OSVERSIONINFOEX Create() - { - return new OSVERSIONINFOEX - { - _dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)) - }; - } - } - - private const int PRODUCT_UNDEFINED = 0x00000000; - private const int PRODUCT_ULTIMATE = 0x00000001; - private const int PRODUCT_HOME_BASIC = 0x00000002; - private const int PRODUCT_HOME_PREMIUM = 0x00000003; - private const int PRODUCT_ENTERPRISE = 0x00000004; - private const int PRODUCT_HOME_BASIC_N = 0x00000005; - private const int PRODUCT_BUSINESS = 0x00000006; - private const int PRODUCT_STANDARD_SERVER = 0x00000007; - private const int PRODUCT_DATACENTER_SERVER = 0x00000008; - private const int PRODUCT_SMALLBUSINESS_SERVER = 0x00000009; - private const int PRODUCT_ENTERPRISE_SERVER = 0x0000000A; - private const int PRODUCT_STARTER = 0x0000000B; - private const int PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C; - private const int PRODUCT_STANDARD_SERVER_CORE = 0x0000000D; - private const int PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E; - private const int PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F; - private const int PRODUCT_BUSINESS_N = 0x00000010; - private const int PRODUCT_WEB_SERVER = 0x00000011; - private const int PRODUCT_CLUSTER_SERVER = 0x00000012; - private const int PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014; - private const int PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015; - private const int PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016; - private const int PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017; - private const int PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018; - private const int PRODUCT_HOME_PREMIUM_N = 0x0000001A; - private const int PRODUCT_ENTERPRISE_N = 0x0000001B; - private const int PRODUCT_ULTIMATE_N = 0x0000001C; - private const int PRODUCT_WEB_SERVER_CORE = 0x0000001D; - private const int PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E; - private const int PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F; - private const int PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020; - private const int PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023; - private const int PRODUCT_STANDARD_SERVER_V = 0x00000024; - private const int PRODUCT_ENTERPRISE_SERVER_V = 0x00000026; - private const int PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028; - private const int PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029; - private const int PRODUCT_HYPERV = 0x0000002A; - - private const int VER_NT_WORKSTATION = 1; - private const int VER_NT_SERVER = 3; - private const int VER_SUITE_ENTERPRISE = 2; - private const int VER_SUITE_DATACENTER = 128; - private const int VER_SUITE_PERSONAL = 512; - private const int VER_SUITE_BLADE = 1024; - - /// - /// Gets the service pack information of the operating system running on this computer. - /// - public static string ServicePack - { - get - { - string servicePack = string.Empty; - OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create(); - - if (GetVersionEx(ref osVersionInfo)) - { - servicePack = osVersionInfo.ServicePackVersion; - } - - return servicePack; - } - } - - /// - /// Gets the build version number of the operating system running on this computer. - /// - public static int BuildVersion => Environment.OSVersion.Version.Build; - - /// - /// Gets the full version string of the operating system running on this computer. - /// - public static string VersionString - { - get - { - if (WindowsVersion.IsWindows10OrLater) - { - return $"build {Environment.OSVersion.Version.Build}"; - } - if (Environment.OSVersion.Version.Revision != 0) - { - return $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build} revision {Environment.OSVersion.Version.Revision:X}"; - } - return $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build}"; - } - } - - /// - /// Gets the full version of the operating system running on this computer. - /// - public static Version Version - { - get - { - return Environment.OSVersion.Version; - } - } - - /// - /// Gets the major version number of the operating system running on this computer. - /// - public static int MajorVersion - { - get - { - return Environment.OSVersion.Version.Major; - } - } - - /// - /// Gets the minor version number of the operating system running on this computer. - /// - public static int MinorVersion - { - get - { - return Environment.OSVersion.Version.Minor; - } - } - - /// - /// Gets the revision version number of the operating system running on this computer. - /// - public static int RevisionVersion - { - get - { - return Environment.OSVersion.Version.Revision; - } - } - } -} \ No newline at end of file diff --git a/Greenshot/Helpers/GuiRectangle.cs b/Greenshot/Helpers/GuiRectangle.cs index c24e591ec..108c5a48e 100644 --- a/Greenshot/Helpers/GuiRectangle.cs +++ b/Greenshot/Helpers/GuiRectangle.cs @@ -28,7 +28,7 @@ namespace Greenshot.Helpers { public static class GuiRectangle { public static Rectangle GetGuiRectangle(int x, int y, int w, int h) { - Rectangle rect = new Rectangle(x, y, w, h); + var rect = new Rectangle(x, y, w, h); MakeGuiRectangle(ref rect); return rect; } @@ -43,22 +43,5 @@ namespace Greenshot.Helpers { rect.Height = -rect.Height; } } - - public static RectangleF GetGuiRectangleF(float x, float y, float w, float h) { - RectangleF rect = new RectangleF(x, y, w, h); - MakeGuiRectangleF(ref rect); - return rect; - } - - public static void MakeGuiRectangleF(ref RectangleF rect) { - if (rect.Width < 0) { - rect.X += rect.Width; - rect.Width = -rect.Width; - } - if (rect.Height < 0) { - rect.Y += rect.Height; - rect.Height = -rect.Height; - } - } - } + } } diff --git a/Greenshot/Helpers/IECaptureHelper.cs b/Greenshot/Helpers/IECaptureHelper.cs index f74403176..24b5136cf 100644 --- a/Greenshot/Helpers/IECaptureHelper.cs +++ b/Greenshot/Helpers/IECaptureHelper.cs @@ -60,27 +60,7 @@ namespace Greenshot.Helpers { ieAccessible.ActivateIETab(tabIndex); } - /// - /// Return true if the supplied window has a sub-window which covers more than the supplied percentage - /// - /// WindowDetails to check - /// min percentage - /// - public static bool IsMostlyIeWindow(WindowDetails someWindow, int minimumPercentage) { - WindowDetails ieWindow = someWindow.GetChild("Internet Explorer_Server"); - if (ieWindow == null) return false; - - Rectangle wholeClient = someWindow.ClientRectangle; - Rectangle partClient = ieWindow.ClientRectangle; - int percentage = (int)(100*(float)(partClient.Width * partClient.Height) / (wholeClient.Width * wholeClient.Height)); - Log.InfoFormat("Window {0}, ie part {1}, percentage {2}", wholeClient, partClient, percentage); - if (percentage > minimumPercentage) { - return true; - } - return false; - } - - /// + /// /// Does the supplied window have a IE part? /// /// @@ -321,15 +301,7 @@ namespace Greenshot.Helpers { return returnDocumentContainer; } - /// - /// Here the logic for capturing the IE Content is located - /// - /// ICapture where the capture needs to be stored - /// ICapture with the content (if any) - public static ICapture CaptureIe(ICapture capture) { - return CaptureIe(capture, WindowDetails.GetActiveWindow()); - } - /// + /// /// Here the logic for capturing the IE Content is located /// /// ICapture where the capture needs to be stored diff --git a/Greenshot/Helpers/MailHelper.cs b/Greenshot/Helpers/MailHelper.cs index 3bc09b5f8..2ba02461e 100644 --- a/Greenshot/Helpers/MailHelper.cs +++ b/Greenshot/Helpers/MailHelper.cs @@ -126,14 +126,7 @@ namespace Greenshot.Helpers { _manualResetEvent = new ManualResetEvent(false); } - /// - /// Creates a new mail message with the specified subject. - /// - public MapiMailMessage(string subject) : this() { - Subject = subject; - } - - /// + /// /// Creates a new mail message with the specified subject and body. /// public MapiMailMessage(string subject, string body) : this() { @@ -437,21 +430,6 @@ namespace Greenshot.Helpers { public MapiMailMessage.RecipientType RecipientType = MapiMailMessage.RecipientType.To; /// - /// Creates a new recipient with the specified address. - /// - public Recipient(string address) { - Address = address; - } - - /// - /// Creates a new recipient with the specified address and display name. - /// - public Recipient(string address, string displayName) { - Address = address; - DisplayName = displayName; - } - - /// /// Creates a new recipient with the specified address and recipient type. /// public Recipient(string address, MapiMailMessage.RecipientType recipientType) { @@ -459,15 +437,6 @@ namespace Greenshot.Helpers { RecipientType = recipientType; } - /// - /// Creates a new recipient with the specified address, display name and recipient type. - /// - public Recipient(string address, string displayName, MapiMailMessage.RecipientType recipientType) { - Address = address; - DisplayName = displayName; - RecipientType = recipientType; - } - /// /// Returns an interop representation of a recepient. /// @@ -499,40 +468,7 @@ namespace Greenshot.Helpers { List.Add(value); } - /// - /// Adds a new recipient with the specified address to this collection. - /// - public void Add(string address) { - Add(new Recipient(address)); - } - - /// - /// Adds a new recipient with the specified address and display name to this collection. - /// - public void Add(string address, string displayName) { - Add(new Recipient(address, displayName)); - } - - /// - /// Adds a new recipient with the specified address and recipient type to this collection. - /// - public void Add(string address, MapiMailMessage.RecipientType recipientType) { - Add(new Recipient(address, recipientType)); - } - - /// - /// Adds a new recipient with the specified address, display name and recipient type to this collection. - /// - public void Add(string address, string displayName, MapiMailMessage.RecipientType recipientType) { - Add(new Recipient(address, displayName, recipientType)); - } - - /// - /// Returns the recipient stored in this collection at the specified index. - /// - public Recipient this[int index] => (Recipient)List[index]; - - internal InteropRecipientCollection GetInteropRepresentation() { + internal InteropRecipientCollection GetInteropRepresentation() { return new InteropRecipientCollection(this); } diff --git a/Greenshot/Helpers/ScaleHelper.cs b/Greenshot/Helpers/ScaleHelper.cs index bb1103ec1..883fb238d 100644 --- a/Greenshot/Helpers/ScaleHelper.cs +++ b/Greenshot/Helpers/ScaleHelper.cs @@ -1,374 +1,339 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -using System; -using System.Drawing; -using System.Windows.Forms; -using Greenshot.Drawing; - -namespace Greenshot.Helpers { - /// - /// Offers a few helper functions for scaling/aligning an element with another element - /// - public static class ScaleHelper { - - [Flags] - public enum ScaleOptions { - /// - /// Default scale behavior. - /// - Default = 0x00, - /// - /// Scale a rectangle in two our four directions, mirrored at it's center coordinates - /// - Centered = 0x01, - /// - /// Scale a rectangle maintaining it's aspect ratio - /// - Rational = 0x02 - } - - /// - /// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio - /// - /// the size of the element to be resized - /// the target size of the element - /// in case the aspect ratio of currentSize and targetSize differs: shall the scaled size fit into targetSize (i.e. that one of its dimensions is smaller - false) or vice versa (true) - /// a new SizeF object indicating the width and height the element should be scaled to - public static SizeF GetScaledSize(SizeF currentSize, SizeF targetSize, bool crop) { - float wFactor = targetSize.Width/currentSize.Width; - float hFactor = targetSize.Height/currentSize.Height; - - float factor = crop ? Math.Max(wFactor, hFactor) : Math.Min(wFactor, hFactor); - return new SizeF(currentSize.Width * factor, currentSize.Height * factor); - } - - /// - /// calculates the position of an element depending on the desired alignment within a RectangleF - /// - /// the bounds of the element to be aligned - /// the rectangle reference for alignment of the element - /// the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize - /// a new RectangleF object with Location aligned aligned to targetRect - public static RectangleF GetAlignedRectangle(RectangleF currentRect, RectangleF targetRect, ContentAlignment alignment) { - RectangleF newRect = new RectangleF(targetRect.Location, currentRect.Size); - switch(alignment) { - case ContentAlignment.TopCenter: - newRect.X = (targetRect.Width - currentRect.Width) / 2; - break; - case ContentAlignment.TopRight: - newRect.X = targetRect.Width - currentRect.Width; - break; - case ContentAlignment.MiddleLeft: - newRect.Y = (targetRect.Height - currentRect.Height) / 2; - break; - case ContentAlignment.MiddleCenter: - newRect.Y = (targetRect.Height - currentRect.Height) / 2; - newRect.X = (targetRect.Width - currentRect.Width) / 2; - break; - case ContentAlignment.MiddleRight: - newRect.Y = (targetRect.Height - currentRect.Height) / 2; - newRect.X = targetRect.Width - currentRect.Width; - break; - case ContentAlignment.BottomLeft: - newRect.Y = targetRect.Height - currentRect.Height; - break; - case ContentAlignment.BottomCenter: - newRect.Y = targetRect.Height - currentRect.Height; - newRect.X = (targetRect.Width - currentRect.Width) / 2; - break; - case ContentAlignment.BottomRight: - newRect.Y = targetRect.Height - currentRect.Height; - newRect.X = targetRect.Width - currentRect.Width; - break; - } - return newRect; - } - - /// - /// calculates the Rectangle an element must be resized an positioned to, in ordder to fit another element, keeping aspect ratio - /// - /// the rectangle of the element to be resized/repositioned - /// the target size/position of the element - /// in case the aspect ratio of currentSize and targetSize differs: shall the scaled size fit into targetSize (i.e. that one of its dimensions is smaller - false) or vice versa (true) - /// the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize - /// a new RectangleF object indicating the width and height the element should be scaled to and the position that should be applied to it for proper alignment - public static RectangleF GetScaledRectangle(RectangleF currentRect, RectangleF targetRect, bool crop, ContentAlignment alignment) { - SizeF newSize = GetScaledSize(currentRect.Size, targetRect.Size, crop); - RectangleF newRect = new RectangleF(new Point(0,0), newSize); - return GetAlignedRectangle(newRect, targetRect, alignment); - } - - public static void RationalScale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) { - Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Rational); - } - - public static void CenteredScale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) { - Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Centered); - } - - public static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) { - Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, null); - } - - /// - /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) - /// - /// bounds of the current rectangle, scaled values will be written to this reference - /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT - /// coordinates of the used handle/gripper - /// ScaleOptions to use when scaling - public static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords, ScaleOptions? options) { - options ??= GetScaleOptions(); - - if ((options & ScaleOptions.Rational) == ScaleOptions.Rational) { - adjustCoordsForRationalScale(originalRectangle, resizeHandlePosition, ref resizeHandleCoords); - } - - if ((options & ScaleOptions.Centered) == ScaleOptions.Centered) { - // store center coordinates of rectangle - float rectCenterX = originalRectangle.Left + originalRectangle.Width / 2; - float rectCenterY = originalRectangle.Top + originalRectangle.Height / 2; - // scale rectangle using handle coordinates - scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords); - // mirror handle coordinates via rectangle center coordinates - resizeHandleCoords.X -= 2 * (resizeHandleCoords.X - rectCenterX); - resizeHandleCoords.Y -= 2 * (resizeHandleCoords.Y - rectCenterY); - // scale again with opposing handle and mirrored coordinates - resizeHandlePosition = (Positions)((((int)resizeHandlePosition) + 4) % 8); - scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords); - } else { - scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords); - } - - } - - /// - /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) - /// - /// bounds of the current rectangle, scaled values will be written to this reference - /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT - /// coordinates of the used handle/gripper - private static void scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) { - switch(resizeHandlePosition) { - - case Positions.TopLeft: - originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X; - originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y; - originalRectangle.X = resizeHandleCoords.X; - originalRectangle.Y = resizeHandleCoords.Y; - break; - - case Positions.TopCenter: - originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y; - originalRectangle.Y = resizeHandleCoords.Y; - break; - - case Positions.TopRight: - originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left; - originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y; - originalRectangle.Y = resizeHandleCoords.Y; - break; - - case Positions.MiddleLeft: - originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X; - originalRectangle.X = resizeHandleCoords.X; - break; - - case Positions.MiddleRight: - originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left; - break; - - case Positions.BottomLeft: - originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X; - originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top; - originalRectangle.X = resizeHandleCoords.X; - break; - - case Positions.BottomCenter: - originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top; - break; - - case Positions.BottomRight: - originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left; - originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top; - break; - - default: - throw new ArgumentException("Position cannot be handled: "+resizeHandlePosition); - - } - } - - /// - /// Adjusts resizeHandleCoords so that aspect ratio is kept after resizing a given rectangle with provided arguments. - /// An adjustment can always be done in two ways, e.g. *in*crease width until fit or *de*crease height until fit. - /// To avoid objects growing near infinity unexpectedly in certain combinations, the adjustment will choose the - /// option resulting in the smaller rectangle. - /// - /// bounds of the current rectangle - /// position of the handle/gripper being used for resized, see Position - /// coordinates of the used handle/gripper, adjusted coordinates will be written to this reference - private static void adjustCoordsForRationalScale(RectangleF originalRectangle, Positions resizeHandlePosition, ref PointF resizeHandleCoords) { - SizeF selectedRectangle, newSize; - - switch(resizeHandlePosition) { - - case Positions.TopLeft: - selectedRectangle = new SizeF(originalRectangle.Right - resizeHandleCoords.X, originalRectangle.Bottom - resizeHandleCoords.Y); - newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); - resizeHandleCoords.X = originalRectangle.Right - newSize.Width; - resizeHandleCoords.Y = originalRectangle.Bottom - newSize.Height; - break; - - case Positions.TopRight: - selectedRectangle = new SizeF(resizeHandleCoords.X - originalRectangle.Left, originalRectangle.Bottom - resizeHandleCoords.Y); - newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); - resizeHandleCoords.X = originalRectangle.Left + newSize.Width; - resizeHandleCoords.Y = originalRectangle.Bottom - newSize.Height; - break; - - case Positions.BottomLeft: - selectedRectangle = new SizeF(originalRectangle.Right - resizeHandleCoords.X, resizeHandleCoords.Y - originalRectangle.Top); - newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); - resizeHandleCoords.X = originalRectangle.Right - newSize.Width; - resizeHandleCoords.Y = originalRectangle.Top + newSize.Height; - break; - - case Positions.BottomRight: - selectedRectangle = new SizeF(resizeHandleCoords.X - originalRectangle.Left, resizeHandleCoords.Y - originalRectangle.Top); - newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); - resizeHandleCoords.X = originalRectangle.Left + newSize.Width; - resizeHandleCoords.Y = originalRectangle.Top + newSize.Height; - break; - } - } - - /// - /// For an original size, and a selected size, returns the the largest possible size that - /// * has the same aspect ratio as the original - /// * fits into selected size - /// - /// size to be considered for keeping aspect ratio - /// selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio) - /// - private static SizeF getNewSizeForRationalScale(SizeF originalSize, SizeF selectedSize) - { - SizeF newSize = selectedSize; - float originalRatio = originalSize.Width / originalSize.Height; - float selectedRatio = selectedSize.Width / selectedSize.Height; - // will fix orientation if the scaling causes size to be flipped in any direction - int flippedRatioSign = Math.Sign(selectedRatio) * Math.Sign(originalRatio); - if (Math.Abs(selectedRatio) > Math.Abs(originalRatio)) - { - // scaled rectangle (ratio) would be wider than original - // keep height and tweak width to maintain aspect ratio - newSize.Width = selectedSize.Height * originalRatio * flippedRatioSign; - } - else if (Math.Abs(selectedRatio) < Math.Abs(originalRatio)) - { - // scaled rectangle (ratio) would be taller than original - // keep width and tweak height to maintain aspect ratio - newSize.Height = selectedSize.Width / originalRatio * flippedRatioSign; - } - return newSize; - } - - public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize) { - Scale(boundsBeforeResize, cursorX, cursorY, ref boundsAfterResize, null); - } - - public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) { - - Scale(boundsBeforeResize, Positions.TopLeft, cursorX, cursorY, ref boundsAfterResize, angleRoundBehavior); - } - - public static void Scale(Rectangle boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) { - - ScaleOptions opts = GetScaleOptions(); - - bool rationalScale = (opts & ScaleOptions.Rational) == ScaleOptions.Rational; - bool centeredScale = (opts & ScaleOptions.Centered) == ScaleOptions.Centered; - - if(rationalScale) { - double angle = GeometryHelper.Angle2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY); - - if(angleRoundBehavior != null) { - angle = angleRoundBehavior.Process(angle); - } - - int dist = GeometryHelper.Distance2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY); - - boundsAfterResize.Width = (int)Math.Round(dist * Math.Cos(angle / 180 * Math.PI)); - boundsAfterResize.Height = (int)Math.Round(dist * Math.Sin(angle / 180 * Math.PI)); - } - - if(centeredScale) { - float wdiff = boundsAfterResize.Width - boundsBeforeResize.Width; - float hdiff = boundsAfterResize.Height - boundsBeforeResize.Height; - boundsAfterResize.Width += wdiff; - boundsAfterResize.Height += hdiff; - boundsAfterResize.X -= wdiff; - boundsAfterResize.Y -= hdiff; - } - - - } - - /// the current ScaleOptions depending on modifier keys held down - public static ScaleOptions GetScaleOptions() { - bool anchorAtCenter = (Control.ModifierKeys & Keys.Control) != 0; - bool maintainAspectRatio = (Control.ModifierKeys & Keys.Shift) != 0; - ScaleOptions opts = ScaleOptions.Default; - if(anchorAtCenter) opts |= ScaleOptions.Centered; - if(maintainAspectRatio) opts |= ScaleOptions.Rational; - return opts; - } - - public interface IDoubleProcessor { - double Process(double d); - } - - public class ShapeAngleRoundBehavior : IDoubleProcessor { - public static ShapeAngleRoundBehavior Instance = new(); - private ShapeAngleRoundBehavior() {} - public double Process(double angle) { - return Math.Round((angle+45)/90)*90 - 45; - } - } - public class LineAngleRoundBehavior : IDoubleProcessor { - public static LineAngleRoundBehavior Instance = new(); - private LineAngleRoundBehavior() {} - public double Process(double angle) { - return Math.Round(angle/15)*15; - } - } - public class FixedAngleRoundBehavior : IDoubleProcessor { - private readonly double fixedAngle; - public FixedAngleRoundBehavior(double fixedAngle) { - this.fixedAngle = fixedAngle; - } - public double Process(double angle) { - return fixedAngle; - } - } - } -} +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System; +using System.Drawing; +using System.Windows.Forms; +using Greenshot.Drawing; + +namespace Greenshot.Helpers { + /// + /// Offers a few helper functions for scaling/aligning an element with another element + /// + public static class ScaleHelper { + + [Flags] + public enum ScaleOptions { + /// + /// Default scale behavior. + /// + Default = 0x00, + /// + /// Scale a rectangle in two our four directions, mirrored at it's center coordinates + /// + Centered = 0x01, + /// + /// Scale a rectangle maintaining it's aspect ratio + /// + Rational = 0x02 + } + + /// + /// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio + /// + /// the size of the element to be resized + /// the target size of the element + /// in case the aspect ratio of currentSize and targetSize differs: shall the scaled size fit into targetSize (i.e. that one of its dimensions is smaller - false) or vice versa (true) + /// a new SizeF object indicating the width and height the element should be scaled to + public static SizeF GetScaledSize(SizeF currentSize, SizeF targetSize, bool crop) { + float wFactor = targetSize.Width/currentSize.Width; + float hFactor = targetSize.Height/currentSize.Height; + + float factor = crop ? Math.Max(wFactor, hFactor) : Math.Min(wFactor, hFactor); + return new SizeF(currentSize.Width * factor, currentSize.Height * factor); + } + + /// + /// calculates the position of an element depending on the desired alignment within a RectangleF + /// + /// the bounds of the element to be aligned + /// the rectangle reference for alignment of the element + /// the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize + /// a new RectangleF object with Location aligned aligned to targetRect + public static RectangleF GetAlignedRectangle(RectangleF currentRect, RectangleF targetRect, ContentAlignment alignment) { + RectangleF newRect = new RectangleF(targetRect.Location, currentRect.Size); + switch(alignment) { + case ContentAlignment.TopCenter: + newRect.X = (targetRect.Width - currentRect.Width) / 2; + break; + case ContentAlignment.TopRight: + newRect.X = targetRect.Width - currentRect.Width; + break; + case ContentAlignment.MiddleLeft: + newRect.Y = (targetRect.Height - currentRect.Height) / 2; + break; + case ContentAlignment.MiddleCenter: + newRect.Y = (targetRect.Height - currentRect.Height) / 2; + newRect.X = (targetRect.Width - currentRect.Width) / 2; + break; + case ContentAlignment.MiddleRight: + newRect.Y = (targetRect.Height - currentRect.Height) / 2; + newRect.X = targetRect.Width - currentRect.Width; + break; + case ContentAlignment.BottomLeft: + newRect.Y = targetRect.Height - currentRect.Height; + break; + case ContentAlignment.BottomCenter: + newRect.Y = targetRect.Height - currentRect.Height; + newRect.X = (targetRect.Width - currentRect.Width) / 2; + break; + case ContentAlignment.BottomRight: + newRect.Y = targetRect.Height - currentRect.Height; + newRect.X = targetRect.Width - currentRect.Width; + break; + } + return newRect; + } + + /// + /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) + /// + /// bounds of the current rectangle, scaled values will be written to this reference + /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT + /// coordinates of the used handle/gripper + /// ScaleOptions to use when scaling + public static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords, ScaleOptions? options) { + options ??= GetScaleOptions(); + + if ((options & ScaleOptions.Rational) == ScaleOptions.Rational) { + AdjustCoordsForRationalScale(originalRectangle, resizeHandlePosition, ref resizeHandleCoords); + } + + if ((options & ScaleOptions.Centered) == ScaleOptions.Centered) { + // store center coordinates of rectangle + float rectCenterX = originalRectangle.Left + originalRectangle.Width / 2; + float rectCenterY = originalRectangle.Top + originalRectangle.Height / 2; + // scale rectangle using handle coordinates + Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords); + // mirror handle coordinates via rectangle center coordinates + resizeHandleCoords.X -= 2 * (resizeHandleCoords.X - rectCenterX); + resizeHandleCoords.Y -= 2 * (resizeHandleCoords.Y - rectCenterY); + // scale again with opposing handle and mirrored coordinates + resizeHandlePosition = (Positions)((((int)resizeHandlePosition) + 4) % 8); + Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords); + } else { + Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords); + } + + } + + /// + /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) + /// + /// bounds of the current rectangle, scaled values will be written to this reference + /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT + /// coordinates of the used handle/gripper + private static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) { + switch(resizeHandlePosition) { + + case Positions.TopLeft: + originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X; + originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y; + originalRectangle.X = resizeHandleCoords.X; + originalRectangle.Y = resizeHandleCoords.Y; + break; + + case Positions.TopCenter: + originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y; + originalRectangle.Y = resizeHandleCoords.Y; + break; + + case Positions.TopRight: + originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left; + originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y; + originalRectangle.Y = resizeHandleCoords.Y; + break; + + case Positions.MiddleLeft: + originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X; + originalRectangle.X = resizeHandleCoords.X; + break; + + case Positions.MiddleRight: + originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left; + break; + + case Positions.BottomLeft: + originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X; + originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top; + originalRectangle.X = resizeHandleCoords.X; + break; + + case Positions.BottomCenter: + originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top; + break; + + case Positions.BottomRight: + originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left; + originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top; + break; + + default: + throw new ArgumentException("Position cannot be handled: "+resizeHandlePosition); + + } + } + + /// + /// Adjusts resizeHandleCoords so that aspect ratio is kept after resizing a given rectangle with provided arguments. + /// An adjustment can always be done in two ways, e.g. *in*crease width until fit or *de*crease height until fit. + /// To avoid objects growing near infinity unexpectedly in certain combinations, the adjustment will choose the + /// option resulting in the smaller rectangle. + /// + /// bounds of the current rectangle + /// position of the handle/gripper being used for resized, see Position + /// coordinates of the used handle/gripper, adjusted coordinates will be written to this reference + private static void AdjustCoordsForRationalScale(RectangleF originalRectangle, Positions resizeHandlePosition, ref PointF resizeHandleCoords) { + SizeF selectedRectangle, newSize; + + switch(resizeHandlePosition) { + + case Positions.TopLeft: + selectedRectangle = new SizeF(originalRectangle.Right - resizeHandleCoords.X, originalRectangle.Bottom - resizeHandleCoords.Y); + newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); + resizeHandleCoords.X = originalRectangle.Right - newSize.Width; + resizeHandleCoords.Y = originalRectangle.Bottom - newSize.Height; + break; + + case Positions.TopRight: + selectedRectangle = new SizeF(resizeHandleCoords.X - originalRectangle.Left, originalRectangle.Bottom - resizeHandleCoords.Y); + newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); + resizeHandleCoords.X = originalRectangle.Left + newSize.Width; + resizeHandleCoords.Y = originalRectangle.Bottom - newSize.Height; + break; + + case Positions.BottomLeft: + selectedRectangle = new SizeF(originalRectangle.Right - resizeHandleCoords.X, resizeHandleCoords.Y - originalRectangle.Top); + newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); + resizeHandleCoords.X = originalRectangle.Right - newSize.Width; + resizeHandleCoords.Y = originalRectangle.Top + newSize.Height; + break; + + case Positions.BottomRight: + selectedRectangle = new SizeF(resizeHandleCoords.X - originalRectangle.Left, resizeHandleCoords.Y - originalRectangle.Top); + newSize = getNewSizeForRationalScale(originalRectangle.Size, selectedRectangle); + resizeHandleCoords.X = originalRectangle.Left + newSize.Width; + resizeHandleCoords.Y = originalRectangle.Top + newSize.Height; + break; + } + } + + /// + /// For an original size, and a selected size, returns the the largest possible size that + /// * has the same aspect ratio as the original + /// * fits into selected size + /// + /// size to be considered for keeping aspect ratio + /// selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio) + /// + private static SizeF getNewSizeForRationalScale(SizeF originalSize, SizeF selectedSize) + { + SizeF newSize = selectedSize; + float originalRatio = originalSize.Width / originalSize.Height; + float selectedRatio = selectedSize.Width / selectedSize.Height; + // will fix orientation if the scaling causes size to be flipped in any direction + int flippedRatioSign = Math.Sign(selectedRatio) * Math.Sign(originalRatio); + if (Math.Abs(selectedRatio) > Math.Abs(originalRatio)) + { + // scaled rectangle (ratio) would be wider than original + // keep height and tweak width to maintain aspect ratio + newSize.Width = selectedSize.Height * originalRatio * flippedRatioSign; + } + else if (Math.Abs(selectedRatio) < Math.Abs(originalRatio)) + { + // scaled rectangle (ratio) would be taller than original + // keep width and tweak height to maintain aspect ratio + newSize.Height = selectedSize.Width / originalRatio * flippedRatioSign; + } + return newSize; + } + + public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize) { + Scale(boundsBeforeResize, cursorX, cursorY, ref boundsAfterResize, null); + } + + public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) { + + Scale(boundsBeforeResize, Positions.TopLeft, cursorX, cursorY, ref boundsAfterResize, angleRoundBehavior); + } + + public static void Scale(Rectangle boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) { + + ScaleOptions opts = GetScaleOptions(); + + bool rationalScale = (opts & ScaleOptions.Rational) == ScaleOptions.Rational; + bool centeredScale = (opts & ScaleOptions.Centered) == ScaleOptions.Centered; + + if(rationalScale) { + double angle = GeometryHelper.Angle2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY); + + if(angleRoundBehavior != null) { + angle = angleRoundBehavior.Process(angle); + } + + int dist = GeometryHelper.Distance2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY); + + boundsAfterResize.Width = (int)Math.Round(dist * Math.Cos(angle / 180 * Math.PI)); + boundsAfterResize.Height = (int)Math.Round(dist * Math.Sin(angle / 180 * Math.PI)); + } + + if(centeredScale) { + float wdiff = boundsAfterResize.Width - boundsBeforeResize.Width; + float hdiff = boundsAfterResize.Height - boundsBeforeResize.Height; + boundsAfterResize.Width += wdiff; + boundsAfterResize.Height += hdiff; + boundsAfterResize.X -= wdiff; + boundsAfterResize.Y -= hdiff; + } + + + } + + /// the current ScaleOptions depending on modifier keys held down + public static ScaleOptions GetScaleOptions() { + bool anchorAtCenter = (Control.ModifierKeys & Keys.Control) != 0; + bool maintainAspectRatio = (Control.ModifierKeys & Keys.Shift) != 0; + ScaleOptions opts = ScaleOptions.Default; + if(anchorAtCenter) opts |= ScaleOptions.Centered; + if(maintainAspectRatio) opts |= ScaleOptions.Rational; + return opts; + } + + public interface IDoubleProcessor { + double Process(double d); + } + + public class ShapeAngleRoundBehavior : IDoubleProcessor { + public static ShapeAngleRoundBehavior Instance = new(); + private ShapeAngleRoundBehavior() {} + public double Process(double angle) { + return Math.Round((angle+45)/90)*90 - 45; + } + } + public class LineAngleRoundBehavior : IDoubleProcessor { + public static LineAngleRoundBehavior Instance = new(); + private LineAngleRoundBehavior() {} + public double Process(double angle) { + return Math.Round(angle/15)*15; + } + } + } +} \ No newline at end of file diff --git a/Greenshot/Helpers/ToolStripItemEndisabler.cs b/Greenshot/Helpers/ToolStripItemEndisabler.cs index db5a5d178..0a8e13d84 100644 --- a/Greenshot/Helpers/ToolStripItemEndisabler.cs +++ b/Greenshot/Helpers/ToolStripItemEndisabler.cs @@ -54,16 +54,8 @@ namespace Greenshot.Helpers { public static void Enable(ToolStripItem tsi) { Endisable(tsi, true, PropagationMode.CHILDREN | PropagationMode.ANCESTORS); } - - /// - /// Disables the ToolStripItem, including children (ToolStripDropDownItem), - /// but NOT the ancestor (OwnerItem) - /// - public static void Disable(ToolStripItem tsi) { - Endisable(tsi, false, PropagationMode.CHILDREN); - } - - private static void Endisable(ToolStrip ts, bool enable, PropagationMode mode) + + private static void Endisable(ToolStrip ts, bool enable, PropagationMode mode) { if ((mode & PropagationMode.CHILDREN) != PropagationMode.CHILDREN) return; diff --git a/Greenshot/Helpers/UpdateService.cs b/Greenshot/Helpers/UpdateService.cs index 8c1728fb8..4ef120690 100644 --- a/Greenshot/Helpers/UpdateService.cs +++ b/Greenshot/Helpers/UpdateService.cs @@ -93,17 +93,6 @@ namespace Greenshot.Helpers _ = BackgroundTask(() => TimeSpan.FromDays(CoreConfig.UpdateCheckInterval), UpdateCheck, _cancellationTokenSource.Token); } - /// - /// Stop the update checks - /// - public void Shutdown() - { - if (!_cancellationTokenSource.IsCancellationRequested) - { - _cancellationTokenSource.Cancel(); - } - } - /// /// This runs a periodic task in the background /// diff --git a/Greenshot/releases/innosetup/setup.iss b/Greenshot/releases/innosetup/setup.iss index 3195d1f55..b4ddf605b 100644 --- a/Greenshot/releases/innosetup/setup.iss +++ b/Greenshot/releases/innosetup/setup.iss @@ -25,6 +25,7 @@ Source: {#ReleaseDir}\Dapplo.Http*.dll; DestDir: {app}; Components: greenshot; F Source: {#ReleaseDir}\Dapplo.Log.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Svg.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Fizzler.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\HtmlAgilityPack.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Newtonsoft.Json.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: ..\..\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion @@ -78,11 +79,6 @@ Source: ..\..\Languages\*zh-TW*; Excludes: "*installer*,*website*"; DestDir: {ap ;Office Plugin Source: {#BaseDir}\GreenshotOfficePlugin\{#BinDir}\GreenshotOfficePlugin.dll; DestDir: {app}\Plugins\GreenshotOfficePlugin; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; -;OCR Plugin -Source: {#BaseDir}\GreenshotOCRPlugin\{#BinDir}\GreenshotOCRPlugin.dll; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; -Source: {#BaseDir}\GreenshotOCRPlugin\Languages\language_ocr*.xml; DestDir: {app}\Languages\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly ignoreversion replacesameversion; -Source: {#BaseDir}\GreenshotOCRCommand\{#BinDir}\GreenshotOCRCommand.exe; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; -Source: {#BaseDir}\GreenshotOCRCommand\{#BinDir}\GreenshotOCRCommand.exe.config; DestDir: {app}\Plugins\GreenshotOCRPlugin; Components: plugins\ocr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; ;JIRA Plugin Source: {#BaseDir}\GreenshotJiraPlugin\{#BinDir}\GreenshotJiraPlugin.dll; DestDir: {app}\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\GreenshotJiraPlugin\{#BinDir}\Dapplo.Jira*.dll; DestDir: {app}\Plugins\GreenshotJiraPlugin; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; @@ -103,8 +99,8 @@ Source: {#BaseDir}\GreenshotFlickrPlugin\Languages\language_flickr*.xml; DestDir Source: {#BaseDir}\GreenshotPhotobucketPlugin\{#BinDir}\GreenshotPhotobucketPlugin.dll; DestDir: {app}\Plugins\GreenshotPhotobucketPlugin; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\GreenshotPhotobucketPlugin\Languages\language_photo*.xml; DestDir: {app}\Languages\Plugins\GreenshotPhotobucketPlugin; Components: plugins\photobucket; Flags: overwritereadonly ignoreversion replacesameversion; ;Picasa Plugin -Source: {#BaseDir}\GreenshotPicasaPlugin\{#BinDir}\GreenshotPicasaPlugin.dll; DestDir: {app}\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; -Source: {#BaseDir}\GreenshotPicasaPlugin\Languages\language_picasa*.xml; DestDir: {app}\Languages\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly ignoreversion replacesameversion; +;Source: {#BaseDir}\GreenshotPicasaPlugin\{#BinDir}\GreenshotPicasaPlugin.dll; DestDir: {app}\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +;Source: {#BaseDir}\GreenshotPicasaPlugin\Languages\language_picasa*.xml; DestDir: {app}\Languages\Plugins\GreenshotPicasaPlugin; Components: plugins\picasa; Flags: overwritereadonly ignoreversion replacesameversion; ;Confluence Plugin Source: {#BaseDir}\GreenshotConfluencePlugin\{#BinDir}\GreenshotConfluencePlugin.dll; DestDir: {app}\Plugins\GreenshotConfluencePlugin; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#BaseDir}\GreenshotConfluencePlugin\Languages\language_confluence*.xml; DestDir: {app}\Languages\Plugins\GreenshotConfluencePlugin; Components: plugins\confluence; Flags: overwritereadonly ignoreversion replacesameversion; @@ -113,6 +109,8 @@ Source: {#BaseDir}\GreenshotExternalCommandPlugin\{#BinDir}\GreenshotExternalCom Source: {#BaseDir}\GreenshotExternalCommandPlugin\Languages\language_externalcommand*.xml; DestDir: {app}\Languages\Plugins\GreenshotExternalCommandPlugin; Components: plugins\externalcommand; Flags: overwritereadonly ignoreversion replacesameversion; ;Win 10 Plugin Source: {#BaseDir}\GreenshotWin10Plugin\{#BinDir}\GreenshotWin10Plugin.dll; DestDir: {app}\Plugins\GreenshotWin10Plugin; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; +Source: {#BaseDir}\GreenshotWin10Plugin\{#BinDir}\Microsoft.Toolkit.Uwp.Notifications; DestDir: {app}\Plugins\GreenshotWin10Plugin; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; + [Setup] ; changes associations is used when the installer installs new extensions, it clears the explorer icon cache ChangesAssociations=yes @@ -260,7 +258,6 @@ en.flickr=Flickr plug-in en.imgur=Imgur plug-in (See: http://imgur.com) en.jira=Jira plug-in en.language=Additional languages -en.ocr=OCR plug-in (needs Microsoft Office Document Imaging (MODI)) en.office=Microsoft Office plug-in en.optimize=Optimizing performance, this may take a while. en.photobucket=Photobucket plug-in @@ -278,7 +275,6 @@ de.externalcommand=Externes Kommando Plug-in de.imgur=Imgur Plug-in (Siehe: http://imgur.com) de.jira=Jira Plug-in de.language=Zusätzliche Sprachen -de.ocr=OCR Plug-in (benötigt Microsoft Office Document Imaging (MODI)) de.office=Microsoft Office Plug-in de.optimize=Optimierung der Leistung, kann etwas dauern. de.startgreenshot={#ExeName} starten @@ -291,7 +287,6 @@ es.externalcommand=Extensión para abrir con programas externos es.imgur=Extensión para Imgur (Ver http://imgur.com) es.jira=Extensión para Jira es.language=Idiomas adicionales -es.ocr=Extensión para OCR (necesita Microsoft Office Document Imaging (MODI)) es.optimize=Optimizando rendimiento; por favor, espera. es.startgreenshot=Lanzar {#ExeName} es.startup=Lanzar {#ExeName} al iniciarse Windows @@ -303,7 +298,6 @@ fi.externalcommand=Avaa Ulkoinen komento-liitännäisellä fi.imgur=Imgur-liitännäinen (Katso: http://imgur.com) fi.jira=Jira-liitännäinen fi.language=Lisäkielet -fi.ocr=OCR-liitännäinen (Tarvitaan: Microsoft Office Document Imaging (MODI)) fi.office=Microsoft-Office-liitännäinen fi.optimize=Optimoidaan suorituskykyä, tämä voi kestää hetken. fi.startgreenshot=Käynnistä {#ExeName} @@ -316,7 +310,6 @@ fr.externalcommand=Ouvrir avec le greffon de commande externe fr.imgur=Greffon Imgur (Voir: http://imgur.com) fr.jira=Greffon Jira fr.language=Langues additionnelles -fr.ocr=Greffon OCR (nécessite Document Imaging de Microsoft Office [MODI]) fr.office=Greffon Microsoft Office fr.optimize=Optimisation des performances, Ceci peut prendre un certain temps. fr.startgreenshot=Démarrer {#ExeName} @@ -332,7 +325,6 @@ it.flickr=Plugin Flickr it.imgur=Plugin Imgur (vedi: http://imgur.com) it.jira=Plugin Jira it.language=Lingue aggiuntive -it.ocr=Plugin OCR (richiede Microsoft Office Document Imaging (MODI)) it.office=Plugin Microsoft Office it.optimize=Ottimizzazione prestazioni (può richiedere tempo). it.photobucket=Plugin Photobucket @@ -386,7 +378,6 @@ lt.externalcommand=Pielāgotu darbību spraudnis lt.imgur=Imgur spraudnis (Vairāk šeit: http://imgur.com) lt.jira=Jira spraudnis lt.language=Papildus valodas -lt.ocr=OCR spraudnis (nepieciešams Microsoft Office Document Imaging (MODI)) lt.office=Microsoft Office spraudnis lt.optimize=Uzlaboju veikstpēju, tas prasīs kādu laiciņu. lt.startgreenshot=Palaist {#ExeName} @@ -399,7 +390,6 @@ lt.externalcommand=Pielāgotu darbību spraudnis lt.imgur=Imgur spraudnis (Vairāk šeit: http://imgur.com) lt.jira=Jira spraudnis lt.language=Papildus valodas -lt.ocr=OCR spraudnis (nepieciešams Microsoft Office Document Imaging (MODI)) lt.office=Microsoft Office spraudnis lt.optimize=Uzlaboju veikstpēju, tas prasīs kādu laiciņu. lt.startgreenshot=Palaist {#ExeName} @@ -412,7 +402,6 @@ nl.externalcommand=Openen met extern commando plug-in nl.imgur=Imgur plug-in (zie: http://imgur.com) nl.jira=Jira plug-in nl.language=Extra talen -nl.ocr=OCR plug-in (vereist Microsoft Office Document Imaging (MODI)) nl.office=Microsoft Office plug-in nl.optimize=Prestaties verbeteren, even geduld. nl.startgreenshot={#ExeName} starten @@ -425,7 +414,6 @@ nn.externalcommand=Tillegg for å opne med ekstern kommando nn.imgur=Imgur-tillegg (sjå http://imgur.com) nn.jira=Jira-tillegg nn.language=Andre språk -nn.ocr=OCR-tillegg (krev Microsoft Office Document Imaging (MODI)) nn.office=Microsoft Office Tillegg nn.optimize=Optimaliserar ytelse, dette kan ta litt tid... nn.startgreenshot=Start {#ExeName} @@ -438,7 +426,6 @@ ru.externalcommand=Открыть с плагином с помощью внеш ru.imgur=Плагин Imgur (смотрите https://imgur.com/) ru.jira=Плагин Jira ru.language=Дополнительные языки -ru.ocr=Плагин OCR (требуется Microsoft Office Document Imaging (MODI)) ru.office=Плагин Microsoft Office ru.optimize=Идет оптимизация производительности, это может занять некоторое время. ru.startgreenshot=Запустить {#ExeName} @@ -451,7 +438,6 @@ sr.externalcommand=Отвори са прикључком за спољне на sr.imgur=Прикључак за Имиџер (http://imgur.com) sr.jira=Прикључак за Џиру sr.language=Додатни језици -sr.ocr=OCR прикључак (захтева Microsoft Office Document Imaging (MODI)) sr.optimize=Оптимизујем перформансе… sr.startgreenshot=Покрени Гриншот sr.startup=Покрени програм са системом @@ -462,7 +448,6 @@ sv.externalcommand=Öppna med externt kommando-insticksprogram sv.imgur=Imgur-insticksprogram (Se: http://imgur.com) sv.jira=Jira-insticksprogram sv.language=Ytterligare språk -sv.ocr=OCR-insticksprogram (kräver Microsoft Office Document Imaging (MODI)) sv.optimize=Optimerar prestanda, detta kan ta en stund. sv.startgreenshot=Starta {#ExeName} sv.startup=Starta {#ExeName} med Windows @@ -474,7 +459,6 @@ uk.externalcommand=Плагін запуску зовнішньої команд uk.imgur=Плагін Imgur (див.: http://imgur.com) uk.jira=Плагін Jira uk.language=Додаткові мови -uk.ocr=Плагін OCR (потребує Microsoft Office Document Imaging (MODI)) uk.optimize=Оптимізація продуктивності, це може забрати час. uk.startgreenshot=Запустити {#ExeName} uk.startup=Запускати {#ExeName} під час запуску Windows @@ -486,7 +470,6 @@ cn.externalcommand=使用外部命令打开插件 cn.imgur=Imgur插件( (请访问: http://imgur.com)) cn.jira=Jira插件 cn.language=其它语言 -cn.ocr=OCR插件(需要Microsoft Office Document Imaging (MODI)的支持) cn.optimize=正在优化性能,这可能需要一点时间。 cn.startgreenshot=启动{#ExeName} cn.startup=让{#ExeName}随Windows一起启动 @@ -508,10 +491,9 @@ Name: "plugins\externalcommand"; Description: {cm:externalcommand}; Types: defau Name: "plugins\flickr"; Description: {cm:flickr}; Types: full custom; Flags: disablenouninstallwarning Name: "plugins\imgur"; Description: {cm:imgur}; Types: default full custom; Flags: disablenouninstallwarning Name: "plugins\jira"; Description: {cm:jira}; Types: full custom; Flags: disablenouninstallwarning -Name: "plugins\ocr"; Description: {cm:ocr}; Types: default full custom; Flags: disablenouninstallwarning Name: "plugins\office"; Description: {cm:office}; Types: default full custom; Flags: disablenouninstallwarning Name: "plugins\photobucket"; Description: {cm:photobucket}; Types: full custom; Flags: disablenouninstallwarning -Name: "plugins\picasa"; Description: {cm:picasa}; Types: full custom; Flags: disablenouninstallwarning +;Name: "plugins\picasa"; Description: {cm:picasa}; Types: full custom; Flags: disablenouninstallwarning Name: "plugins\win10"; Description: {cm:win10}; Types: default full custom; Flags: disablenouninstallwarning; Check: IsWindows10OrNewer() Name: "languages"; Description: {cm:language}; Types: full custom; Flags: disablenouninstallwarning Name: "languages\arSY"; Description: {cm:arSY}; Types: full custom; Flags: disablenouninstallwarning; Check: hasLanguageGroup('d') diff --git a/GreenshotBoxPlugin/BoxDestination.cs b/GreenshotBoxPlugin/BoxDestination.cs index 06402ca89..4283a178c 100644 --- a/GreenshotBoxPlugin/BoxDestination.cs +++ b/GreenshotBoxPlugin/BoxDestination.cs @@ -30,17 +30,9 @@ namespace GreenshotBoxPlugin { _plugin = plugin; } - public override string Designation { - get { - return "Box"; - } - } + public override string Designation => "Box"; - public override string Description { - get { - return Language.GetString("box", LangKey.upload_menu_item); - } - } + public override string Description => Language.GetString("box", LangKey.upload_menu_item); public override Image DisplayIcon { get { diff --git a/GreenshotBoxPlugin/BoxUtils.cs b/GreenshotBoxPlugin/BoxUtils.cs index 28bc90fb6..a20447c86 100644 --- a/GreenshotBoxPlugin/BoxUtils.cs +++ b/GreenshotBoxPlugin/BoxUtils.cs @@ -21,18 +21,18 @@ using GreenshotPlugin.Core; using System.Collections.Generic; -using System.Drawing; using System.IO; using System.Runtime.Serialization.Json; using System.Text; +using GreenshotPlugin.Core.OAuth; using GreenshotPlugin.IniFile; namespace GreenshotBoxPlugin { - /// - /// Description of ImgurUtils. - /// - public static class BoxUtils { + /// + /// Description of BoxUtils. + /// + public static class BoxUtils { private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(BoxUtils)); private static readonly BoxConfiguration Config = IniConfig.GetIniSection(); private const string UploadFileUri = "https://upload.box.com/api/2.0/files/content"; @@ -73,9 +73,8 @@ namespace GreenshotBoxPlugin { CloudServiceName = "Box", ClientId = BoxCredentials.ClientId, ClientSecret = BoxCredentials.ClientSecret, - RedirectUrl = "https://www.box.com/home/", - BrowserSize = new Size(1060, 600), - AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser, + RedirectUrl = "https://getgreenshot.org/authorize/box", + AuthorizeMode = OAuth2AuthorizeMode.JsonReceiver, RefreshToken = Config.RefreshToken, AccessToken = Config.AccessToken, AccessTokenExpires = Config.AccessTokenExpires @@ -121,19 +120,7 @@ namespace GreenshotBoxPlugin { /// A simple helper class for the DataContractJsonSerializer /// internal static class JsonSerializer { - /// - /// Helper method to serialize object to JSON - /// - /// JSON object - /// string - public static string Serialize(object jsonObject) { - var serializer = new DataContractJsonSerializer(jsonObject.GetType()); - using MemoryStream stream = new MemoryStream(); - serializer.WriteObject(stream, jsonObject); - return Encoding.UTF8.GetString(stream.ToArray()); - } - - /// + /// /// Helper method to parse JSON to object /// /// @@ -141,7 +128,7 @@ namespace GreenshotBoxPlugin { /// public static T Deserialize(string jsonString) { var deserializer = new DataContractJsonSerializer(typeof(T)); - using MemoryStream stream = new MemoryStream(); + using var stream = new MemoryStream(); byte[] content = Encoding.UTF8.GetBytes(jsonString); stream.Write(content, 0, content.Length); stream.Seek(0, SeekOrigin.Begin); diff --git a/GreenshotBoxPlugin/GreenshotBoxPlugin.Credentials.template b/GreenshotBoxPlugin/GreenshotBoxPlugin.Credentials.template index 9ad35eced..72cfa4b79 100644 --- a/GreenshotBoxPlugin/GreenshotBoxPlugin.Credentials.template +++ b/GreenshotBoxPlugin/GreenshotBoxPlugin.Credentials.template @@ -25,7 +25,7 @@ namespace GreenshotBoxPlugin { /// You can set your own values here /// public static class BoxCredentials { - public static string ClientId = "${Box_ClientId}"; - public static string ClientSecret = "${Box_ClientSecret}"; + public static string ClientId = "${Box13_ClientId}"; + public static string ClientSecret = "${Box13_ClientSecret}"; } } diff --git a/GreenshotBoxPlugin/LanguageKeys.cs b/GreenshotBoxPlugin/LanguageKeys.cs index 6e757a01d..5d2491ae3 100644 --- a/GreenshotBoxPlugin/LanguageKeys.cs +++ b/GreenshotBoxPlugin/LanguageKeys.cs @@ -21,13 +21,8 @@ namespace GreenshotBoxPlugin { public enum LangKey { upload_menu_item, - settings_title, - label_upload_format, - upload_success, upload_failure, communication_wait, - Configure, - label_AfterUpload, - label_AfterUploadLinkToClipBoard + Configure } } diff --git a/GreenshotConfluencePlugin/EnumDisplayer.cs b/GreenshotConfluencePlugin/EnumDisplayer.cs index 84ca2925e..5358362ef 100644 --- a/GreenshotConfluencePlugin/EnumDisplayer.cs +++ b/GreenshotConfluencePlugin/EnumDisplayer.cs @@ -33,15 +33,8 @@ namespace GreenshotConfluencePlugin { private Type _type; private IDictionary _displayValues; private IDictionary _reverseValues; - - public EnumDisplayer() { - } - - public EnumDisplayer(Type type) { - Type = type; - } - - public Type Type { + + public Type Type { get { return _type; } set { if (!value.IsEnum) { diff --git a/GreenshotConfluencePlugin/Forms/ListViewColumnSorter.cs b/GreenshotConfluencePlugin/Forms/ListViewColumnSorter.cs deleted file mode 100644 index d4cbe59d4..000000000 --- a/GreenshotConfluencePlugin/Forms/ListViewColumnSorter.cs +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Collections; -using System.Windows.Forms; - -namespace GreenshotConfluencePlugin.Forms -{ - /// - /// This class is an implementation of the 'IComparer' interface. - /// - public class ListViewColumnSorter : IComparer { - /// - /// Specifies the column to be sorted - /// - private int _columnToSort; - /// - /// Specifies the order in which to sort (i.e. 'Ascending'). - /// - private SortOrder _orderOfSort; - /// - /// Case insensitive comparer object - /// - private readonly CaseInsensitiveComparer _objectCompare; - - /// - /// Class constructor. Initializes various elements - /// - public ListViewColumnSorter() { - // Initialize the column to '0' - _columnToSort = 0; - - // Initialize the sort order to 'none' - _orderOfSort = SortOrder.None; - - // Initialize the CaseInsensitiveComparer object - _objectCompare = new CaseInsensitiveComparer(); - } - - /// - /// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison. - /// - /// First object to be compared - /// Second object to be compared - /// The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y' - public int Compare(object x, object y) { - int compareResult; - ListViewItem listviewX, listviewY; - - // Cast the objects to be compared to ListViewItem objects - listviewX = (ListViewItem)x; - listviewY = (ListViewItem)y; - - // Compare the two items - compareResult = _objectCompare.Compare(listviewX.SubItems[_columnToSort].Text, listviewY.SubItems[_columnToSort].Text); - - // Calculate correct return value based on object comparison - if (_orderOfSort == SortOrder.Ascending) { - // Ascending sort is selected, return normal result of compare operation - return compareResult; - } else if (_orderOfSort == SortOrder.Descending) { - // Descending sort is selected, return negative result of compare operation - return (-compareResult); - } else { - // Return '0' to indicate they are equal - return 0; - } - } - - /// - /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0'). - /// - public int SortColumn { - set { - _columnToSort = value; - } - get { - return _columnToSort; - } - } - - /// - /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending'). - /// - public SortOrder Order { - set { - _orderOfSort = value; - } - get { - return _orderOfSort; - } - } - - } -} diff --git a/GreenshotConfluencePlugin/LanguageKeys.cs b/GreenshotConfluencePlugin/LanguageKeys.cs index 9cd71ea8e..5ba0b2cbe 100644 --- a/GreenshotConfluencePlugin/LanguageKeys.cs +++ b/GreenshotConfluencePlugin/LanguageKeys.cs @@ -22,14 +22,7 @@ namespace GreenshotConfluencePlugin { public enum LangKey { login_error, - login_title, - label_url, - label_upload_format, - OK, - CANCEL, upload_menu_item, - upload_success, - upload_failure, communication_wait } } diff --git a/GreenshotConfluencePlugin/Support/TranslationManager.cs b/GreenshotConfluencePlugin/Support/TranslationManager.cs index 241cce868..472f2e27d 100644 --- a/GreenshotConfluencePlugin/Support/TranslationManager.cs +++ b/GreenshotConfluencePlugin/Support/TranslationManager.cs @@ -29,12 +29,7 @@ namespace GreenshotConfluencePlugin.Support { public ITranslationProvider TranslationProvider { get; set; } - private void OnLanguageChanged() - { - LanguageChanged?.Invoke(this, EventArgs.Empty); - } - - public object Translate(string key) { + public object Translate(string key) { object translatedValue = TranslationProvider?.Translate(key); if( translatedValue != null) { return translatedValue; diff --git a/GreenshotDropboxPlugin/DropboxDestination.cs b/GreenshotDropboxPlugin/DropboxDestination.cs index 57d0a1326..9762652c4 100644 --- a/GreenshotDropboxPlugin/DropboxDestination.cs +++ b/GreenshotDropboxPlugin/DropboxDestination.cs @@ -1,20 +1,20 @@ /* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel - * + * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * + * (at your option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,7 +32,7 @@ namespace GreenshotDropboxPlugin { public DropboxDestination(DropboxPlugin plugin) { _plugin = plugin; } - + public override string Designation => "Dropbox"; public override string Description => Language.GetString("dropbox", LangKey.upload_menu_item); @@ -43,10 +43,10 @@ namespace GreenshotDropboxPlugin { return (Image)resources.GetObject("Dropbox"); } } - + public override ExportInformation ExportCapture(bool manually, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(Designation, Description); - bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl); + bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl); if (uploaded) { exportInformation.Uri = uploadUrl; exportInformation.ExportMade = true; diff --git a/GreenshotDropboxPlugin/DropboxPlugin.cs b/GreenshotDropboxPlugin/DropboxPlugin.cs index 0d3ca827d..2977c2d36 100644 --- a/GreenshotDropboxPlugin/DropboxPlugin.cs +++ b/GreenshotDropboxPlugin/DropboxPlugin.cs @@ -1,27 +1,26 @@ /* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel - * + * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.ComponentModel; using System.Drawing; -using System.IO; using System.Windows.Forms; using GreenshotPlugin.Controls; using GreenshotPlugin.Core; @@ -45,13 +44,12 @@ namespace GreenshotDropboxPlugin { GC.SuppressFinalize(this); } - protected void Dispose(bool disposing) { - if (disposing) { - if (_itemPlugInConfig != null) { - _itemPlugInConfig.Dispose(); - _itemPlugInConfig = null; - } - } + private void Dispose(bool disposing) + { + if (!disposing) return; + if (_itemPlugInConfig == null) return; + _itemPlugInConfig.Dispose(); + _itemPlugInConfig = null; } /// @@ -102,20 +100,16 @@ namespace GreenshotDropboxPlugin { public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) { uploadUrl = null; SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false); - try { - string dropboxUrl = null; - new PleaseWaitForm().ShowAndWait("Dropbox", Language.GetString("dropbox", LangKey.communication_wait), + try + { + bool result = false; + new PleaseWaitForm().ShowAndWait("Dropbox", Language.GetString("dropbox", LangKey.communication_wait), delegate { - string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails)); - dropboxUrl = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, filename); + result = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, captureDetails); } ); - if (dropboxUrl == null) { - return false; - } - uploadUrl = dropboxUrl; - return true; + return result; } catch (Exception e) { Log.Error(e); MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message); diff --git a/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs b/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs index 52baabdef..b13622db2 100644 --- a/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs +++ b/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs @@ -1,23 +1,25 @@ /* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel - * + * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using System; using System.Windows.Forms; using GreenshotDropboxPlugin.Forms; using GreenshotPlugin.Core; @@ -39,10 +41,18 @@ namespace GreenshotDropboxPlugin { [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Dropbox link to clipboard.", DefaultValue = "true")] public bool AfterUploadLinkToClipBoard { get; set; } - [IniProperty("DropboxToken", Description = "The Dropbox token", Encrypted = true, ExcludeIfNull = true)] - public string DropboxToken { get; set; } - [IniProperty("DropboxTokenSecret", Description = "The Dropbox token secret", Encrypted = true, ExcludeIfNull = true)] - public string DropboxTokenSecret { get; set; } + [IniProperty("RefreshToken", Description = "Dropbox refresh Token", Encrypted = true, ExcludeIfNull = true)] + public string RefreshToken { get; set; } + + /// + /// AccessToken, not stored + /// + public string AccessToken { get; set; } + + /// + /// AccessTokenExpires, not stored + /// + public DateTimeOffset AccessTokenExpires { get; set; } /// /// A form for token diff --git a/GreenshotDropboxPlugin/DropboxUtils.cs b/GreenshotDropboxPlugin/DropboxUtils.cs index 717b41fe3..8bf1d57b5 100644 --- a/GreenshotDropboxPlugin/DropboxUtils.cs +++ b/GreenshotDropboxPlugin/DropboxUtils.cs @@ -1,30 +1,32 @@ /* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel - * + * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.Collections.Generic; -using System.Drawing; +using System.IO; using GreenshotPlugin.Core; +using GreenshotPlugin.Core.OAuth; using GreenshotPlugin.IniFile; using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces.Plugin; +using Newtonsoft.Json; namespace GreenshotDropboxPlugin { /// @@ -37,49 +39,54 @@ namespace GreenshotDropboxPlugin { private DropboxUtils() { } - public static string UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string filename) { - var oAuth = new OAuthSession(DropBoxCredentials.CONSUMER_KEY, DropBoxCredentials.CONSUMER_SECRET) - { - BrowserSize = new Size(1080, 650), - CheckVerifier = false, - AccessTokenUrl = "https://api.dropbox.com/1/oauth/access_token", - AuthorizeUrl = "https://api.dropbox.com/1/oauth/authorize", - RequestTokenUrl = "https://api.dropbox.com/1/oauth/request_token", - LoginTitle = "Dropbox authorization", - Token = DropboxConfig.DropboxToken, - TokenSecret = DropboxConfig.DropboxTokenSecret + public static bool UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, ICaptureDetails captureDetails) + { + var oauth2Settings = new OAuth2Settings + { + AuthUrlPattern = "https://api.dropbox.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}&redirect_uri={RedirectUrl}", + TokenUrl = "https://api.dropbox.com/oauth2/token", + RedirectUrl = "https://getgreenshot.org/authorize/dropbox", + CloudServiceName = "Dropbox", + ClientId = DropBoxCredentials.CONSUMER_KEY, + ClientSecret = DropBoxCredentials.CONSUMER_SECRET, + AuthorizeMode = OAuth2AuthorizeMode.JsonReceiver, + RefreshToken = DropboxConfig.RefreshToken, + AccessToken = DropboxConfig.AccessToken, + AccessTokenExpires = DropboxConfig.AccessTokenExpires }; + try + { + string filename = Path.GetFileName(FilenameHelper.GetFilename(DropboxConfig.UploadFormat, captureDetails)); + SurfaceContainer image = new SurfaceContainer(surfaceToUpload, outputSettings, filename); - try { - SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename); - string uploadResponse = oAuth.MakeOAuthRequest(HTTPMethod.POST, "https://api-content.dropbox.com/1/files_put/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, imageToUpload); - Log.DebugFormat("Upload response: {0}", uploadResponse); - } catch (Exception ex) { + IDictionary arguments = new Dictionary + { + { "autorename", true }, + { "mute", true }, + { "path", "/" + filename.Replace(Path.DirectorySeparatorChar, '\\')} + }; + IDictionary headers = new Dictionary + { + { "Dropbox-API-Arg", JsonConvert.SerializeObject(arguments)} + }; + var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, "https://content.dropboxapi.com/2/files/upload", oauth2Settings); + + NetworkHelper.Post(webRequest, headers, image); + var responseString = NetworkHelper.GetResponseAsString(webRequest); + Log.DebugFormat("Upload response: {0}", responseString); + var response = JsonConvert.DeserializeObject>(responseString); + return response.ContainsKey("id"); + } + catch (Exception ex) { Log.Error("Upload error: ", ex); throw; } finally { - if (!string.IsNullOrEmpty(oAuth.Token)) { - DropboxConfig.DropboxToken = oAuth.Token; - } - if (!string.IsNullOrEmpty(oAuth.TokenSecret)) { - DropboxConfig.DropboxTokenSecret = oAuth.TokenSecret; - } - } - - // Try to get a URL to the uploaded image - try { - string responseString = oAuth.MakeOAuthRequest(HTTPMethod.GET, "https://api.dropbox.com/1/shares/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, null); - if (responseString != null) { - Log.DebugFormat("Parsing output: {0}", responseString); - IDictionary returnValues = JSONHelper.JsonDecode(responseString); - if (returnValues.ContainsKey("url")) { - return returnValues["url"] as string; - } - } - } catch (Exception ex) { - Log.Error("Can't parse response.", ex); - } - return null; + DropboxConfig.RefreshToken = oauth2Settings.RefreshToken; + DropboxConfig.AccessToken = oauth2Settings.AccessToken; + DropboxConfig.AccessTokenExpires = oauth2Settings.AccessTokenExpires; + DropboxConfig.IsDirty = true; + IniConfig.Save(); + } } } } diff --git a/GreenshotDropboxPlugin/GreenshotDropboxPlugin.Credentials.template b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.Credentials.template index 6a13eb6d7..f674f1bb7 100644 --- a/GreenshotDropboxPlugin/GreenshotDropboxPlugin.Credentials.template +++ b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.Credentials.template @@ -25,7 +25,7 @@ namespace GreenshotDropboxPlugin { /// You can set your own values here /// public static class DropBoxCredentials { - public static string CONSUMER_KEY = "${DropBox_ClientId}"; - public static string CONSUMER_SECRET = "${DropBox_ClientSecret}"; + public static string CONSUMER_KEY = "${DropBox13_ClientId}"; + public static string CONSUMER_SECRET = "${DropBox13_ClientSecret}"; } } diff --git a/GreenshotDropboxPlugin/LanguageKeys.cs b/GreenshotDropboxPlugin/LanguageKeys.cs index d50660add..0b1ae489e 100644 --- a/GreenshotDropboxPlugin/LanguageKeys.cs +++ b/GreenshotDropboxPlugin/LanguageKeys.cs @@ -21,13 +21,8 @@ namespace GreenshotDropboxPlugin { public enum LangKey { upload_menu_item, - settings_title, - label_upload_format, - upload_success, upload_failure, communication_wait, - Configure, - label_AfterUpload, - label_AfterUploadLinkToClipBoard - } + Configure + } } diff --git a/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs b/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs index 13d1868d1..9389705b8 100644 --- a/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs +++ b/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs @@ -29,134 +29,158 @@ using GreenshotPlugin.IniFile; using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces.Plugin; -namespace GreenshotExternalCommandPlugin { - /// - /// An Plugin to run commands after an image was written - /// +namespace GreenshotExternalCommandPlugin +{ + /// + /// An Plugin to run commands after an image was written + /// [Plugin("ExternalCommand", true)] - public class ExternalCommandPlugin : IGreenshotPlugin { - private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ExternalCommandPlugin)); - private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); - private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection(); - private ToolStripMenuItem _itemPlugInRoot; + public class ExternalCommandPlugin : IGreenshotPlugin + { + private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ExternalCommandPlugin)); + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection(); + private ToolStripMenuItem _itemPlugInRoot; - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } - protected virtual void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { if (!disposing) return; if (_itemPlugInRoot == null) return; _itemPlugInRoot.Dispose(); _itemPlugInRoot = null; } - private IEnumerable Destinations() { - foreach(string command in ExternalCommandConfig.Commands) { - yield return new ExternalCommandDestination(command); - } - } + private IEnumerable Destinations() + { + foreach (string command in ExternalCommandConfig.Commands) + { + yield return new ExternalCommandDestination(command); + } + } - /// - /// Check and eventually fix the command settings - /// - /// - /// false if the command is not correctly configured - private bool IsCommandValid(string command) { - if (!ExternalCommandConfig.RunInbackground.ContainsKey(command)) { - Log.WarnFormat("Found missing runInbackground for {0}", command); - // Fix it - ExternalCommandConfig.RunInbackground.Add(command, true); - } - if (!ExternalCommandConfig.Argument.ContainsKey(command)) { - Log.WarnFormat("Found missing argument for {0}", command); - // Fix it - ExternalCommandConfig.Argument.Add(command, "{0}"); - } - if (!ExternalCommandConfig.Commandline.ContainsKey(command)) { - Log.WarnFormat("Found missing commandline for {0}", command); - return false; - } - string commandline = FilenameHelper.FillVariables(ExternalCommandConfig.Commandline[command], true); - commandline = FilenameHelper.FillCmdVariables(commandline, true); + /// + /// Check and eventually fix the command settings + /// + /// + /// false if the command is not correctly configured + private bool IsCommandValid(string command) + { + if (!ExternalCommandConfig.RunInbackground.ContainsKey(command)) + { + Log.WarnFormat("Found missing runInbackground for {0}", command); + // Fix it + ExternalCommandConfig.RunInbackground.Add(command, true); + } + if (!ExternalCommandConfig.Argument.ContainsKey(command)) + { + Log.WarnFormat("Found missing argument for {0}", command); + // Fix it + ExternalCommandConfig.Argument.Add(command, "{0}"); + } + if (!ExternalCommandConfig.Commandline.ContainsKey(command)) + { + Log.WarnFormat("Found missing commandline for {0}", command); + return false; + } + string commandline = FilenameHelper.FillVariables(ExternalCommandConfig.Commandline[command], true); + commandline = FilenameHelper.FillCmdVariables(commandline, true); - if (!File.Exists(commandline)) { - Log.WarnFormat("Found 'invalid' commandline {0} for command {1}", ExternalCommandConfig.Commandline[command], command); - return false; - } + if (!File.Exists(commandline)) + { + Log.WarnFormat("Found 'invalid' commandline {0} for command {1}", ExternalCommandConfig.Commandline[command], command); + return false; + } + return true; + } + /// + /// Implementation of the IGreenshotPlugin.Initialize + /// + public virtual bool Initialize() + { + Log.DebugFormat("Initialize called"); + + var commandsToDelete = new List(); + // Check configuration + foreach (string command in ExternalCommandConfig.Commands) + { + if (!IsCommandValid(command)) + { + commandsToDelete.Add(command); + } + } + // cleanup + foreach (string command in commandsToDelete) + { + ExternalCommandConfig.Delete(command); + } SimpleServiceProvider.Current.AddService(Destinations()); - return true; - } - /// - /// Implementation of the IGreenshotPlugin.Initialize - /// - public virtual bool Initialize() { - Log.DebugFormat("Initialize called"); - List commandsToDelete = new List(); - // Check configuration - foreach(string command in ExternalCommandConfig.Commands) { - if (!IsCommandValid(command)) { - commandsToDelete.Add(command); - } - } - - // cleanup - foreach (string command in commandsToDelete) { - ExternalCommandConfig.Delete(command); - } - - _itemPlugInRoot = new ToolStripMenuItem(); + _itemPlugInRoot = new ToolStripMenuItem(); _itemPlugInRoot.Click += ConfigMenuClick; - OnIconSizeChanged(this, new PropertyChangedEventArgs("IconSize")); - OnLanguageChanged(this, null); + OnIconSizeChanged(this, new PropertyChangedEventArgs("IconSize")); + OnLanguageChanged(this, null); - PluginUtils.AddToContextMenu(_itemPlugInRoot); - Language.LanguageChanged += OnLanguageChanged; - CoreConfig.PropertyChanged += OnIconSizeChanged; - return true; - } + PluginUtils.AddToContextMenu(_itemPlugInRoot); + Language.LanguageChanged += OnLanguageChanged; + CoreConfig.PropertyChanged += OnIconSizeChanged; + return true; + } - /// - /// Fix icon reference - /// - /// - /// - private void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "IconSize") { - try { - string exePath = PluginUtils.GetExePath("cmd.exe"); - if (exePath != null && File.Exists(exePath)) { - _itemPlugInRoot.Image = PluginUtils.GetCachedExeIcon(exePath, 0); - } - } catch (Exception ex) { - Log.Warn("Couldn't get the cmd.exe image", ex); - } - } - } + /// + /// Fix icon reference + /// + /// + /// + private void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == "IconSize") + { + try + { + string exePath = PluginUtils.GetExePath("cmd.exe"); + if (exePath != null && File.Exists(exePath)) + { + _itemPlugInRoot.Image = PluginUtils.GetCachedExeIcon(exePath, 0); + } + } + catch (Exception ex) + { + Log.Warn("Couldn't get the cmd.exe image", ex); + } + } + } - private void OnLanguageChanged(object sender, EventArgs e) { - if (_itemPlugInRoot != null) { - _itemPlugInRoot.Text = Language.GetString("externalcommand", "contextmenu_configure"); - } - } + private void OnLanguageChanged(object sender, EventArgs e) + { + if (_itemPlugInRoot != null) + { + _itemPlugInRoot.Text = Language.GetString("externalcommand", "contextmenu_configure"); + } + } - public virtual void Shutdown() { - Log.Debug("Shutdown"); - } + public virtual void Shutdown() + { + Log.Debug("Shutdown"); + } - private void ConfigMenuClick(object sender, EventArgs eventArgs) { - Configure(); - } + private void ConfigMenuClick(object sender, EventArgs eventArgs) + { + Configure(); + } - /// - /// Implementation of the IPlugin.Configure - /// - public virtual void Configure() { - Log.Debug("Configure called"); - new SettingsForm().ShowDialog(); - } - } + /// + /// Implementation of the IPlugin.Configure + /// + public virtual void Configure() + { + Log.Debug("Configure called"); + new SettingsForm().ShowDialog(); + } + } } \ No newline at end of file diff --git a/GreenshotFlickrPlugin/FlickrUtils.cs b/GreenshotFlickrPlugin/FlickrUtils.cs index 6713e3702..9337c51f6 100644 --- a/GreenshotFlickrPlugin/FlickrUtils.cs +++ b/GreenshotFlickrPlugin/FlickrUtils.cs @@ -24,6 +24,7 @@ using System.Collections.Generic; using System.Drawing; using System.Xml; using GreenshotPlugin.Core; +using GreenshotPlugin.Core.OAuth; using GreenshotPlugin.IniFile; using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces.Plugin; diff --git a/GreenshotFlickrPlugin/LanguageKeys.cs b/GreenshotFlickrPlugin/LanguageKeys.cs index 44320512b..ae3a6af02 100644 --- a/GreenshotFlickrPlugin/LanguageKeys.cs +++ b/GreenshotFlickrPlugin/LanguageKeys.cs @@ -21,15 +21,8 @@ namespace GreenshotFlickrPlugin { public enum LangKey { upload_menu_item, - settings_title, - label_upload_format, - upload_success, upload_failure, communication_wait, - Configure, - label_HiddenFromSearch, - label_SafetyLevel, - label_AfterUpload, - label_AfterUploadLinkToClipBoard - } + Configure + } } diff --git a/GreenshotPicasaPlugin/Forms/PicasaForm.cs b/GreenshotGooglePhotosPlugin/Forms/GooglePhotosForm.cs similarity index 85% rename from GreenshotPicasaPlugin/Forms/PicasaForm.cs rename to GreenshotGooglePhotosPlugin/Forms/GooglePhotosForm.cs index cea5a2f35..10b18bebe 100644 --- a/GreenshotPicasaPlugin/Forms/PicasaForm.cs +++ b/GreenshotGooglePhotosPlugin/Forms/GooglePhotosForm.cs @@ -1,5 +1,5 @@ /* - * A Picasa Plugin for Greenshot + * A GooglePhotos Plugin for Greenshot * Copyright (C) 2011 Francis Noel * * For more information see: http://getgreenshot.org/ @@ -20,7 +20,7 @@ using GreenshotPlugin.Controls; -namespace GreenshotPicasaPlugin.Forms { - public class PicasaForm : GreenshotForm { +namespace GreenshotGooglePhotosPlugin.Forms { + public class GooglePhotosForm : GreenshotForm { } } diff --git a/GreenshotPicasaPlugin/Forms/SettingsForm.Designer.cs b/GreenshotGooglePhotosPlugin/Forms/SettingsForm.Designer.cs similarity index 91% rename from GreenshotPicasaPlugin/Forms/SettingsForm.Designer.cs rename to GreenshotGooglePhotosPlugin/Forms/SettingsForm.Designer.cs index 38555c179..cea2b6acf 100644 --- a/GreenshotPicasaPlugin/Forms/SettingsForm.Designer.cs +++ b/GreenshotGooglePhotosPlugin/Forms/SettingsForm.Designer.cs @@ -1,147 +1,147 @@ -/* - * A Picasa Plugin for Greenshot - * Copyright (C) 2011 Francis Noel - * - * For more information see: http://getgreenshot.org/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -namespace GreenshotPicasaPlugin.Forms { - partial class SettingsForm { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); - this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); - this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel(); - this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.SuspendLayout(); - // - // buttonOK - // - this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonOK.LanguageKey = "OK"; - this.buttonOK.Location = new System.Drawing.Point(267, 78); - this.buttonOK.Name = "buttonOK"; - this.buttonOK.Size = new System.Drawing.Size(75, 23); - this.buttonOK.TabIndex = 10; - this.buttonOK.UseVisualStyleBackColor = true; - // - // buttonCancel - // - this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonCancel.LanguageKey = "CANCEL"; - this.buttonCancel.Location = new System.Drawing.Point(348, 78); - this.buttonCancel.Name = "buttonCancel"; - this.buttonCancel.Size = new System.Drawing.Size(75, 23); - this.buttonCancel.TabIndex = 11; - this.buttonCancel.UseVisualStyleBackColor = true; - // - // combobox_uploadimageformat - // - this.combobox_uploadimageformat.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.combobox_uploadimageformat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.combobox_uploadimageformat.FormattingEnabled = true; - this.combobox_uploadimageformat.Location = new System.Drawing.Point(197, 12); - this.combobox_uploadimageformat.Name = "combobox_uploadimageformat"; - this.combobox_uploadimageformat.PropertyName = "UploadFormat"; - this.combobox_uploadimageformat.SectionName = "Picasa"; - this.combobox_uploadimageformat.Size = new System.Drawing.Size(225, 21); - this.combobox_uploadimageformat.TabIndex = 1; - // - // label_upload_format - // - this.label_upload_format.LanguageKey = "picasa.label_upload_format"; - this.label_upload_format.Location = new System.Drawing.Point(10, 18); - this.label_upload_format.Name = "label_upload_format"; - this.label_upload_format.Size = new System.Drawing.Size(181, 33); - this.label_upload_format.TabIndex = 4; - // - // label_AfterUpload - // - this.label_AfterUpload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.label_AfterUpload.LanguageKey = "picasa.label_AfterUpload"; - this.label_AfterUpload.Location = new System.Drawing.Point(10, 51); - this.label_AfterUpload.Name = "label_AfterUpload"; - this.label_AfterUpload.Size = new System.Drawing.Size(181, 29); - this.label_AfterUpload.TabIndex = 8; - // - // checkboxAfterUploadLinkToClipBoard - // - this.checkboxAfterUploadLinkToClipBoard.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "picasa.label_AfterUploadLinkToClipBoard"; - this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(197, 50); - this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard"; - this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard"; - this.checkboxAfterUploadLinkToClipBoard.SectionName = "Picasa"; - this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17); - this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2; - this.checkboxAfterUploadLinkToClipBoard.UseVisualStyleBackColor = true; - // - // SettingsForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(432, 110); - this.Controls.Add(this.checkboxAfterUploadLinkToClipBoard); - this.Controls.Add(this.label_AfterUpload); - this.Controls.Add(this.label_upload_format); - this.Controls.Add(this.combobox_uploadimageformat); - this.Controls.Add(this.buttonCancel); - this.Controls.Add(this.buttonOK); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.LanguageKey = "picasa.settings_title"; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "SettingsForm"; - this.ResumeLayout(false); - this.PerformLayout(); - - } - private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; - private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload; - private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; - } -} +/* + * A GooglePhotos Plugin for Greenshot + * Copyright (C) 2011 Francis Noel + * + * For more information see: http://getgreenshot.org/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +namespace GreenshotGooglePhotosPlugin.Forms { + partial class SettingsForm { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); + this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); + this.combobox_uploadimageformat = new GreenshotPlugin.Controls.GreenshotComboBox(); + this.label_upload_format = new GreenshotPlugin.Controls.GreenshotLabel(); + this.label_AfterUpload = new GreenshotPlugin.Controls.GreenshotLabel(); + this.checkboxAfterUploadLinkToClipBoard = new GreenshotPlugin.Controls.GreenshotCheckBox(); + this.SuspendLayout(); + // + // buttonOK + // + this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonOK.LanguageKey = "OK"; + this.buttonOK.Location = new System.Drawing.Point(267, 78); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.Size = new System.Drawing.Size(75, 23); + this.buttonOK.TabIndex = 10; + this.buttonOK.UseVisualStyleBackColor = true; + // + // buttonCancel + // + this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.LanguageKey = "CANCEL"; + this.buttonCancel.Location = new System.Drawing.Point(348, 78); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 11; + this.buttonCancel.UseVisualStyleBackColor = true; + // + // combobox_uploadimageformat + // + this.combobox_uploadimageformat.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.combobox_uploadimageformat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.combobox_uploadimageformat.FormattingEnabled = true; + this.combobox_uploadimageformat.Location = new System.Drawing.Point(197, 12); + this.combobox_uploadimageformat.Name = "combobox_uploadimageformat"; + this.combobox_uploadimageformat.PropertyName = "UploadFormat"; + this.combobox_uploadimageformat.SectionName = "GooglePhotos"; + this.combobox_uploadimageformat.Size = new System.Drawing.Size(225, 21); + this.combobox_uploadimageformat.TabIndex = 1; + // + // label_upload_format + // + this.label_upload_format.LanguageKey = "googlephotos.label_upload_format"; + this.label_upload_format.Location = new System.Drawing.Point(10, 18); + this.label_upload_format.Name = "label_upload_format"; + this.label_upload_format.Size = new System.Drawing.Size(181, 33); + this.label_upload_format.TabIndex = 4; + // + // label_AfterUpload + // + this.label_AfterUpload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label_AfterUpload.LanguageKey = "googlephotos.label_AfterUpload"; + this.label_AfterUpload.Location = new System.Drawing.Point(10, 51); + this.label_AfterUpload.Name = "label_AfterUpload"; + this.label_AfterUpload.Size = new System.Drawing.Size(181, 29); + this.label_AfterUpload.TabIndex = 8; + // + // checkboxAfterUploadLinkToClipBoard + // + this.checkboxAfterUploadLinkToClipBoard.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.checkboxAfterUploadLinkToClipBoard.LanguageKey = "googlephotos.label_AfterUploadLinkToClipBoard"; + this.checkboxAfterUploadLinkToClipBoard.Location = new System.Drawing.Point(197, 50); + this.checkboxAfterUploadLinkToClipBoard.Name = "checkboxAfterUploadLinkToClipBoard"; + this.checkboxAfterUploadLinkToClipBoard.PropertyName = "AfterUploadLinkToClipBoard"; + this.checkboxAfterUploadLinkToClipBoard.SectionName = "GooglePhotos"; + this.checkboxAfterUploadLinkToClipBoard.Size = new System.Drawing.Size(104, 17); + this.checkboxAfterUploadLinkToClipBoard.TabIndex = 2; + this.checkboxAfterUploadLinkToClipBoard.UseVisualStyleBackColor = true; + // + // SettingsForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(432, 110); + this.Controls.Add(this.checkboxAfterUploadLinkToClipBoard); + this.Controls.Add(this.label_AfterUpload); + this.Controls.Add(this.label_upload_format); + this.Controls.Add(this.combobox_uploadimageformat); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonOK); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.LanguageKey = "googlephotos.settings_title"; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SettingsForm"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + private GreenshotPlugin.Controls.GreenshotComboBox combobox_uploadimageformat; + private GreenshotPlugin.Controls.GreenshotLabel label_upload_format; + private GreenshotPlugin.Controls.GreenshotButton buttonCancel; + private GreenshotPlugin.Controls.GreenshotButton buttonOK; + private GreenshotPlugin.Controls.GreenshotLabel label_AfterUpload; + private GreenshotPlugin.Controls.GreenshotCheckBox checkboxAfterUploadLinkToClipBoard; + } +} diff --git a/GreenshotPicasaPlugin/Forms/SettingsForm.cs b/GreenshotGooglePhotosPlugin/Forms/SettingsForm.cs similarity index 86% rename from GreenshotPicasaPlugin/Forms/SettingsForm.cs rename to GreenshotGooglePhotosPlugin/Forms/SettingsForm.cs index a6691a424..be31f1d44 100644 --- a/GreenshotPicasaPlugin/Forms/SettingsForm.cs +++ b/GreenshotGooglePhotosPlugin/Forms/SettingsForm.cs @@ -1,38 +1,38 @@ -/* - * A Picasa Plugin for Greenshot - * Copyright (C) 2011 Francis Noel - * - * For more information see: http://getgreenshot.org/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotPicasaPlugin.Forms { - /// - /// Description of PasswordRequestForm. - /// - public partial class SettingsForm : PicasaForm { - - public SettingsForm() - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - CancelButton = buttonCancel; - AcceptButton = buttonOK; - } - - } -} +/* + * A GooglePhotos Plugin for Greenshot + * Copyright (C) 2011 Francis Noel + * + * For more information see: http://getgreenshot.org/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +namespace GreenshotGooglePhotosPlugin.Forms { + /// + /// Description of PasswordRequestForm. + /// + public partial class SettingsForm : GooglePhotosForm { + + public SettingsForm() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + CancelButton = buttonCancel; + AcceptButton = buttonOK; + } + + } +} diff --git a/GreenshotGooglePhotosPlugin/GooglePhotos.png b/GreenshotGooglePhotosPlugin/GooglePhotos.png new file mode 100644 index 000000000..ea7824f9d Binary files /dev/null and b/GreenshotGooglePhotosPlugin/GooglePhotos.png differ diff --git a/GreenshotPicasaPlugin/PicasaConfiguration.cs b/GreenshotGooglePhotosPlugin/GooglePhotosConfiguration.cs similarity index 72% rename from GreenshotPicasaPlugin/PicasaConfiguration.cs rename to GreenshotGooglePhotosPlugin/GooglePhotosConfiguration.cs index 202929459..7e1b614b2 100644 --- a/GreenshotPicasaPlugin/PicasaConfiguration.cs +++ b/GreenshotGooglePhotosPlugin/GooglePhotosConfiguration.cs @@ -1,93 +1,93 @@ -/* - * A Picasa Plugin for Greenshot - * Copyright (C) 2011 Francis Noel - * - * For more information see: http://getgreenshot.org/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -using System.Windows.Forms; -using GreenshotPlugin.Core; -using System; -using GreenshotPicasaPlugin.Forms; -using GreenshotPlugin.IniFile; - -namespace GreenshotPicasaPlugin { - /// - /// Description of PicasaConfiguration. - /// - [IniSection("Picasa", Description = "Greenshot Picasa Plugin configuration")] - public class PicasaConfiguration : IniSection { - [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] - public OutputFormat UploadFormat { get; set; } - - [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] - public int UploadJpegQuality { get; set; } - - [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Picasa link to clipboard.", DefaultValue = "true")] - public bool AfterUploadLinkToClipBoard { get; set; } - [IniProperty("AddFilename", Description = "Is the filename passed on to Picasa", DefaultValue = "False")] - public bool AddFilename { - get; - set; - } - - [IniProperty("UploadUser", Description = "The Picasa user to upload to", DefaultValue = "default")] - public string UploadUser { - get; - set; - } - - [IniProperty("UploadAlbum", Description = "The Picasa album to upload to", DefaultValue = "default")] - public string UploadAlbum { - get; - set; - } - - [IniProperty("RefreshToken", Description = "Picasa authorization refresh Token", Encrypted = true)] - public string RefreshToken { - get; - set; - } - - /// - /// Not stored - /// - public string AccessToken { - get; - set; - } - - /// - /// Not stored - /// - public DateTimeOffset AccessTokenExpires { - get; - set; - } - - /// - /// A form for token - /// - /// bool true if OK was pressed, false if cancel - public bool ShowConfigDialog() { - DialogResult result = new SettingsForm().ShowDialog(); - if (result == DialogResult.OK) { - return true; - } - return false; - } - - } -} +/* + * A GooglePhotos Plugin for Greenshot + * Copyright (C) 2011 Francis Noel + * + * For more information see: http://getgreenshot.org/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System.Windows.Forms; +using GreenshotPlugin.Core; +using System; +using GreenshotGooglePhotosPlugin.Forms; +using GreenshotPlugin.IniFile; + +namespace GreenshotGooglePhotosPlugin { + /// + /// Description of GooglePhotosConfiguration. + /// + [IniSection("GooglePhotos", Description = "Greenshot GooglePhotos Plugin configuration")] + public class GooglePhotosConfiguration : IniSection { + [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] + public OutputFormat UploadFormat { get; set; } + + [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] + public int UploadJpegQuality { get; set; } + + [IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send GooglePhotos link to clipboard.", DefaultValue = "true")] + public bool AfterUploadLinkToClipBoard { get; set; } + [IniProperty("AddFilename", Description = "Is the filename passed on to GooglePhotos", DefaultValue = "False")] + public bool AddFilename { + get; + set; + } + + [IniProperty("UploadUser", Description = "The GooglePhotos user to upload to", DefaultValue = "default")] + public string UploadUser { + get; + set; + } + + [IniProperty("UploadAlbum", Description = "The GooglePhotos album to upload to", DefaultValue = "default")] + public string UploadAlbum { + get; + set; + } + + [IniProperty("RefreshToken", Description = "GooglePhotos authorization refresh Token", Encrypted = true)] + public string RefreshToken { + get; + set; + } + + /// + /// Not stored + /// + public string AccessToken { + get; + set; + } + + /// + /// Not stored + /// + public DateTimeOffset AccessTokenExpires { + get; + set; + } + + /// + /// A form for token + /// + /// bool true if OK was pressed, false if cancel + public bool ShowConfigDialog() { + DialogResult result = new SettingsForm().ShowDialog(); + if (result == DialogResult.OK) { + return true; + } + return false; + } + + } +} diff --git a/GreenshotPicasaPlugin/PicasaDestination.cs b/GreenshotGooglePhotosPlugin/GooglePhotosDestination.cs similarity index 75% rename from GreenshotPicasaPlugin/PicasaDestination.cs rename to GreenshotGooglePhotosPlugin/GooglePhotosDestination.cs index 4107ecd48..586a6e842 100644 --- a/GreenshotPicasaPlugin/PicasaDestination.cs +++ b/GreenshotGooglePhotosPlugin/GooglePhotosDestination.cs @@ -1,54 +1,54 @@ -/* - * A Picasa Plugin for Greenshot - * Copyright (C) 2011 Francis Noel - * - * For more information see: http://getgreenshot.org/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -using System.ComponentModel; -using System.Drawing; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; - -namespace GreenshotPicasaPlugin { - public class PicasaDestination : AbstractDestination { - private readonly PicasaPlugin _plugin; - public PicasaDestination(PicasaPlugin plugin) { - _plugin = plugin; - } - - public override string Designation => "Picasa"; - - public override string Description => Language.GetString("picasa", LangKey.upload_menu_item); - - public override Image DisplayIcon { - get { - ComponentResourceManager resources = new ComponentResourceManager(typeof(PicasaPlugin)); - return (Image)resources.GetObject("Picasa"); - } - } - - public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { - ExportInformation exportInformation = new ExportInformation(Designation, Description); - bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl); - if (uploaded) { - exportInformation.ExportMade = true; - exportInformation.Uri = uploadUrl; - } - ProcessExport(exportInformation, surface); - return exportInformation; - } - } -} +/* + * A GooglePhotos Plugin for Greenshot + * Copyright (C) 2011 Francis Noel + * + * For more information see: http://getgreenshot.org/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System.ComponentModel; +using System.Drawing; +using GreenshotPlugin.Core; +using GreenshotPlugin.Interfaces; + +namespace GreenshotGooglePhotosPlugin { + public class GooglePhotosDestination : AbstractDestination { + private readonly GooglePhotosPlugin _plugin; + public GooglePhotosDestination(GooglePhotosPlugin plugin) { + _plugin = plugin; + } + + public override string Designation => "GooglePhotos"; + + public override string Description => Language.GetString("googlephotos", LangKey.upload_menu_item); + + public override Image DisplayIcon { + get { + ComponentResourceManager resources = new ComponentResourceManager(typeof(GooglePhotosPlugin)); + return (Image)resources.GetObject("GooglePhotos"); + } + } + + public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { + ExportInformation exportInformation = new ExportInformation(Designation, Description); + bool uploaded = _plugin.Upload(captureDetails, surface, out var uploadUrl); + if (uploaded) { + exportInformation.ExportMade = true; + exportInformation.Uri = uploadUrl; + } + ProcessExport(exportInformation, surface); + return exportInformation; + } + } +} diff --git a/GreenshotPicasaPlugin/PicasaPlugin.cs b/GreenshotGooglePhotosPlugin/GooglePhotosPlugin.cs similarity index 68% rename from GreenshotPicasaPlugin/PicasaPlugin.cs rename to GreenshotGooglePhotosPlugin/GooglePhotosPlugin.cs index a8f312484..b5d37f62c 100644 --- a/GreenshotPicasaPlugin/PicasaPlugin.cs +++ b/GreenshotGooglePhotosPlugin/GooglePhotosPlugin.cs @@ -1,125 +1,124 @@ -/* - * A Picasa Plugin for Greenshot - * Copyright (C) 2011 Francis Noel - * - * For more information see: http://getgreenshot.org/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -using System; -using System.ComponentModel; -using System.Drawing; -using System.IO; -using System.Windows.Forms; -using GreenshotPlugin.Controls; -using GreenshotPlugin.Core; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; - -namespace GreenshotPicasaPlugin { - /// - /// This is the Picasa base code - /// - [Plugin("Picasa", true)] - public class PicasaPlugin : IGreenshotPlugin { - private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PicasaPlugin)); - private static PicasaConfiguration _config; - private ComponentResourceManager _resources; - private ToolStripMenuItem _itemPlugInRoot; - - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected void Dispose(bool disposing) { - if (disposing) { - if (_itemPlugInRoot != null) { - _itemPlugInRoot.Dispose(); - _itemPlugInRoot = null; - } - } - } - - /// - /// Implementation of the IGreenshotPlugin.Initialize - /// - public bool Initialize() { - SimpleServiceProvider.Current.AddService(new PicasaDestination(this)); - - // Get configuration - _config = IniConfig.GetIniSection(); - _resources = new ComponentResourceManager(typeof(PicasaPlugin)); - - _itemPlugInRoot = new ToolStripMenuItem - { - Text = Language.GetString("picasa", LangKey.Configure), - Image = (Image) _resources.GetObject("Picasa") - }; - _itemPlugInRoot.Click += ConfigMenuClick; - PluginUtils.AddToContextMenu(_itemPlugInRoot); - Language.LanguageChanged += OnLanguageChanged; - return true; - } - - public void OnLanguageChanged(object sender, EventArgs e) { - if (_itemPlugInRoot != null) { - _itemPlugInRoot.Text = Language.GetString("picasa", LangKey.Configure); - } - } - - public void Shutdown() { - Log.Debug("Picasa Plugin shutdown."); - Language.LanguageChanged -= OnLanguageChanged; - //host.OnImageEditorOpen -= new OnImageEditorOpenHandler(ImageEditorOpened); - } - - /// - /// Implementation of the IPlugin.Configure - /// - public void Configure() { - _config.ShowConfigDialog(); - } - - public void ConfigMenuClick(object sender, EventArgs eventArgs) { - Configure(); - } - - public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) { - SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality); - try { - string url = null; - new PleaseWaitForm().ShowAndWait("Picasa", Language.GetString("picasa", LangKey.communication_wait), - delegate - { - string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails)); - url = PicasaUtils.UploadToPicasa(surfaceToUpload, outputSettings, captureDetails.Title, filename); - } - ); - uploadUrl = url; - - if (uploadUrl != null && _config.AfterUploadLinkToClipBoard) { - ClipboardHelper.SetClipboardData(uploadUrl); - } - return true; - } catch (Exception e) { - Log.Error("Error uploading.", e); - MessageBox.Show(Language.GetString("picasa", LangKey.upload_failure) + " " + e.Message); - } - uploadUrl = null; - return false; - } - } -} +/* + * A GooglePhotos Plugin for Greenshot + * Copyright (C) 2011 Francis Noel + * + * For more information see: http://getgreenshot.org/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Windows.Forms; +using GreenshotPlugin.Controls; +using GreenshotPlugin.Core; +using GreenshotPlugin.IniFile; +using GreenshotPlugin.Interfaces; +using GreenshotPlugin.Interfaces.Plugin; + +namespace GreenshotGooglePhotosPlugin { + /// + /// This is the GooglePhotos base code + /// + [Plugin("GooglePhotos", true)] + public class GooglePhotosPlugin : IGreenshotPlugin { + private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosPlugin)); + private static GooglePhotosConfiguration _config; + private ComponentResourceManager _resources; + private ToolStripMenuItem _itemPlugInRoot; + + public void Dispose() { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!disposing) return; + if (_itemPlugInRoot == null) return; + _itemPlugInRoot.Dispose(); + _itemPlugInRoot = null; + } + + /// + /// Implementation of the IGreenshotPlugin.Initialize + /// + public bool Initialize() { + SimpleServiceProvider.Current.AddService(new GooglePhotosDestination(this)); + + // Get configuration + _config = IniConfig.GetIniSection(); + _resources = new ComponentResourceManager(typeof(GooglePhotosPlugin)); + + _itemPlugInRoot = new ToolStripMenuItem + { + Text = Language.GetString("googlephotos", LangKey.Configure), + Image = (Image) _resources.GetObject("GooglePhotos") + }; + _itemPlugInRoot.Click += ConfigMenuClick; + PluginUtils.AddToContextMenu(_itemPlugInRoot); + Language.LanguageChanged += OnLanguageChanged; + return true; + } + + public void OnLanguageChanged(object sender, EventArgs e) { + if (_itemPlugInRoot != null) { + _itemPlugInRoot.Text = Language.GetString("googlephotos", LangKey.Configure); + } + } + + public void Shutdown() { + Log.Debug("GooglePhotos Plugin shutdown."); + Language.LanguageChanged -= OnLanguageChanged; + //host.OnImageEditorOpen -= new OnImageEditorOpenHandler(ImageEditorOpened); + } + + /// + /// Implementation of the IPlugin.Configure + /// + public void Configure() { + _config.ShowConfigDialog(); + } + + public void ConfigMenuClick(object sender, EventArgs eventArgs) { + Configure(); + } + + public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) { + SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality); + try { + string url = null; + new PleaseWaitForm().ShowAndWait("GooglePhotos", Language.GetString("googlephotos", LangKey.communication_wait), + delegate + { + string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails)); + url = GooglePhotosUtils.UploadToGooglePhotos(surfaceToUpload, outputSettings, captureDetails.Title, filename); + } + ); + uploadUrl = url; + + if (uploadUrl != null && _config.AfterUploadLinkToClipBoard) { + ClipboardHelper.SetClipboardData(uploadUrl); + } + return true; + } catch (Exception e) { + Log.Error("Error uploading.", e); + MessageBox.Show(Language.GetString("googlephotos", LangKey.upload_failure) + " " + e.Message); + } + uploadUrl = null; + return false; + } + } +} diff --git a/GreenshotPicasaPlugin/PicasaPlugin.resx b/GreenshotGooglePhotosPlugin/GooglePhotosPlugin.resx similarity index 96% rename from GreenshotPicasaPlugin/PicasaPlugin.resx rename to GreenshotGooglePhotosPlugin/GooglePhotosPlugin.resx index de5045226..240e4a53e 100644 --- a/GreenshotPicasaPlugin/PicasaPlugin.resx +++ b/GreenshotGooglePhotosPlugin/GooglePhotosPlugin.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - picasa.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + GooglePhotos.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff --git a/GreenshotPicasaPlugin/PicasaUtils.cs b/GreenshotGooglePhotosPlugin/GooglePhotosUtils.cs similarity index 74% rename from GreenshotPicasaPlugin/PicasaUtils.cs rename to GreenshotGooglePhotosPlugin/GooglePhotosUtils.cs index eb2b2be2e..27aa13d8f 100644 --- a/GreenshotPicasaPlugin/PicasaUtils.cs +++ b/GreenshotGooglePhotosPlugin/GooglePhotosUtils.cs @@ -1,119 +1,120 @@ -/* - * A Picasa Plugin for Greenshot - * Copyright (C) 2011 Francis Noel - * - * For more information see: http://getgreenshot.org/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using GreenshotPlugin.Core; -using System; -using System.Xml; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; - -namespace GreenshotPicasaPlugin { - /// - /// Description of PicasaUtils. - /// - public static class PicasaUtils { - private const string PicasaScope = "https://picasaweb.google.com/data/"; - private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(PicasaUtils)); - private static readonly PicasaConfiguration Config = IniConfig.GetIniSection(); - private const string AuthUrl = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}&scope=" + PicasaScope; - private const string TokenUrl = "https://www.googleapis.com/oauth2/v3/token"; - private const string UploadUrl = "https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}"; - - /// - /// Do the actual upload to Picasa - /// - /// Image to upload - /// - /// - /// - /// PicasaResponse - public static string UploadToPicasa(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { - // Fill the OAuth2Settings - var settings = new OAuth2Settings - { - AuthUrlPattern = AuthUrl, - TokenUrl = TokenUrl, - CloudServiceName = "Picasa", - ClientId = PicasaCredentials.ClientId, - ClientSecret = PicasaCredentials.ClientSecret, - AuthorizeMode = OAuth2AuthorizeMode.LocalServer, - RefreshToken = Config.RefreshToken, - AccessToken = Config.AccessToken, - AccessTokenExpires = Config.AccessTokenExpires - }; - - // Copy the settings from the config, which is kept in memory and on the disk - - try { - var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings); - if (Config.AddFilename) { - webRequest.Headers.Add("Slug", NetworkHelper.EscapeDataString(filename)); - } - SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename); - container.Upload(webRequest); - - string response = NetworkHelper.GetResponseAsString(webRequest); - - return ParseResponse(response); - } finally { - // Copy the settings back to the config, so they are stored. - Config.RefreshToken = settings.RefreshToken; - Config.AccessToken = settings.AccessToken; - Config.AccessTokenExpires = settings.AccessTokenExpires; - Config.IsDirty = true; - IniConfig.Save(); - } - } - - /// - /// Parse the upload URL from the response - /// - /// - /// - public static string ParseResponse(string response) { - if (response == null) { - return null; - } - try { - XmlDocument doc = new XmlDocument(); - doc.LoadXml(response); - XmlNodeList nodes = doc.GetElementsByTagName("link", "*"); - if(nodes.Count > 0) { - string url = null; - foreach(XmlNode node in nodes) { - if (node.Attributes != null) { - url = node.Attributes["href"].Value; - string rel = node.Attributes["rel"].Value; - // Pictures with rel="http://schemas.google.com/photos/2007#canonical" are the direct link - if (rel != null && rel.EndsWith("canonical")) { - break; - } - } - } - return url; - } - } catch(Exception e) { - Log.ErrorFormat("Could not parse Picasa response due to error {0}, response was: {1}", e.Message, response); - } - return null; - } - } -} +/* + * A GooglePhotos Plugin for Greenshot + * Copyright (C) 2011 Francis Noel + * + * For more information see: http://getgreenshot.org/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using GreenshotPlugin.Core; +using System; +using System.Xml; +using GreenshotPlugin.Core.OAuth; +using GreenshotPlugin.IniFile; +using GreenshotPlugin.Interfaces; +using GreenshotPlugin.Interfaces.Plugin; + +namespace GreenshotGooglePhotosPlugin { + /// + /// Description of GooglePhotosUtils. + /// + public static class GooglePhotosUtils { + private const string GooglePhotosScope = "https://picasaweb.google.com/data/"; + private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(GooglePhotosUtils)); + private static readonly GooglePhotosConfiguration Config = IniConfig.GetIniSection(); + private const string AuthUrl = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}&scope=" + GooglePhotosScope; + private const string TokenUrl = "https://www.googleapis.com/oauth2/v3/token"; + private const string UploadUrl = "https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}"; + + /// + /// Do the actual upload to GooglePhotos + /// + /// Image to upload + /// SurfaceOutputSettings + /// string + /// string + /// GooglePhotosResponse + public static string UploadToGooglePhotos(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) { + // Fill the OAuth2Settings + var settings = new OAuth2Settings + { + AuthUrlPattern = AuthUrl, + TokenUrl = TokenUrl, + CloudServiceName = "GooglePhotos", + ClientId = GooglePhotosCredentials.ClientId, + ClientSecret = GooglePhotosCredentials.ClientSecret, + AuthorizeMode = OAuth2AuthorizeMode.JsonReceiver, + RefreshToken = Config.RefreshToken, + AccessToken = Config.AccessToken, + AccessTokenExpires = Config.AccessTokenExpires + }; + + // Copy the settings from the config, which is kept in memory and on the disk + + try { + var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, string.Format(UploadUrl, Config.UploadUser, Config.UploadAlbum), settings); + if (Config.AddFilename) { + webRequest.Headers.Add("Slug", NetworkHelper.EscapeDataString(filename)); + } + SurfaceContainer container = new SurfaceContainer(surfaceToUpload, outputSettings, filename); + container.Upload(webRequest); + + string response = NetworkHelper.GetResponseAsString(webRequest); + + return ParseResponse(response); + } finally { + // Copy the settings back to the config, so they are stored. + Config.RefreshToken = settings.RefreshToken; + Config.AccessToken = settings.AccessToken; + Config.AccessTokenExpires = settings.AccessTokenExpires; + Config.IsDirty = true; + IniConfig.Save(); + } + } + + /// + /// Parse the upload URL from the response + /// + /// + /// + public static string ParseResponse(string response) { + if (response == null) { + return null; + } + try { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(response); + XmlNodeList nodes = doc.GetElementsByTagName("link", "*"); + if(nodes.Count > 0) { + string url = null; + foreach(XmlNode node in nodes) { + if (node.Attributes != null) { + url = node.Attributes["href"].Value; + string rel = node.Attributes["rel"].Value; + // Pictures with rel="http://schemas.google.com/photos/2007#canonical" are the direct link + if (rel != null && rel.EndsWith("canonical")) { + break; + } + } + } + return url; + } + } catch(Exception e) { + Log.ErrorFormat("Could not parse GooglePhotos response due to error {0}, response was: {1}", e.Message, response); + } + return null; + } + } +} diff --git a/GreenshotPicasaPlugin/GreenshotPicasaPlugin.Credentials.template b/GreenshotGooglePhotosPlugin/GreenshotGooglePhotosPlugin.Credentials.template similarity index 83% rename from GreenshotPicasaPlugin/GreenshotPicasaPlugin.Credentials.template rename to GreenshotGooglePhotosPlugin/GreenshotGooglePhotosPlugin.Credentials.template index 47172f2d4..452922112 100644 --- a/GreenshotPicasaPlugin/GreenshotPicasaPlugin.Credentials.template +++ b/GreenshotGooglePhotosPlugin/GreenshotGooglePhotosPlugin.Credentials.template @@ -19,13 +19,13 @@ * along with this program. If not, see . */ -namespace GreenshotPicasaPlugin { +namespace GreenshotGooglePhotosPlugin { /// /// This class is merely a placeholder for the file keeping the API key and secret for dropbox integration. /// You can set your own values here /// - public static class PicasaCredentials { - public static string ClientId = "${Picasa_ClientId}"; - public static string ClientSecret = "${Picasa_ClientSecret}"; + public static class GooglePhotosCredentials { + public static string ClientId = "${GooglePhotos_ClientId}"; + public static string ClientSecret = "${GooglePhotos_ClientSecret}"; } } diff --git a/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj b/GreenshotGooglePhotosPlugin/GreenshotGooglePhotosPlugin.csproj similarity index 64% rename from GreenshotOCRPlugin/GreenshotOCRPlugin.csproj rename to GreenshotGooglePhotosPlugin/GreenshotGooglePhotosPlugin.csproj index 42e03e628..3fb62aa99 100644 --- a/GreenshotOCRPlugin/GreenshotOCRPlugin.csproj +++ b/GreenshotGooglePhotosPlugin/GreenshotGooglePhotosPlugin.csproj @@ -1,16 +1,15 @@ - - - - GreenshotOCRPlugin - GreenshotOCRPlugin - - - - - PreserveNewest - - - - - - + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/LanguageKeys.cs b/GreenshotGooglePhotosPlugin/LanguageKeys.cs similarity index 81% rename from GreenshotPicasaPlugin/LanguageKeys.cs rename to GreenshotGooglePhotosPlugin/LanguageKeys.cs index 58a488db5..1a7a73996 100644 --- a/GreenshotPicasaPlugin/LanguageKeys.cs +++ b/GreenshotGooglePhotosPlugin/LanguageKeys.cs @@ -1,5 +1,5 @@ /* - * A Picasa Plugin for Greenshot + * A GooglePhotos Plugin for Greenshot * Copyright (C) 2011 Francis Noel * * For more information see: http://getgreenshot.org/ @@ -16,19 +16,14 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - */ - -namespace GreenshotPicasaPlugin { + */ + +namespace GreenshotGooglePhotosPlugin { public enum LangKey { upload_menu_item, - settings_title, - label_upload_format, - upload_success, upload_failure, communication_wait, - Configure, - label_AfterUpload, - label_AfterUploadLinkToClipBoard + Configure } } diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-cs-CZ.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-cs-CZ.xml similarity index 74% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-cs-CZ.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-cs-CZ.xml index 4fe14494b..7168b569c 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-cs-CZ.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-cs-CZ.xml @@ -1,29 +1,29 @@ - - - - Zrušit - Probíhá komunikace s Picasem. Prosím počkejte ... - Konfigurace - Opravdu chcete odstranit obrázek {0} z Picasa? - Odstranit Picasa {0} - Historie - Neplatná oprávnění. Otevřít nastavení pro provedené změn. - Po odeslání - Kopírovat odkaz do schránky - Zobrazit historii - Výchozí velikost - Heslo - Formát obrázku - Jméno - OK - Originál URL - Čtvercové náhledy URL ??? - Webová adresa URL - Nastavení Picasa - Nahrát - Nahrání obrázku do Picasa se nezdařilo: - Nahrát do Picasa - Úspěšně odeslaný obrázek do Picasa! - Prosím ověřit aplikaci Picasa. Otevřít nastavení obrazovky. ??? - + + + + Zrušit + Probíhá komunikace s Picasem. Prosím počkejte ... + Konfigurace + Opravdu chcete odstranit obrázek {0} z GooglePhotos? + Odstranit GooglePhotos {0} + Historie + Neplatná oprávnění. Otevřít nastavení pro provedené změn. + Po odeslání + Kopírovat odkaz do schránky + Zobrazit historii + Výchozí velikost + Heslo + Formát obrázku + Jméno + OK + Originál URL + Čtvercové náhledy URL ??? + Webová adresa URL + Nastavení GooglePhotos + Nahrát + Nahrání obrázku do GooglePhotos se nezdařilo: + Nahrát do GooglePhotos + Úspěšně odeslaný obrázek do GooglePhotos! + Prosím ověřit aplikaci GooglePhotos. Otevřít nastavení obrazovky. ??? + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-de-DE.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-de-DE.xml similarity index 74% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-de-DE.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-de-DE.xml index 6b30f0214..0a437a443 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-de-DE.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-de-DE.xml @@ -8,25 +8,25 @@ Anschliessend - Picasa konfigurieren + GooglePhotos konfigurieren - Hochladen zu Picasa + Hochladen zu GooglePhotos - Picasa Einstellungen + GooglePhotos Einstellungen - Hochladen zu Picasa war erfolgreich ! + Hochladen zu GooglePhotos war erfolgreich ! - Fehler beim Hochladen zu Picasa: + Fehler beim Hochladen zu GooglePhotos: Grafikformat - Übermittle Daten zu Picasa. Bitte warten... + Übermittle Daten zu GooglePhotos. Bitte warten... diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-en-US.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-en-US.xml similarity index 73% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-en-US.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-en-US.xml index e99c84ed7..70ec9f14a 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-en-US.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-en-US.xml @@ -8,25 +8,25 @@ After upload - Configure Picasa + Configure GooglePhotos - Upload to Picasa + Upload to GooglePhotos - Picasa settings + GooglePhotos settings - Successfully uploaded image to Picasa! + Successfully uploaded image to GooglePhotos! - An error occured while uploading to Picasa: + An error occured while uploading to GooglePhotos: Image format - Communicating with Picasa. Please wait... + Communicating with GooglePhotos. Please wait... \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-fr-FR.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-fr-FR.xml similarity index 62% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-fr-FR.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-fr-FR.xml index 589d55613..553d5725e 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-fr-FR.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-fr-FR.xml @@ -1,14 +1,14 @@ - - - - Communication en cours avec Picasa. Veuillez patientez... - Configurer Picasa - Après téléversement - Copier le lien dans le presse-papier - Format image - Paramètres Picasa - Une erreur s'est produite lors du téléversement vers Picasa : - Téléverser vers Picasa - Image téléversée avec succès vers Picasa ! - + + + + Communication en cours avec GooglePhotos. Veuillez patientez... + Configurer GooglePhotos + Après téléversement + Copier le lien dans le presse-papier + Format image + Paramètres GooglePhotos + Une erreur s'est produite lors du téléversement vers GooglePhotos : + Téléverser vers GooglePhotos + Image téléversée avec succès vers GooglePhotos ! + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-id-ID.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-id-ID.xml similarity index 58% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-id-ID.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-id-ID.xml index 5632a3daa..c906bb08e 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-id-ID.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-id-ID.xml @@ -1,14 +1,14 @@ - - - - Menyambungkan ke Picasa. Tunggu sebentar... - Konfigurasi Picasa - Sesudah mengunggah - Sambung ke papanklip - Format gambar - Pengaturan Picasa - Kesalahan terjadi ketika mengunggah ke Picasa: - Unggah ke Picasa - Berhasil mengunggah gambar ke Picasa! - + + + + Menyambungkan ke GooglePhotos. Tunggu sebentar... + Konfigurasi GooglePhotos + Sesudah mengunggah + Sambung ke papanklip + Format gambar + Pengaturan GooglePhotos + Kesalahan terjadi ketika mengunggah ke GooglePhotos: + Unggah ke GooglePhotos + Berhasil mengunggah gambar ke GooglePhotos! + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-it-IT.xml similarity index 73% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-it-IT.xml index 6f0b76c78..801e57cfd 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-it-IT.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-it-IT.xml @@ -1,32 +1,32 @@ - - - - - Collegamento agli Appunti - - - Dopo il caricamento - - - Impostazioni Picasa - - - Carica su Picasa - - - Impostazioni Picasa - - - Caricamento immagine su Picasa completato! - - - Si è verificato un errore durante il caricamento su Picasa: - - - Formato immagine - - - Comunicazione con Picasa... - - - + + + + + Collegamento agli Appunti + + + Dopo il caricamento + + + Impostazioni GooglePhotos + + + Carica su GooglePhotos + + + Impostazioni GooglePhotos + + + Caricamento immagine su GooglePhotos completato! + + + Si è verificato un errore durante il caricamento su GooglePhotos: + + + Formato immagine + + + Comunicazione con GooglePhotos... + + + diff --git a/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ja-JP.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ja-JP.xml new file mode 100644 index 000000000..19c1ffc6c --- /dev/null +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ja-JP.xml @@ -0,0 +1,14 @@ + + + + リンクをクリップボードへコピー + アップロード後 + GooglePhotos の設定 + GooglePhotos にアップロード + GooglePhotos の設定 + GooglePhotos へのアップロードに成功しました! + GooglePhotos へのアップロード中にエラーが発生しました: + 画像フォーマット + GooglePhotos に接続中です。しばらくお待ち下さい... + + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-kab-DZ.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-kab-DZ.xml similarity index 59% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-kab-DZ.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-kab-DZ.xml index 367287108..dd5c784d4 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-kab-DZ.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-kab-DZ.xml @@ -1,14 +1,14 @@ - S tidett tebɣiḍ ad tekkseḍ amazray adigan n Picasa ?... - Swel Picasa + S tidett tebɣiḍ ad tekkseḍ amazray adigan n GooglePhotos ?... + Swel GooglePhotos Ticki yemmed usali Nɣel aseɣwen ɣef afus Amsal n tugna - Iɣewwaṛen Picasa - Teḍra-d tuccḍa deg usali ɣer Picasa : - Sali ɣer Picasa - Tugna tuli ɣer Picasa ! + Iɣewwaṛen GooglePhotos + Teḍra-d tuccḍa deg usali ɣer GooglePhotos : + Sali ɣer GooglePhotos + Tugna tuli ɣer GooglePhotos ! diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-ko-KR.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ko-KR.xml similarity index 74% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-ko-KR.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ko-KR.xml index f452a9618..d095f9f72 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-ko-KR.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ko-KR.xml @@ -8,25 +8,25 @@ 얼로드 후 - Picasa 설정 + GooglePhotos 설정 - Picasa로 업로드 + GooglePhotos로 업로드 - Picasa 설정 + GooglePhotos 설정 - Picasa로 이미지 업로드 성공! + GooglePhotos로 이미지 업로드 성공! - Picasa로 업로드시 오류 발생: + GooglePhotos로 업로드시 오류 발생: 이미지 형식 - Picasa와 연결 중 잠시 기다리세요... + GooglePhotos와 연결 중 잠시 기다리세요... \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-lv-LV.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-lv-LV.xml similarity index 75% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-lv-LV.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-lv-LV.xml index c33bdc519..7e0e0b8ca 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-lv-LV.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-lv-LV.xml @@ -9,25 +9,25 @@ Pēc augšupielādes - Picasa iestatījumi + GooglePhotos iestatījumi - Augšupieladēt uz Picasa + Augšupieladēt uz GooglePhotos - Picasa iestatījumi + GooglePhotos iestatījumi - Attēls veiksmīgi augšupielādēts uz Picasa! + Attēls veiksmīgi augšupielādēts uz GooglePhotos! - Kļūda augšuplādējot uz Picasa: + Kļūda augšuplādējot uz GooglePhotos: Attēla formāts - Savienojos ar Picasa. Lūdzu uzgaidiet... + Savienojos ar GooglePhotos. Lūdzu uzgaidiet... diff --git a/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-pl-PL.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-pl-PL.xml new file mode 100644 index 000000000..be521cb06 --- /dev/null +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-pl-PL.xml @@ -0,0 +1,14 @@ + + + + Trwa komunikacja z GooglePhotos. Proszę czekać... + Konfiguruj GooglePhotos + Po wysłaniu + Link do schowka + Format obrazów + Ustawienia GooglePhotos + Wystąpił błąd przy wysyłaniu do GooglePhotos: + Wyślij do GooglePhotos + Wysyłanie obrazu do GooglePhotos powiodło się! + + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-pt-PT.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-pt-PT.xml similarity index 73% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-pt-PT.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-pt-PT.xml index 4649e8005..c3194dad0 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-pt-PT.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-pt-PT.xml @@ -8,25 +8,25 @@ Após enviar - Configurar o Picasa + Configurar o GooglePhotos - enviar para o Picasa + enviar para o GooglePhotos - Definições Picasa + Definições GooglePhotos - Imagem enviada com êxito para o Picasa! + Imagem enviada com êxito para o GooglePhotos! - Ocorreu um erro ao enviar para o Picasa: + Ocorreu um erro ao enviar para o GooglePhotos: Formato da imagem - A comunicar com o Picasa. Por favor aguarde... + A comunicar com o GooglePhotos. Por favor aguarde... \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-ru-RU.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ru-RU.xml similarity index 61% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-ru-RU.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ru-RU.xml index 7a273bce7..c7aa0317d 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-ru-RU.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-ru-RU.xml @@ -1,14 +1,14 @@ - - - - Обмен данными с Picasa. Подождите... - Настройка Picasa - После загрузки - Ссылки в буфер обмена - Формат изображения - Настройки Picasa - Произошла ошибка при загрузке на Picasa: - Загрузить на Picasa - Изображение успешно загружено на Picasa! - + + + + Обмен данными с GooglePhotos. Подождите... + Настройка GooglePhotos + После загрузки + Ссылки в буфер обмена + Формат изображения + Настройки GooglePhotos + Произошла ошибка при загрузке на GooglePhotos: + Загрузить на GooglePhotos + Изображение успешно загружено на GooglePhotos! + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-sr-RS.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-sr-RS.xml similarity index 98% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-sr-RS.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-sr-RS.xml index f43494f01..88c045edd 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-sr-RS.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-sr-RS.xml @@ -1,14 +1,14 @@ - - - - Комуницирам с Пикасом. Сачекајте… - Поставке Пикасе - Након отпремања: - Веза ка остави - Формат слике: - Поставке Пикасе - Дошло је до грешке при отпремању на Пикасу: - Отпреми на Пикасу - Слика је успешно отпремљена на Пикасу. - + + + + Комуницирам с Пикасом. Сачекајте… + Поставке Пикасе + Након отпремања: + Веза ка остави + Формат слике: + Поставке Пикасе + Дошло је до грешке при отпремању на Пикасу: + Отпреми на Пикасу + Слика је успешно отпремљена на Пикасу. + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-sv-SE.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-sv-SE.xml similarity index 73% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-sv-SE.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-sv-SE.xml index d3469d802..86a0aec4c 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-sv-SE.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-sv-SE.xml @@ -8,25 +8,25 @@ Vid uppladdning - Konfigurera Picasa + Konfigurera GooglePhotos - Ladda upp till Picasa + Ladda upp till GooglePhotos - Picasa-inställningar + GooglePhotos-inställningar - Skärmdumpen laddades upp till Picasa! + Skärmdumpen laddades upp till GooglePhotos! - Ett fel uppstod vid uppladdning till Picasa: + Ett fel uppstod vid uppladdning till GooglePhotos: Bildformat - Kommunicerar med Picasa. Vänta... + Kommunicerar med GooglePhotos. Vänta... \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-uk-UA.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-uk-UA.xml similarity index 53% rename from GreenshotPicasaPlugin/Languages/language_picasaplugin-uk-UA.xml rename to GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-uk-UA.xml index c1ecd0a4c..9be4ab5b6 100644 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-uk-UA.xml +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-uk-UA.xml @@ -1,14 +1,14 @@ - - - - Посилання в буфер обміну - Після вивантаження - Налаштувати Picasa - Вивантажити на Picasa - Параметри Picasa - Зображення вдало вивантажено на Picasa! - Відбулась помилка під час вивантаження на Picasa: - Формат зображення - З’єднання з Picasa. Будь ласка, зачекайте... - - + + + + Посилання в буфер обміну + Після вивантаження + Налаштувати GooglePhotos + Вивантажити на GooglePhotos + Параметри GooglePhotos + Зображення вдало вивантажено на GooglePhotos! + Відбулась помилка під час вивантаження на GooglePhotos: + Формат зображення + З’єднання з GooglePhotos. Будь ласка, зачекайте... + + diff --git a/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-zh-CN.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-zh-CN.xml new file mode 100644 index 000000000..0323ba38d --- /dev/null +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-zh-CN.xml @@ -0,0 +1,14 @@ + + + + 正在连接到GooglePhotos。请稍后... + 配置 GooglePhotos + 上传之后 + 复制链接到剪贴板 + 图片格式 + GooglePhotos设置 + 上传到GooglePhotos时发生错误: + 上传到GooglePhotos + 图片已成功上传到了GooglePhotos! + + \ No newline at end of file diff --git a/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-zh-TW.xml b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-zh-TW.xml new file mode 100644 index 000000000..34fa14d3f --- /dev/null +++ b/GreenshotGooglePhotosPlugin/Languages/language_googlephotosplugin-zh-TW.xml @@ -0,0 +1,14 @@ + + + + 正在與 GooglePhotos 通訊,請稍候... + 組態 GooglePhotos + 上傳後 + 連結到剪貼簿 + 圖片格式 + GooglePhotos 設定 + 上傳到 GooglePhotos 時發生錯誤: + 上傳到 GooglePhotos + 上傳圖片到 GooglePhotos 成功! + + \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Properties/AssemblyInfo.cs b/GreenshotGooglePhotosPlugin/Properties/AssemblyInfo.cs similarity index 94% rename from GreenshotPicasaPlugin/Properties/AssemblyInfo.cs rename to GreenshotGooglePhotosPlugin/Properties/AssemblyInfo.cs index 3a917ddcd..d4fa2878a 100644 --- a/GreenshotPicasaPlugin/Properties/AssemblyInfo.cs +++ b/GreenshotGooglePhotosPlugin/Properties/AssemblyInfo.cs @@ -25,7 +25,7 @@ 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: AssemblyDescription("A plugin to upload images to Picasa")] +[assembly: AssemblyDescription("A plugin to upload images to GooglePhotos")] // This sets the default COM visibility of types in the assembly to invisible. // If you need to expose a type to COM, use [ComVisible(true)] on that type. diff --git a/GreenshotPicasaPlugin/README b/GreenshotGooglePhotosPlugin/README similarity index 100% rename from GreenshotPicasaPlugin/README rename to GreenshotGooglePhotosPlugin/README diff --git a/GreenshotImgurPlugin/GreenshotImgurPlugin.Credentials.template b/GreenshotImgurPlugin/GreenshotImgurPlugin.Credentials.template index 42dd7986f..4c6948fea 100644 --- a/GreenshotImgurPlugin/GreenshotImgurPlugin.Credentials.template +++ b/GreenshotImgurPlugin/GreenshotImgurPlugin.Credentials.template @@ -25,7 +25,7 @@ namespace GreenshotImgurPlugin { /// You can set your own values here /// public static class ImgurCredentials { - public static string CONSUMER_KEY = "${Imgur_ClientId}"; - public static string CONSUMER_SECRET = "${Imgur_ClientSecret}"; + public static string CONSUMER_KEY = "${Imgur13_ClientId}"; + public static string CONSUMER_SECRET = "${Imgur13_ClientSecret}"; } } diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs index ecbbf775b..6c4b06674 100644 --- a/GreenshotImgurPlugin/ImgurUtils.cs +++ b/GreenshotImgurPlugin/ImgurUtils.cs @@ -20,11 +20,11 @@ */ using System; using System.Collections.Generic; -using System.Drawing; using System.IO; using System.Linq; using System.Net; using GreenshotPlugin.Core; +using GreenshotPlugin.Core.OAuth; using GreenshotPlugin.IniFile; using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces.Plugin; @@ -37,10 +37,8 @@ namespace GreenshotImgurPlugin { private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurUtils)); private const string SmallUrlPattern = "http://i.imgur.com/{0}s.jpg"; private static readonly ImgurConfiguration Config = IniConfig.GetIniSection(); - private const string AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}"; - private const string TokenUrl = "https://api.imgur.com/oauth2/token"; - /// + /// /// Check if we need to load the history /// /// @@ -162,20 +160,20 @@ namespace GreenshotImgurPlugin { responseString = reader.ReadToEnd(); } } catch (Exception ex) { - Log.Error("Upload to imgur gave an exeption: ", ex); + Log.Error("Upload to imgur gave an exception: ", ex); throw; } } else { var oauth2Settings = new OAuth2Settings { - AuthUrlPattern = AuthUrlPattern, - TokenUrl = TokenUrl, - RedirectUrl = "https://getgreenshot.org/oauth/imgur", + AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=token&client_id={ClientId}&state={State}", + TokenUrl = "https://api.imgur.com/oauth2/token", + RedirectUrl = "https://getgreenshot.org/authorize/imgur", CloudServiceName = "Imgur", ClientId = ImgurCredentials.CONSUMER_KEY, ClientSecret = ImgurCredentials.CONSUMER_SECRET, - AuthorizeMode = OAuth2AuthorizeMode.OutOfBoundAuto, + AuthorizeMode = OAuth2AuthorizeMode.JsonReceiver, RefreshToken = Config.RefreshToken, AccessToken = Config.AccessToken, AccessTokenExpires = Config.AccessTokenExpires @@ -221,7 +219,7 @@ namespace GreenshotImgurPlugin { Log.InfoFormat("Retrieving Imgur image for {0} with url {1}", imgurInfo.Hash, imgurInfo.SmallSquare); HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(string.Format(SmallUrlPattern, imgurInfo.Hash), HTTPMethod.GET); webRequest.ServicePoint.Expect100Continue = false; - // Not for getting the thumbnail, in anonymous modus + // Not for getting the thumbnail, in anonymous mode //SetClientId(webRequest); using WebResponse response = webRequest.GetResponse(); LogRateLimitInfo(response); @@ -304,7 +302,7 @@ namespace GreenshotImgurPlugin { } } } - // Make sure we remove it from the history, if no error occured + // Make sure we remove it from the history, if no error occurred Config.runtimeImgurHistory.Remove(imgurInfo.Hash); Config.ImgurUploadHistory.Remove(imgurInfo.Hash); imgurInfo.Image = null; diff --git a/GreenshotImgurPlugin/LanguageKeys.cs b/GreenshotImgurPlugin/LanguageKeys.cs index 25b3e311f..cfde3c940 100644 --- a/GreenshotImgurPlugin/LanguageKeys.cs +++ b/GreenshotImgurPlugin/LanguageKeys.cs @@ -22,19 +22,11 @@ namespace GreenshotImgurPlugin { public enum LangKey { upload_menu_item, - settings_title, - label_url, - label_upload_format, - label_clear, - OK, - CANCEL, - upload_success, upload_failure, communication_wait, delete_question, clear_question, delete_title, - use_page_link, history, configure } diff --git a/GreenshotJiraPlugin/AsyncMemoryCache.cs b/GreenshotJiraPlugin/AsyncMemoryCache.cs index de2a61d04..af34e769e 100644 --- a/GreenshotJiraPlugin/AsyncMemoryCache.cs +++ b/GreenshotJiraPlugin/AsyncMemoryCache.cs @@ -80,39 +80,7 @@ namespace GreenshotJiraPlugin return keyObject.ToString(); } - /// - /// Get an element from the cache, if this is not available call the create function. - /// - /// object for the key - /// CancellationToken - /// TResult - public async Task DeleteAsync(TKey keyObject, CancellationToken cancellationToken = default) - { - var key = CreateKey(keyObject); - await _semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false); - try - { - _cache.Remove(key); - } - finally - { - _semaphoreSlim.Release(); - } - } - - /// - /// Get a task element from the cache, if this is not available return null. - /// You probably want to call GetOrCreateAsync - /// - /// object for the key - /// Task with TResult, null if no value - public Task GetAsync(TKey keyObject) - { - var key = CreateKey(keyObject); - return _cache.Get(key) as Task ?? EmptyValueTask; - } - - /// + /// /// Get a task element from the cache, if this is not available call the create function. /// /// object for the key @@ -124,20 +92,7 @@ namespace GreenshotJiraPlugin return _cache.Get(key) as Task ?? GetOrCreateInternalAsync(keyObject, null, cancellationToken); } - /// - /// Get a task element from the cache, if this is not available call the create function. - /// - /// object for the key - /// CacheItemPolicy for when you want more control over the item - /// CancellationToken - /// Task with TResult - public Task GetOrCreateAsync(TKey keyObject, CacheItemPolicy cacheItemPolicy, CancellationToken cancellationToken = default) - { - var key = CreateKey(keyObject); - return _cache.Get(key) as Task ?? GetOrCreateInternalAsync(keyObject, cacheItemPolicy, cancellationToken); - } - - /// + /// /// This takes care of the real async part of the code. /// /// @@ -213,7 +168,7 @@ namespace GreenshotJiraPlugin /// Override to know when an item is removed, make sure to configure ActivateUpdateCallback / ActivateRemovedCallback /// /// CacheEntryRemovedArguments - protected virtual void RemovedCallback(CacheEntryRemovedArguments cacheEntryRemovedArguments) + protected void RemovedCallback(CacheEntryRemovedArguments cacheEntryRemovedArguments) { _log.Verbose().WriteLine("Item {0} removed due to {1}.", cacheEntryRemovedArguments.CacheItem.Key, cacheEntryRemovedArguments.RemovedReason); if (cacheEntryRemovedArguments.CacheItem.Value is IDisposable disposable) @@ -228,7 +183,7 @@ namespace GreenshotJiraPlugin /// ActivateUpdateCallback / ActivateRemovedCallback /// /// CacheEntryUpdateArguments - protected virtual void UpdateCallback(CacheEntryUpdateArguments cacheEntryUpdateArguments) + protected void UpdateCallback(CacheEntryUpdateArguments cacheEntryUpdateArguments) { _log.Verbose().WriteLine("Update request for {0} due to {1}.", cacheEntryUpdateArguments.Key, cacheEntryUpdateArguments.RemovedReason); } diff --git a/GreenshotJiraPlugin/JiraConfiguration.cs b/GreenshotJiraPlugin/JiraConfiguration.cs index ba8cad80c..f54132b04 100644 --- a/GreenshotJiraPlugin/JiraConfiguration.cs +++ b/GreenshotJiraPlugin/JiraConfiguration.cs @@ -34,10 +34,7 @@ namespace GreenshotJiraPlugin { [IniProperty("Url", Description="Base url to Jira system, without anything else", DefaultValue=DefaultUrl)] public string Url { get; set; } - [IniProperty("Timeout", Description="Session timeout in minutes", DefaultValue="30")] - public int Timeout { get; set; } - - [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] + [IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")] public OutputFormat UploadFormat { get; set; } [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")] diff --git a/GreenshotJiraPlugin/LanguageKeys.cs b/GreenshotJiraPlugin/LanguageKeys.cs index d881be575..6820d5d50 100644 --- a/GreenshotJiraPlugin/LanguageKeys.cs +++ b/GreenshotJiraPlugin/LanguageKeys.cs @@ -30,16 +30,8 @@ namespace GreenshotJiraPlugin { column_summary, label_comment, label_filename, - label_jira, label_jirafilter, login_error, - login_title, - settings_title, - label_url, - label_upload_format, - OK, - CANCEL, - upload_success, upload_failure, communication_wait, } diff --git a/GreenshotOCRCommand/COMWrapper.cs b/GreenshotOCRCommand/COMWrapper.cs deleted file mode 100644 index fd26cfeb9..000000000 --- a/GreenshotOCRCommand/COMWrapper.cs +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Diagnostics; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Messaging; -using System.Runtime.Remoting.Proxies; - -namespace GreenshotOCRCommand { - /// - /// Wraps a late-bound COM server. - /// - public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo { - private const int MK_E_UNAVAILABLE = -2147221021; - private const int CO_E_CLASSSTRING = -2147221005; - - /// - /// Holds reference to the actual COM object which is wrapped by this proxy - /// - private readonly object _comObject; - - /// - /// Type of the COM object, set on constructor after getting the COM reference - /// - private readonly Type _comType; - - /// - /// The type of which method calls are intercepted and executed on the COM object. - /// - private readonly Type _interceptType; - - /// - /// Gets a COM object and returns the transparent proxy which intercepts all calls to the object - /// - /// Interface which defines the method and properties to intercept - /// Transparent proxy to the real proxy for the object - /// T must be an interface decorated with the attribute. - public static T GetInstance() { - Type type = typeof(T); - if (null == type) { - throw new ArgumentNullException(nameof(T)); - } - if (!type.IsInterface) { - throw new ArgumentException("The specified type must be an interface.", nameof(T)); - } - - ComProgIdAttribute progIdAttribute = ComProgIdAttribute.GetAttribute(type); - if (string.IsNullOrEmpty(progIdAttribute?.Value)) { - throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T)); - } - string progId = progIdAttribute.Value; - - object comObject = null; - try { - comObject = Marshal.GetActiveObject(progId); - } catch (COMException comE) { - if (comE.ErrorCode == MK_E_UNAVAILABLE) - { - Debug.WriteLine($"No current instance of {progId} object available."); - } - else if (comE.ErrorCode == CO_E_CLASSSTRING) - { - Debug.WriteLine($"Unknown progId {progId}"); - } - } catch (Exception ex) { - Debug.WriteLine($"Error getting active object for {progId} {ex.Message}"); - } - - if (comObject != null) { - COMWrapper wrapper = new COMWrapper(comObject, type); - return (T)wrapper.GetTransparentProxy(); - } - return default; - } - - /// - /// Gets or creates a COM object and returns the transparent proxy which intercepts all calls to the object - /// The ComProgId can be a normal ComProgId or a GUID prefixed with "clsid:" - /// - /// Interface which defines the method and properties to intercept - /// Transparent proxy to the real proxy for the object - /// The type must be an interface decorated with the attribute. - public static T GetOrCreateInstance() { - Type type = typeof(T); - if (null == type) { - throw new ArgumentNullException(nameof(T)); - } - if (!type.IsInterface) { - throw new ArgumentException("The specified type must be an interface.", nameof(T)); - } - - ComProgIdAttribute progIdAttribute = ComProgIdAttribute.GetAttribute(type); - if (string.IsNullOrEmpty(progIdAttribute?.Value)) { - throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T)); - } - - object comObject = null; - Type comType = null; - string progId = progIdAttribute.Value; - - try { - comObject = Marshal.GetActiveObject(progId); - } catch (COMException comE) { - if (comE.ErrorCode == MK_E_UNAVAILABLE) - { - Debug.WriteLine($"No current instance of {progId} object available."); - } - else if (comE.ErrorCode == CO_E_CLASSSTRING) - { - Debug.WriteLine($"Unknown progId {progId}"); - } - } catch (Exception ex) { - Debug.WriteLine($"Error getting active object for {progId} {ex.Message}"); - } - // Did we get the current instance? If not, try to create a new - if (comObject == null) { - try { - comType = Type.GetTypeFromProgID(progId, true); - } catch (Exception) { - Debug.WriteLine($"Error getting type for {progId}"); - } - if (comType != null) { - try { - comObject = Activator.CreateInstance(comType); - if (comObject != null) { - Debug.WriteLine($"Created new instance of {progId} object."); - } - } catch (Exception ex) { - Debug.WriteLine($"Error creating object for {progId} {ex.Message}"); - } - } - } - if (comObject != null) { - COMWrapper wrapper = new COMWrapper(comObject, type); - return (T)wrapper.GetTransparentProxy(); - } - return default; - } - - /// - /// Wrap an object and return the transparent proxy which intercepts all calls to the object - /// - /// An object to intercept - /// Interface which defines the method and properties to intercept - /// Transparent proxy to the real proxy for the object - private static object Wrap(object comObject, Type type) { - if (null == comObject) { - throw new ArgumentNullException(nameof(comObject)); - } - if (null == type) { - throw new ArgumentNullException(nameof(type)); - } - - COMWrapper wrapper = new COMWrapper(comObject, type); - return wrapper.GetTransparentProxy(); - } - - /// - /// Constructor - /// - /// - /// The COM object to wrap. - /// - /// - /// The interface type to impersonate. - /// - private COMWrapper(object comObject, Type type) - : base(type) { - _comObject = comObject; - _comType = comObject.GetType(); - _interceptType = type; - } - - /// - /// If is not called, we need to make - /// sure that the COM object is still cleaned up. - /// - ~COMWrapper() { - Dispose(false); - } - - /// - /// Cleans up the COM object. - /// - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Release the COM reference - /// - /// - /// if this was called from the - /// interface. - /// - private void Dispose(bool disposing) { - if (disposing && null != _comObject) { - if (Marshal.IsComObject(_comObject)) { - try { - while (Marshal.ReleaseComObject(_comObject) > 0) - { - } - } catch (Exception ex) { - Debug.WriteLine($"Problem releasing {_comType}"); - Debug.WriteLine("Error: " + ex); - } - } - } - } - - /// - /// Returns a string representing the wrapped object. - /// - /// - /// The full name of the intercepted type. - /// - public override string ToString() { - return _interceptType.FullName; - } - - /// - /// Returns the hash code of the wrapped object. - /// - /// - /// The hash code of the wrapped object. - /// - public override int GetHashCode() { - return _comObject.GetHashCode(); - } - - /// - /// Compares this object to another. - /// - /// - /// The value to compare to. - /// - /// - /// if the objects are equal. - /// - public override bool Equals(object value) { - if (null != value && RemotingServices.IsTransparentProxy(value)) { - if (RemotingServices.GetRealProxy(value) is COMWrapper wrapper) { - return _comObject == wrapper._comObject; - } - } - - return base.Equals(value); - } - - /// - /// Returns the base type for a reference type. - /// - /// - /// The reference type. - /// - /// - /// The base value type. - /// - /// - /// is . - /// - private static Type GetByValType(Type byRefType) { - if (null == byRefType) { - throw new ArgumentNullException(nameof(byRefType)); - } - - if (byRefType.IsByRef) { - string name = byRefType.FullName; - name = name.Substring(0, name.Length - 1); - byRefType = byRefType.Assembly.GetType(name, true); - } - - return byRefType; - } - - /// - /// Intercept method calls - /// - /// - /// Contains information about the method being called - /// - /// - /// A . - /// - public override IMessage Invoke(IMessage myMessage) { - IMethodCallMessage callMessage = myMessage as IMethodCallMessage; - - MethodInfo method = callMessage?.MethodBase as MethodInfo; - if (method == null) - { - if (callMessage != null) - { - Debug.WriteLine($"Unrecognized Invoke call: {callMessage.MethodBase}"); - } - return null; - } - - object returnValue = null; - object[] outArgs = null; - int outArgsCount = 0; - - string methodName = method.Name; - Type returnType = method.ReturnType; - BindingFlags flags = BindingFlags.InvokeMethod; - int argCount = callMessage.ArgCount; - - ParameterModifier[] argModifiers = null; - ParameterInfo[] parameters = null; - - if ("Dispose" == methodName && 0 == argCount && typeof(void) == returnType) { - Dispose(); - } else if ("ToString" == methodName && 0 == argCount && typeof(string) == returnType) { - returnValue = ToString(); - } else if ("GetType" == methodName && 0 == argCount && typeof(Type) == returnType) { - returnValue = _interceptType; - } else if ("GetHashCode" == methodName && 0 == argCount && typeof(int) == returnType) { - returnValue = GetHashCode(); - } else if ("Equals" == methodName && 1 == argCount && typeof(bool) == returnType) { - returnValue = Equals(callMessage.Args[0]); - } else if (1 == argCount && typeof(void) == returnType && (methodName.StartsWith("add_") || methodName.StartsWith("remove_"))) { - if (!(callMessage.InArgs[0] is Delegate handler)) { - return new ReturnMessage(new ArgumentNullException(nameof(handler)), callMessage); - } - } else { - var invokeObject = _comObject; - var invokeType = _comType; - - ParameterInfo parameter; - object[] args; - if (methodName.StartsWith("get_")) { - // Property Get - methodName = methodName.Substring(4); - flags = BindingFlags.GetProperty; - args = callMessage.InArgs; - } else if (methodName.StartsWith("set_")) { - // Property Set - methodName = methodName.Substring(4); - flags = BindingFlags.SetProperty; - args = callMessage.InArgs; - } else { - args = callMessage.Args; - if (null != args && 0 != args.Length) { - // Modifiers for ref / out parameters - argModifiers = new ParameterModifier[1]; - argModifiers[0] = new ParameterModifier(args.Length); - - parameters = method.GetParameters(); - for (int i = 0; i < parameters.Length; i++) { - parameter = parameters[i]; - if (parameter.IsOut || parameter.ParameterType.IsByRef) { - argModifiers[0][i] = true; - outArgsCount++; - } - } - - if (0 == outArgsCount) { - argModifiers = null; - } - } - } - - // Un-wrap wrapped COM objects before passing to the method - COMWrapper[] originalArgs; - COMWrapper wrapper; - Type byValType; - if (null == args || 0 == args.Length) { - originalArgs = null; - } else { - originalArgs = new COMWrapper[args.Length]; - for (int i = 0; i < args.Length; i++) { - if (null != args[i] && RemotingServices.IsTransparentProxy(args[i])) { - wrapper = RemotingServices.GetRealProxy(args[i]) as COMWrapper; - if (null != wrapper) { - originalArgs[i] = wrapper; - args[i] = wrapper._comObject; - } - } else if (argModifiers != null && (0 != outArgsCount && argModifiers[0][i])) { - byValType = GetByValType(parameters[i].ParameterType); - if (byValType.IsInterface) { - // If we're passing a COM object by reference, and - // the parameter is null, we need to pass a - // DispatchWrapper to avoid a type mismatch exception. - if (null == args[i]) { - args[i] = new DispatchWrapper(null); - } - } else if (typeof(decimal) == byValType) { - // If we're passing a decimal value by reference, - // we need to pass a CurrencyWrapper to avoid a - // type mismatch exception. - // http://support.microsoft.com/?kbid=837378 - args[i] = new CurrencyWrapper(args[i]); - } - } - } - } - - try { - returnValue = invokeType.InvokeMember(methodName, flags, null, invokeObject, args, argModifiers, null, null); - } catch (Exception ex) { - return new ReturnMessage(ex, callMessage); - } - - // Handle enum and interface return types - if (null != returnValue) { - if (returnType.IsInterface) { - // Wrap the returned value in an intercepting COM wrapper - if (Marshal.IsComObject(returnValue)) { - returnValue = Wrap(returnValue, returnType); - } - } else if (returnType.IsEnum) { - // Convert to proper Enum type - returnValue = Enum.Parse(returnType, returnValue.ToString()); - } - } - - // Handle out args - if (0 != outArgsCount) { - if (args != null && parameters != null) - { - outArgs = new object[args.Length]; - for (int i = 0; i < parameters.Length; i++) { - if (argModifiers != null && !argModifiers[0][i]) { - continue; - } - - var arg = args[i]; - if (null == arg) { - continue; - } - - parameter = parameters[i]; - wrapper = null; - - byValType = GetByValType(parameter.ParameterType); - if (typeof(decimal) == byValType) { - if (arg is CurrencyWrapper) { - arg = ((CurrencyWrapper)arg).WrappedObject; - } - } else if (byValType.IsEnum) { - arg = Enum.Parse(byValType, arg.ToString()); - } else if (byValType.IsInterface) { - if (Marshal.IsComObject(arg)) { - if (originalArgs != null) - { - wrapper = originalArgs[i]; - } - if (null != wrapper && wrapper._comObject != arg) { - wrapper.Dispose(); - wrapper = null; - } - - if (null == wrapper) { - wrapper = new COMWrapper(arg, byValType); - } - arg = wrapper.GetTransparentProxy(); - } - } - outArgs[i] = arg; - } - } - } - } - - return new ReturnMessage(returnValue, outArgs, outArgsCount, callMessage.LogicalCallContext, callMessage); - } - - /// - /// Implementation for the interface IRemotingTypeInfo - /// This makes it possible to cast the COMWrapper - /// - /// Type to cast to - /// object to cast - /// - public bool CanCastTo(Type toType, object o) { - bool returnValue = _interceptType.IsAssignableFrom(toType); - return returnValue; - } - - /// - /// Implementation for the interface IRemotingTypeInfo - /// - public string TypeName { - get { - throw new NotSupportedException(); - } - set { - throw new NotSupportedException(); - } - } - } -} diff --git a/GreenshotOCRCommand/ComProgIdAttribute.cs b/GreenshotOCRCommand/ComProgIdAttribute.cs deleted file mode 100644 index 936ea34f9..000000000 --- a/GreenshotOCRCommand/ComProgIdAttribute.cs +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; - -namespace GreenshotOCRCommand { - /// - /// An attribute to specifiy the ProgID of the COM class to create. (As suggested by Kristen Wegner) - /// - [AttributeUsage(AttributeTargets.Interface)] - public sealed class ComProgIdAttribute : Attribute { - /// - /// Extracts the attribute from the specified type. - /// - /// - /// The interface type. - /// - /// - /// The . - /// - /// - /// is . - /// - public static ComProgIdAttribute GetAttribute(Type interfaceType) { - if (null == interfaceType) { - throw new ArgumentNullException(nameof(interfaceType)); - } - - Type attributeType = typeof(ComProgIdAttribute); - object[] attributes = interfaceType.GetCustomAttributes(attributeType, false); - - if (0 == attributes.Length) { - Type[] interfaces = interfaceType.GetInterfaces(); - for (int i = 0; i < interfaces.Length; i++) { - interfaceType = interfaces[i]; - attributes = interfaceType.GetCustomAttributes(attributeType, false); - if (0 != attributes.Length) { - break; - } - } - } - - if (0 == attributes.Length) { - return null; - } - return (ComProgIdAttribute)attributes[0]; - } - - /// Constructor - /// The COM ProgID. - public ComProgIdAttribute(string value) { - Value = value; - } - - /// - /// Returns the COM ProgID - /// - public string Value { get; } - } -} diff --git a/GreenshotOCRCommand/GreenshotOCRCommand.csproj b/GreenshotOCRCommand/GreenshotOCRCommand.csproj deleted file mode 100644 index 4267325f2..000000000 --- a/GreenshotOCRCommand/GreenshotOCRCommand.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - GreenshotOCRCommand - GreenshotOCRCommand - WinExe - - - - - - - - diff --git a/GreenshotOCRCommand/Modi/CompressionLevel.cs b/GreenshotOCRCommand/Modi/CompressionLevel.cs deleted file mode 100644 index 0cb9a4bc7..000000000 --- a/GreenshotOCRCommand/Modi/CompressionLevel.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi -{ - public enum CompressionLevel { - miCOMP_LEVEL_LOW = 0, - miCOMP_LEVEL_MEDIUM = 1, - miCOMP_LEVEL_HIGH = 2 - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/FileFormat.cs b/GreenshotOCRCommand/Modi/FileFormat.cs deleted file mode 100644 index 42c86a104..000000000 --- a/GreenshotOCRCommand/Modi/FileFormat.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi -{ - public enum FileFormat { - miFILE_FORMAT_DEFAULTVALUE = -1, - miFILE_FORMAT_TIFF = 1, - miFILE_FORMAT_TIFF_LOSSLESS = 2, - miFILE_FORMAT_MDI = 4 - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/ICommon.cs b/GreenshotOCRCommand/Modi/ICommon.cs deleted file mode 100644 index 433fcd121..000000000 --- a/GreenshotOCRCommand/Modi/ICommon.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; - -namespace GreenshotOCRCommand.Modi -{ - /// - /// Base class for the common properties of the Modi interfaces - /// - public interface ICommon : IDisposable { - IDocument Application { get; } - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/IDispatch.cs b/GreenshotOCRCommand/Modi/IDispatch.cs deleted file mode 100644 index 623feef72..000000000 --- a/GreenshotOCRCommand/Modi/IDispatch.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.CustomMarshalers; - -namespace GreenshotOCRCommand.Modi { - [ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IDispatch { - void Reserved(); - [PreserveSig] - int GetTypeInfo(uint nInfo, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] out Type typeInfo); - } -} diff --git a/GreenshotOCRCommand/Modi/IDocument.cs b/GreenshotOCRCommand/Modi/IDocument.cs deleted file mode 100644 index cd9098f61..000000000 --- a/GreenshotOCRCommand/Modi/IDocument.cs +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi { - /// - /// The MODI Document object represents an ordered collection of document images saved as a single file. - /// You can use the Create method to load an existing MDI or TIF file, or to create an empty document that you can populate with images from other documents. - /// The OCR method performs OCR on all pages in the document, and the OnOCRProgress event reports the status of the operation and allows the user to cancel it. - /// The Dirty property lets you know whether your document has unsaved OCR results or changes. - /// The SaveAs method allows you to specify an image file format and a compression level. - /// You can also use the PrintOut method to print the document to a printer or a file. - /// - [ComProgId("MODI.Document")] - public interface IDocument : ICommon { - /// - /// Closes the document. - /// - /// - void Close(bool saveCall); - - /// - /// The document's collection of pages. - /// - IImages Images - { - get; - } - - /// - /// Occurs periodically during an optical character recognition (OCR) operation. Returns the estimated percentage of the OCR operation that is complete, and allows the user to cancel the operation. - /// - // event OnOCRProgress { get; } - - /// - /// Indicates whether the active document has unsaved changes. - /// - bool Dirty { get; } - - /// - /// Creates a new document. - /// - /// Optional String. The path and filename of the optional document file that is to be loaded into the new document. - void Create(string file); - - /// - /// Performs optical character recognition (OCR) on the specified document or image. - /// - /// ModiLanguage - /// Optional Boolean. Specifies whether the OCR engine attempts to determine the orientation of the page. Default is true. - /// Optional Boolean. Specifies whether the OCR engine attempts to "de-skew" the page to correct for small angles of misalignment from the vertical. Default is true. - void OCR(ModiLanguage language, bool orientimage, bool straightenImage); - - /// - /// - /// - /// - /// - /// - void SaveAs(string filename, FileFormat fileFormat, CompressionLevel compressionLevel); - } -} diff --git a/GreenshotOCRCommand/Modi/IImage.cs b/GreenshotOCRCommand/Modi/IImage.cs deleted file mode 100644 index 5329c4eaf..000000000 --- a/GreenshotOCRCommand/Modi/IImage.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi -{ - /// - /// Describes the page in a scan - /// - public interface IImage : ICommon { - ILayout Layout { - get; - } - - long BitsPerPixel { get; } - CompressionLevel Compression { get; } - //IPictureDisp Picture { get; } - int PixelHeight { get; } - int PixelWidth { get; } - //IPictureDisp Thumbnail { get; } - int XDPI { get; } - int YDPI { get; } - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/IImages.cs b/GreenshotOCRCommand/Modi/IImages.cs deleted file mode 100644 index 3c429c7d0..000000000 --- a/GreenshotOCRCommand/Modi/IImages.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Collections; - -namespace GreenshotOCRCommand.Modi -{ - /// - /// Use the Images accessor property of the Document object to return an Images collection. - /// Use the Item property of the Images collection to return an Image object and gain access to its OCR Layout - /// (including recognized Text and Words), the properties that describe its dimensions and format (BitsPerPixel, Compression, PixelHeight, PixelWidth, XDPI, and YDPI), - /// and its Picture and Thumbnail images. - /// - public interface IImages : ICommon, IEnumerable { - int Count { - get; - } - IImage this [int index] { - get; - } - new IEnumerator GetEnumerator(); - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/ILayout.cs b/GreenshotOCRCommand/Modi/ILayout.cs deleted file mode 100644 index 351724150..000000000 --- a/GreenshotOCRCommand/Modi/ILayout.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi -{ - /// - /// Layout of the IImage - /// - public interface ILayout : ICommon { - /// - /// Returns the recognized text as a Unicode string. - /// - string Text { - get; - } - - /// - /// An accessor property that returns the Words collection recognized in the text during an optical character recognition (OCR) operation. - /// - IWords Words { get; } - - /// - /// Returns the number of characters in the recognized text. - /// - int NumChars { get; } - - /// - /// Returns the number of words in the recognized text. - /// - int NumWords { get; } - - /// - /// Returns the language identifier for the recognized text. Read-only Long. - /// - ModiLanguage Language { get; } - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/IMiRect.cs b/GreenshotOCRCommand/Modi/IMiRect.cs deleted file mode 100644 index 3474a5e86..000000000 --- a/GreenshotOCRCommand/Modi/IMiRect.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi -{ - /// - /// Represents a bounding rectangle in the optical character recognition (OCR) layout. - /// - public interface IMiRect : ICommon { - /// - /// The Bottom property represent the distance in pixels from the top edge of the containing image. - /// - int Bottom { get; } - - /// - /// The Left property represent the distance in pixels from the left edge of the containing image. - /// - int Left { get; } - - /// - /// The Right property represent the distance in pixels from the left edge of the containing image. - /// - int Right { get; } - - /// - /// The Top property represent the distance in pixels from the top edge of the containing image. - /// - int Top { get; } - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/IMiRects.cs b/GreenshotOCRCommand/Modi/IMiRects.cs deleted file mode 100644 index e322b577d..000000000 --- a/GreenshotOCRCommand/Modi/IMiRects.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Collections; - -namespace GreenshotOCRCommand.Modi -{ - /// - /// Represents the collection of bounding rectangles in the optical character recognition (OCR) layout. A collection of MiRect objects. - /// - public interface IMiRects : ICommon, IEnumerable { - int Count { - get; - } - IMiRect this [int index] { - get; - } - new IEnumerator GetEnumerator(); - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Modi/IWord.cs b/GreenshotOCRCommand/Modi/IWord.cs deleted file mode 100644 index 6ba1a425b..000000000 --- a/GreenshotOCRCommand/Modi/IWord.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi -{ - /// - /// Represents a word recognized in the text during an optical character recognition (OCR) operation. - /// - public interface IWord : ICommon - { - /// - /// Returns the index of the specified word in the Words collection of the Layout or IMiSelectableItem object. - /// - long Id { get; } - - /// - /// Returns the number of the region in the optical character recognition (OCR) layout where the word occurs. - /// - long RegionId { get; } - - /// - /// Returns the number of the line in the optical character recognition (OCR) layout where the word occurs. - /// - long LineId { get; } - - /// - /// Returns the recognized text as a Unicode string. - /// - string Text { get; } - - /// - /// Returns the relative confidence factor reported by the optical character recognition (OCR) engine (on a scale of 0 to 999) after recognizing the specified word. - /// - short RecognitionConfidence { get; } - - /// - /// Returns the index of the font used by the specified wordthis is the font that was recognized in the text during an optical character recognition (OCR) operation. - /// - long FontId { get; } - - /// - /// Rectangles - /// - IMiRects Rects { get; } - - } -} diff --git a/GreenshotOCRCommand/Modi/IWords.cs b/GreenshotOCRCommand/Modi/IWords.cs deleted file mode 100644 index 4e7243cdd..000000000 --- a/GreenshotOCRCommand/Modi/IWords.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Collections; - -namespace GreenshotOCRCommand.Modi -{ - /// - /// The Words collection recognized in the text during an optical character recognition (OCR) operation. - /// - public interface IWords : ICommon, IEnumerable - { - int Count - { - get; - } - - IWord this[int index] - { - get; - } - - new IEnumerator GetEnumerator(); - } -} diff --git a/GreenshotOCRCommand/Modi/ModiLanguage.cs b/GreenshotOCRCommand/Modi/ModiLanguage.cs deleted file mode 100644 index b1af9f30c..000000000 --- a/GreenshotOCRCommand/Modi/ModiLanguage.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace GreenshotOCRCommand.Modi -{ - public enum ModiLanguage { - CHINESE_SIMPLIFIED = 2052, - CHINESE_TRADITIONAL = 1028, - CZECH = 5, - DANISH = 6, - DUTCH = 19, - ENGLISH = 9, - FINNISH = 11, - FRENCH = 12, - GERMAN = 7, - GREEK = 8, - HUNGARIAN = 14, - ITALIAN = 16, - JAPANESE = 17, - KOREAN = 18, - NORWEGIAN = 20, - POLISH = 21, - PORTUGUESE = 22, - RUSSIAN = 25, - SPANISH = 10, - SWEDISH = 29, - TURKISH = 31, - SYSDEFAULT = 2048 - } -} \ No newline at end of file diff --git a/GreenshotOCRCommand/Program.cs b/GreenshotOCRCommand/Program.cs deleted file mode 100644 index 7f1c81b09..000000000 --- a/GreenshotOCRCommand/Program.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using GreenshotOCRCommand.Modi; - -namespace GreenshotOCRCommand { - public class Program { - private const string Usage = "<-c> | [language] [orientimage] [straightenImage]"; - public static int Main(string[] args) { - if (args.Length == 0) { - Console.WriteLine(Usage); - return -1; - } - string filename = args[0]; - ModiLanguage language = ModiLanguage.ENGLISH; - if (args.Length >= 2) { - language = (ModiLanguage)Enum.Parse(typeof(ModiLanguage), args[1]); - } - bool orientimage = true; - if (args.Length >= 3) { - orientimage = bool.Parse(args[2]); - } - bool straightenImage = true; - if (args.Length >= 4) { - straightenImage = bool.Parse(args[3]); - } - try { - if (File.Exists(filename) || "-c".Equals(filename)) - { - using var document = COMWrapper.GetOrCreateInstance(); - if (document == null) { - Console.WriteLine("MODI not installed"); - return -2; - } - if ("-c".Equals(filename)) { - return 0; - } - document.Create(filename); - document.OCR(language, orientimage, straightenImage); - var modiImage = document.Images[0]; - var layout = modiImage.Layout; - if (layout != null) - { -#if DEBUG - if (layout.Words != null) - { - foreach (var word in ToEnumerable(layout.Words)) - { - if (word.Rects != null) - { - foreach (var rect in ToEnumerable(word.Rects)) - { - Debug.WriteLine($"Rect {rect.Left},{rect.Top},{rect.Right},{rect.Bottom} - Word {word.Text} : Confidence: {word.RecognitionConfidence}"); - } - } - } - } -#endif - if (layout.Text != null) - { - // For for BUG-1884: - // Although trim is done in the OCR Plugin, it does make sense in the command too. - Console.WriteLine(layout.Text.Trim()); - } - } - document.Close(false); - return 0; - } - } catch (Exception ex) { - Console.WriteLine(ex.Message); - } - return -1; - } - - /// - /// Helper method - /// - /// IEnumerable of IMiRect - private static IEnumerable ToEnumerable(IMiRects rects) - { - for (int i = 0; i < rects.Count; i++) - { - yield return rects[i]; - } - } - - /// - /// Helper method - /// - /// IEnumerable of IWord - private static IEnumerable ToEnumerable(IWords words) - { - for (int i = 0; i < words.Count; i++) - { - yield return words[i]; - } - } - } -} diff --git a/GreenshotOCRCommand/Properties/AssemblyInfo.cs b/GreenshotOCRCommand/Properties/AssemblyInfo.cs deleted file mode 100644 index 85d71c24d..000000000 --- a/GreenshotOCRCommand/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyDescription("A small executable to OCR a bitmap")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("d7668e7e-3018-4d27-9aa0-21b1afade1b8")] diff --git a/GreenshotOCRCommand/app.config b/GreenshotOCRCommand/app.config deleted file mode 100644 index 2dcad202f..000000000 --- a/GreenshotOCRCommand/app.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-cs-CZ.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-cs-CZ.xml deleted file mode 100644 index eb225ae3e..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-cs-CZ.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Jazyk pro OCR - Orientaci obrázku - Srovnat obrázek - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-de-DE.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-de-DE.xml deleted file mode 100644 index a5743f569..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-de-DE.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Sprache für OCR - - - Bild ausrichten - - - Bild glätten - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-en-US.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-en-US.xml deleted file mode 100644 index 6412a02f6..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-en-US.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Language for OCR - - - Orient image - - - Straighten image - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-fr-FR.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-fr-FR.xml deleted file mode 100644 index 9e3c8126d..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-fr-FR.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Langage pour l'OCR - Orienter l'image - Redresser l'image - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-id-ID.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-id-ID.xml deleted file mode 100644 index e828076e2..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-id-ID.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Bahasa untuk OCR - Orientasikan gambar - Rapikan gambar - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-it-IT.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-it-IT.xml deleted file mode 100644 index 52259f004..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-it-IT.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Lingua OCR - - - Orientamento immagine - - - Raddrizza immagine - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-ja-JP.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-ja-JP.xml deleted file mode 100644 index c103704d4..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-ja-JP.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - OCRの言語 - 画像の向きを揃える - 画像の傾きを補正する - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-kab-DZ.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-kab-DZ.xml deleted file mode 100644 index 3d884a724..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-kab-DZ.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Tutlayt i OCR - Wehhi tugna - Seggwem tugna - - diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-ko-KR.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-ko-KR.xml deleted file mode 100644 index e35bfe3b8..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-ko-KR.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - OCR 언어 - - - 가로 이미지 - - - 세로 이미지 - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-lv-LV.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-lv-LV.xml deleted file mode 100644 index 463aa73fb..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-lv-LV.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - OCR valoda - - - Pagriezt attēlu - - - Iztaisnot attēlu - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-nl-NL.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-nl-NL.xml deleted file mode 100644 index dac711d25..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-nl-NL.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Taal voor OCR - - - Beeld richten - - - Beeld vereffenen - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-pl-PL.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-pl-PL.xml deleted file mode 100644 index 37b40b65a..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-pl-PL.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Język dla OCR - Orientacja obrazu - Wyprostowanie obrazów - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-pt-PT.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-pt-PT.xml deleted file mode 100644 index ee55958d8..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-pt-PT.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Idioma para OCR - Orientar imagem - Endireitar imagem - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-ru-RU.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-ru-RU.xml deleted file mode 100644 index f2fffd34e..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-ru-RU.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Язык для OCR - Ориентация изображения - Выпрямление изображения - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-sk-SK.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-sk-SK.xml deleted file mode 100644 index 0f61ec429..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-sk-SK.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Jazyk pre OCR - - - Orientácia obrázku - - - Narovnať obrázok - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-sr-RS.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-sr-RS.xml deleted file mode 100644 index eaf252bd6..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-sr-RS.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Језик за препознавање знакова - Усмери слику - Исправи слику - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-sv-SE.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-sv-SE.xml deleted file mode 100644 index e59ce5e75..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-sv-SE.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Språk för OCR - - - Orientera bild - - - Släta ut bild - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-uk-UA.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-uk-UA.xml deleted file mode 100644 index 7a433eb4f..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-uk-UA.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - Мова для ОРТ - Орієнтувати зображення - Випрямлення зображення - - diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-CN.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-CN.xml deleted file mode 100644 index ccd0e159a..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-CN.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - OCR语言 - - - 图像定位 - - - 图像矫正 - - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-TW.xml b/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-TW.xml deleted file mode 100644 index dce00e4cf..000000000 --- a/GreenshotOCRPlugin/Languages/language_ocrplugin-zh-TW.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - OCR 語言 - 定向圖片 - 拉直圖片 - - \ No newline at end of file diff --git a/GreenshotOCRPlugin/ModiLanguage.cs b/GreenshotOCRPlugin/ModiLanguage.cs deleted file mode 100644 index 3edd95d0f..000000000 --- a/GreenshotOCRPlugin/ModiLanguage.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -namespace GreenshotOCRPlugin -{ - /// - /// Needed for the drop down, available languages for OCR - /// - public enum ModiLanguage { - CHINESE_SIMPLIFIED = 2052, - CHINESE_TRADITIONAL = 1028, - CZECH = 5, - DANISH = 6, - DUTCH = 19, - ENGLISH = 9, - FINNISH = 11, - FRENCH = 12, - GERMAN = 7, - GREEK = 8, - HUNGARIAN = 14, - ITALIAN = 16, - JAPANESE = 17, - KOREAN = 18, - NORWEGIAN = 20, - POLISH = 21, - PORTUGUESE = 22, - RUSSIAN = 25, - SPANISH = 10, - SWEDISH = 29, - TURKISH = 31, - SYSDEFAULT = 2048 - } -} \ No newline at end of file diff --git a/GreenshotOCRPlugin/OCRConfiguration.cs b/GreenshotOCRPlugin/OCRConfiguration.cs deleted file mode 100644 index 8eebcc91e..000000000 --- a/GreenshotOCRPlugin/OCRConfiguration.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using GreenshotPlugin.IniFile; - -namespace GreenshotOCRPlugin { - /// - /// Description of CoreConfiguration. - /// - [IniSection("OCR", Description="Greenshot OCR Plugin configuration")] - public class OCRConfiguration : IniSection { - [IniProperty("Language", Description="Language for OCR", DefaultValue="miLANG_ENGLISH")] - public string Language { get; set; } - [IniProperty("orientimage", Description="Orient image?", DefaultValue="true")] - public bool Orientimage { get; set; } - [IniProperty("straightenImage", Description="Straighten image?", DefaultValue="true")] - public bool StraightenImage { get; set; } - } -} diff --git a/GreenshotOCRPlugin/OCRDestination.cs b/GreenshotOCRPlugin/OCRDestination.cs deleted file mode 100644 index 5c774bfc1..000000000 --- a/GreenshotOCRPlugin/OCRDestination.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Drawing; -using System.IO; -using GreenshotPlugin.Core; -using GreenshotPlugin.Interfaces; - -namespace GreenshotOCRPlugin { - /// - /// Description of OCRDestination. - /// - public class OCRDestination : AbstractDestination { - private readonly OcrPlugin _plugin; - - public override string Designation => "OCR"; - - public override string Description => "OCR"; - - public override Image DisplayIcon { - get { - string exePath = PluginUtils.GetExePath("MSPVIEW.EXE"); - if (exePath != null && File.Exists(exePath)) { - return PluginUtils.GetCachedExeIcon(exePath, 0); - } - return null; - } - } - - public OCRDestination(OcrPlugin plugin) { - _plugin = plugin; - } - - public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { - ExportInformation exportInformation = new ExportInformation(Designation, Description) - { - ExportMade = _plugin.DoOcr(surface) != null - }; - return exportInformation; - } - } -} diff --git a/GreenshotOCRPlugin/OCRForm.cs b/GreenshotOCRPlugin/OCRForm.cs deleted file mode 100644 index 5ba8fda84..000000000 --- a/GreenshotOCRPlugin/OCRForm.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using GreenshotPlugin.Controls; - -namespace GreenshotOCRPlugin { - /// - /// This class is needed for design-time resolving of the language files - /// - public class OcrForm : GreenshotForm { - } -} diff --git a/GreenshotOCRPlugin/OCRPlugin.cs b/GreenshotOCRPlugin/OCRPlugin.cs deleted file mode 100644 index 677e22342..000000000 --- a/GreenshotOCRPlugin/OCRPlugin.cs +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Diagnostics; -using System.IO; -using System.Windows.Forms; -using GreenshotPlugin.Core; -using GreenshotPlugin.Effects; -using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces; -using GreenshotPlugin.Interfaces.Plugin; - -//using Microsoft.Win32; - -namespace GreenshotOCRPlugin { - /// - /// OCR Plugin Greenshot - /// - [Plugin("Ocr", true)] - public class OcrPlugin : IGreenshotPlugin { - private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(OcrPlugin)); - private string _ocrCommand; - private static OCRConfiguration _config; - private ToolStripMenuItem _ocrMenuItem = new ToolStripMenuItem(); - - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected void Dispose(bool disposing) - { - if (!disposing) return; - if (_ocrMenuItem == null) return; - _ocrMenuItem.Dispose(); - _ocrMenuItem = null; - } - - /// - /// Implementation of the IGreenshotPlugin.Initialize - /// - /// true if plugin is initialized, false if not (doesn't show) - public bool Initialize() { - Log.Debug("Initialize called"); - - var ocrDirectory = Path.GetDirectoryName(GetType().Assembly.Location); - if (ocrDirectory == null) - { - return false; - } - _ocrCommand = Path.Combine(ocrDirectory, "greenshotocrcommand.exe"); - - if (!HasModi()) { - Log.Warn("No MODI found!"); - return false; - } - // Provide the IDestination - SimpleServiceProvider.Current.AddService(new OCRDestination(this)); - // Load configuration - _config = IniConfig.GetIniSection(); - - if (_config.Language != null) { - _config.Language = _config.Language.Replace("miLANG_", string.Empty).Replace("_"," "); - } - return true; - } - - /// - /// Implementation of the IGreenshotPlugin.Shutdown - /// - public void Shutdown() { - Log.Debug("Shutdown"); - } - - /// - /// Implementation of the IPlugin.Configure - /// - public void Configure() { - if (!HasModi()) { - MessageBox.Show("Sorry, is seems that Microsoft Office Document Imaging (MODI) is not installed, therefor the OCR Plugin cannot work."); - return; - } - SettingsForm settingsForm = new SettingsForm(Enum.GetNames(typeof(ModiLanguage)), _config); - DialogResult result = settingsForm.ShowDialog(); - if (result == DialogResult.OK) { - // "Re"set hotkeys - IniConfig.Save(); - } - } - - - private const int MinWidth = 130; - private const int MinHeight = 130; - /// - /// Handling of the CaptureTaken "event" from the ICaptureHost - /// We do the OCR here! - /// - /// Has the Image and the capture details - public string DoOcr(ISurface surface) { - SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 0, true) - { - ReduceColors = true, - SaveBackgroundOnly = true - }; - // We only want the background - // Force Grayscale output - outputSettings.Effects.Add(new GrayscaleEffect()); - - // Also we need to check the size, resize if needed to 130x130 this is the minimum - if (surface.Image.Width < MinWidth || surface.Image.Height < MinHeight) { - int addedWidth = MinWidth - surface.Image.Width; - if (addedWidth < 0) { - addedWidth = 0; - } - int addedHeight = MinHeight - surface.Image.Height; - if (addedHeight < 0) { - addedHeight = 0; - } - IEffect effect = new ResizeCanvasEffect(addedWidth / 2, addedWidth / 2, addedHeight / 2, addedHeight / 2); - outputSettings.Effects.Add(effect); - } - var filePath = ImageOutput.SaveToTmpFile(surface, outputSettings, null); - - Log.Debug("Saved tmp file to: " + filePath); - - string text = ""; - try { - ProcessStartInfo processStartInfo = new ProcessStartInfo(_ocrCommand, "\"" + filePath + "\" " + _config.Language + " " + _config.Orientimage + " " + _config.StraightenImage) - { - CreateNoWindow = true, - RedirectStandardOutput = true, - UseShellExecute = false - }; - using Process process = Process.Start(processStartInfo); - if (process != null) - { - process.WaitForExit(30 * 1000); - if (process.ExitCode == 0) { - text = process.StandardOutput.ReadToEnd(); - } - } - } catch (Exception e) { - Log.Error("Error while calling Microsoft Office Document Imaging (MODI) to OCR: ", e); - } finally { - if (File.Exists(filePath)) { - Log.Debug("Cleaning up tmp file: " + filePath); - File.Delete(filePath); - } - } - - if (string.IsNullOrEmpty(text)) { - Log.Info("No text returned"); - return null; - } - - // For for BUG-1884: - text = text.Trim(); - - try { - Log.DebugFormat("Pasting OCR Text to Clipboard: {0}", text); - // Paste to Clipboard (the Plugin currently doesn't have access to the ClipboardHelper from Greenshot - IDataObject ido = new DataObject(); - ido.SetData(DataFormats.Text, true, text); - Clipboard.SetDataObject(ido, true); - } catch (Exception e) { - Log.Error("Problem pasting text to clipboard: ", e); - } - return text; - } - - private bool HasModi() { - try - { - using Process process = Process.Start(_ocrCommand, "-c"); - if (process != null) - { - process.WaitForExit(); - return process.ExitCode == 0; - } - } catch(Exception e) { - Log.DebugFormat("Error trying to initiate MODI: {0}", e.Message); - } - Log.InfoFormat("No Microsoft Office Document Imaging (MODI) found, disabling OCR"); - return false; - } - } -} \ No newline at end of file diff --git a/GreenshotOCRPlugin/SettingsForm.Designer.cs b/GreenshotOCRPlugin/SettingsForm.Designer.cs deleted file mode 100644 index a9e57749a..000000000 --- a/GreenshotOCRPlugin/SettingsForm.Designer.cs +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -namespace GreenshotOCRPlugin -{ - partial class SettingsForm - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the form. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.comboBox_languages = new System.Windows.Forms.ComboBox(); - this.checkBox_orientImage = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.checkBox_straightenImage = new GreenshotPlugin.Controls.GreenshotCheckBox(); - this.label_language = new GreenshotPlugin.Controls.GreenshotLabel(); - this.buttonOK = new GreenshotPlugin.Controls.GreenshotButton(); - this.buttonCancel = new GreenshotPlugin.Controls.GreenshotButton(); - this.SuspendLayout(); - // - // comboBox_languages - // - this.comboBox_languages.FormattingEnabled = true; - this.comboBox_languages.Items.AddRange(new object[] { - "English", - "Deutsch"}); - this.comboBox_languages.Location = new System.Drawing.Point(74, 12); - this.comboBox_languages.Name = "comboBox_languages"; - this.comboBox_languages.Size = new System.Drawing.Size(153, 21); - this.comboBox_languages.TabIndex = 1; - // - // checkBox_orientImage - // - this.checkBox_orientImage.LanguageKey = "ocr.orient_image"; - this.checkBox_orientImage.Location = new System.Drawing.Point(13, 68); - this.checkBox_orientImage.Name = "checkBox_orientImage"; - this.checkBox_orientImage.PropertyName = "orientimage"; - this.checkBox_orientImage.SectionName = "OCR"; - this.checkBox_orientImage.Size = new System.Drawing.Size(104, 24); - this.checkBox_orientImage.TabIndex = 3; - this.checkBox_orientImage.UseVisualStyleBackColor = true; - // - // checkBox_straightenImage - // - this.checkBox_straightenImage.LanguageKey = "ocr.straighten_image"; - this.checkBox_straightenImage.Location = new System.Drawing.Point(13, 41); - this.checkBox_straightenImage.Name = "checkBox_straightenImage"; - this.checkBox_straightenImage.PropertyName = "straightenImage"; - this.checkBox_straightenImage.SectionName = "OCR"; - this.checkBox_straightenImage.Size = new System.Drawing.Size(109, 24); - this.checkBox_straightenImage.TabIndex = 2; - this.checkBox_straightenImage.UseVisualStyleBackColor = true; - // - // label_language - // - this.label_language.LanguageKey = "ocr.language"; - this.label_language.Location = new System.Drawing.Point(13, 15); - this.label_language.Name = "label_language"; - this.label_language.Size = new System.Drawing.Size(55, 23); - this.label_language.TabIndex = 3; - // - // buttonOK - // - this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonOK.LanguageKey = "OK"; - this.buttonOK.Location = new System.Drawing.Point(12, 98); - this.buttonOK.Name = "buttonOK"; - this.buttonOK.Size = new System.Drawing.Size(104, 23); - this.buttonOK.TabIndex = 4; - this.buttonOK.UseVisualStyleBackColor = true; - this.buttonOK.Click += new System.EventHandler(this.ButtonOKClick); - // - // buttonCancel - // - this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonCancel.LanguageKey = "CANCEL"; - this.buttonCancel.Location = new System.Drawing.Point(128, 98); - this.buttonCancel.Name = "buttonCancel"; - this.buttonCancel.Size = new System.Drawing.Size(104, 23); - this.buttonCancel.TabIndex = 5; - this.buttonCancel.UseVisualStyleBackColor = true; - // - // SettingsForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(244, 135); - this.Controls.Add(this.buttonCancel); - this.Controls.Add(this.buttonOK); - this.Controls.Add(this.label_language); - this.Controls.Add(this.checkBox_straightenImage); - this.Controls.Add(this.checkBox_orientImage); - this.Controls.Add(this.comboBox_languages); - this.LanguageKey = "settings_title"; - this.Name = "SettingsForm"; - this.ResumeLayout(false); - - } - private GreenshotPlugin.Controls.GreenshotLabel label_language; - private GreenshotPlugin.Controls.GreenshotButton buttonCancel; - private GreenshotPlugin.Controls.GreenshotButton buttonOK; - private GreenshotPlugin.Controls.GreenshotCheckBox checkBox_orientImage; - private GreenshotPlugin.Controls.GreenshotCheckBox checkBox_straightenImage; - private System.Windows.Forms.ComboBox comboBox_languages; - } -} diff --git a/GreenshotOCRPlugin/SettingsForm.cs b/GreenshotOCRPlugin/SettingsForm.cs deleted file mode 100644 index 94805f941..000000000 --- a/GreenshotOCRPlugin/SettingsForm.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; - -namespace GreenshotOCRPlugin { - /// - /// Description of SettingsForm. - /// - public partial class SettingsForm : OcrForm { - private readonly OCRConfiguration _config; - - public SettingsForm(string [] languages, OCRConfiguration config) { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - this._config = config; - InitializeComponent(); - AcceptButton = buttonOK; - CancelButton = buttonCancel; - - comboBox_languages.Items.Clear(); - int index=0; - - // Preventing Tracker #3234560, although this should not happen... - string languageFromConfig = "ENGLISH"; - if (config.Language != null) { - languageFromConfig = config.Language; - } - foreach(string availableLanguage in languages) { - string displayLanguage = availableLanguage.Substring(0, 1).ToUpper() + availableLanguage.Substring(1).ToLower(); - comboBox_languages.Items.Add(displayLanguage); - if (availableLanguage.Equals(languageFromConfig, StringComparison.CurrentCultureIgnoreCase)) { - comboBox_languages.SelectedIndex = index; - } - index++; - } - } - - private void ButtonOKClick(object sender, EventArgs e) { - string selectedString = (string) comboBox_languages.SelectedItem; - if (selectedString != null) { - _config.Language = selectedString.ToUpper(); - } - } - } -} diff --git a/GreenshotOfficePlugin/Com/Ole32Api.cs b/GreenshotOfficePlugin/Com/Ole32Api.cs index 783f48d0d..d80167022 100644 --- a/GreenshotOfficePlugin/Com/Ole32Api.cs +++ b/GreenshotOfficePlugin/Com/Ole32Api.cs @@ -27,21 +27,6 @@ namespace GreenshotOfficePlugin.Com return clsId; } - /// - /// This converts a clsid (Class ID) into a ProgID (program ID) - /// - /// Guid with the clsid (Class ID) - /// string with the progid - public static string ProgIdFromClassId(Guid clsId) - { - if (ProgIDFromCLSID(ref clsId, out string progId).Succeeded()) - { - return progId; - } - - return null; - } - /// /// See more here /// @@ -50,14 +35,5 @@ namespace GreenshotOfficePlugin.Com /// HResult [DllImport("ole32.dll", ExactSpelling = true)] private static extern HResult CLSIDFromProgID([In] [MarshalAs(UnmanagedType.LPWStr)] string progId, [Out] out Guid clsId); - - /// - /// See more here - /// - /// Guid The CLSID for which the ProgID is to be requested. - /// string the ProgID string. The string that represents clsid includes enclosing braces. - /// HResult - [DllImport("ole32.dll")] - private static extern HResult ProgIDFromCLSID([In] ref Guid clsId, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgId); } } diff --git a/GreenshotOfficePlugin/OfficeInterop/OfficeVersions.cs b/GreenshotOfficePlugin/OfficeInterop/OfficeVersions.cs index 03943e4db..3988148c5 100644 --- a/GreenshotOfficePlugin/OfficeInterop/OfficeVersions.cs +++ b/GreenshotOfficePlugin/OfficeInterop/OfficeVersions.cs @@ -29,14 +29,6 @@ namespace GreenshotOfficePlugin.OfficeInterop /// Office97 = 8, /// - /// Office 2000 - /// - Office2000 = 9, - /// - /// Office 2002 - /// - Office2002 = 10, - /// /// Office 2003 /// Office2003 = 11, diff --git a/GreenshotPhotobucketPlugin/LanguageKeys.cs b/GreenshotPhotobucketPlugin/LanguageKeys.cs index b94f13722..010c4fda0 100644 --- a/GreenshotPhotobucketPlugin/LanguageKeys.cs +++ b/GreenshotPhotobucketPlugin/LanguageKeys.cs @@ -22,13 +22,8 @@ namespace GreenshotPhotobucketPlugin { public enum LangKey { upload_menu_item, - settings_title, - label_upload_format, - label_clear, - upload_success, upload_failure, communication_wait, - use_page_link, configure } } diff --git a/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs b/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs index 8136adbff..c852c0c81 100644 --- a/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs +++ b/GreenshotPhotobucketPlugin/PhotobucketConfiguration.cs @@ -47,12 +47,7 @@ namespace GreenshotPhotobucketPlugin { [IniProperty("Username", Description = "The Photobucket api username", ExcludeIfNull = true)] public string Username { get; set; } - public int Credits { - get; - set; - } - - /// + /// /// A form for username/password /// /// bool true if OK was pressed, false if cancel diff --git a/GreenshotPhotobucketPlugin/PhotobucketUtils.cs b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs index 4226e57c4..bb59ff09a 100644 --- a/GreenshotPhotobucketPlugin/PhotobucketUtils.cs +++ b/GreenshotPhotobucketPlugin/PhotobucketUtils.cs @@ -24,6 +24,7 @@ using System.Collections.Generic; using System.Drawing; using System.Xml; using GreenshotPlugin.Core; +using GreenshotPlugin.Core.OAuth; using GreenshotPlugin.IniFile; using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces.Plugin; diff --git a/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj b/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj deleted file mode 100644 index ac827cfec..000000000 --- a/GreenshotPicasaPlugin/GreenshotPicasaPlugin.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - GreenshotPicasaPlugin - GreenshotPicasaPlugin - - - - - PreserveNewest - - - - - - - - - - - \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-ja-JP.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-ja-JP.xml deleted file mode 100644 index ac8216e96..000000000 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-ja-JP.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - リンクをクリップボードへコピー - アップロード後 - Picasa の設定 - Picasa にアップロード - Picasa の設定 - Picasa へのアップロードに成功しました! - Picasa へのアップロード中にエラーが発生しました: - 画像フォーマット - Picasa に接続中です。しばらくお待ち下さい... - - \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-pl-PL.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-pl-PL.xml deleted file mode 100644 index c4be12b84..000000000 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-pl-PL.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - Trwa komunikacja z Picasa. Proszę czekać... - Konfiguruj Picasa - Po wysłaniu - Link do schowka - Format obrazów - Ustawienia Picasa - Wystąpił błąd przy wysyłaniu do Picasa: - Wyślij do Picasa - Wysyłanie obrazu do Picasa powiodło się! - - \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-CN.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-CN.xml deleted file mode 100644 index 38601fc93..000000000 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-CN.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - 正在连接到Picasa。请稍后... - 配置 Picasa - 上传之后 - 复制链接到剪贴板 - 图片格式 - Picasa设置 - 上传到Picasa时发生错误: - 上传到Picasa - 图片已成功上传到了Picasa! - - \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-TW.xml b/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-TW.xml deleted file mode 100644 index a818bc748..000000000 --- a/GreenshotPicasaPlugin/Languages/language_picasaplugin-zh-TW.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - 正在與 Picasa 通訊,請稍候... - 組態 Picasa - 上傳後 - 連結到剪貼簿 - 圖片格式 - Picasa 設定 - 上傳到 Picasa 時發生錯誤: - 上傳到 Picasa - 上傳圖片到 Picasa 成功! - - \ No newline at end of file diff --git a/GreenshotPicasaPlugin/Picasa.png b/GreenshotPicasaPlugin/Picasa.png deleted file mode 100644 index 97b70cf86..000000000 Binary files a/GreenshotPicasaPlugin/Picasa.png and /dev/null differ diff --git a/GreenshotPlugin/Controls/BackgroundForm.cs b/GreenshotPlugin/Controls/BackgroundForm.cs index 5ce737185..9ffe414e1 100644 --- a/GreenshotPlugin/Controls/BackgroundForm.cs +++ b/GreenshotPlugin/Controls/BackgroundForm.cs @@ -20,7 +20,6 @@ */ using System; using System.Drawing; -using System.Threading; using System.Windows.Forms; using GreenshotPlugin.Core; @@ -30,23 +29,8 @@ namespace GreenshotPlugin.Controls { /// public sealed partial class BackgroundForm : Form { private volatile bool _shouldClose; - - private void BackgroundShowDialog() { - ShowDialog(); - } - public static BackgroundForm ShowAndWait(string title, string text) { - BackgroundForm backgroundForm = new BackgroundForm(title, text); - // Show form in background thread - Thread backgroundTask = new Thread (backgroundForm.BackgroundShowDialog); - backgroundForm.Name = "Background form"; - backgroundTask.IsBackground = true; - backgroundTask.SetApartmentState(ApartmentState.STA); - backgroundTask.Start(); - return backgroundForm; - } - - public BackgroundForm(string title, string text){ + public BackgroundForm(string title, string text){ // // The InitializeComponent() call is required for Windows Forms designer support. // diff --git a/GreenshotPlugin/Controls/HotkeyControl.cs b/GreenshotPlugin/Controls/HotkeyControl.cs index cb9f4593a..6f1c6d8d5 100644 --- a/GreenshotPlugin/Controls/HotkeyControl.cs +++ b/GreenshotPlugin/Controls/HotkeyControl.cs @@ -426,11 +426,7 @@ namespace GreenshotPlugin.Controls { _hotkeyHwnd = hWnd; } - public static int RegisterHotKey(string hotkey, HotKeyHandler handler) { - return RegisterHotKey(HotkeyModifiersFromString(hotkey), HotkeyFromString(hotkey),handler); - } - - /// + /// /// Register a hotkey /// /// The modifier, e.g.: Modifiers.CTRL, Modifiers.NONE or Modifiers.ALT @@ -477,21 +473,7 @@ namespace GreenshotPlugin.Controls { KeyHandlers.Clear(); } - public static void UnregisterHotkey(int hotkey) { - bool removeHotkey = false; - foreach(int availableHotkey in KeyHandlers.Keys) { - if (availableHotkey == hotkey) { - UnregisterHotKey(_hotkeyHwnd, hotkey); - removeHotkey = true; - } - } - if (removeHotkey) { - // Remove key handler - KeyHandlers.Remove(hotkey); - } - } - - /// + /// /// Handle WndProc messages for the hotkey /// /// diff --git a/GreenshotPlugin/Controls/OAuthLoginForm.cs b/GreenshotPlugin/Controls/OAuthLoginForm.cs index e2b036f97..998b938bb 100644 --- a/GreenshotPlugin/Controls/OAuthLoginForm.cs +++ b/GreenshotPlugin/Controls/OAuthLoginForm.cs @@ -1,20 +1,20 @@ /* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * + * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -32,9 +32,8 @@ namespace GreenshotPlugin.Controls { public sealed partial class OAuthLoginForm : Form { private static readonly ILog LOG = LogManager.GetLogger(typeof(OAuthLoginForm)); private readonly string _callbackUrl; - private IDictionary _callbackParameters; - - public IDictionary CallbackParameters => _callbackParameters; + + public IDictionary CallbackParameters { get; private set; } public bool IsOk => DialogResult == DialogResult.OK; @@ -94,7 +93,7 @@ namespace GreenshotPlugin.Controls { if (queryParams.Length > 0) { queryParams = NetworkHelper.UrlDecode(queryParams); //Store the Token and Token Secret - _callbackParameters = NetworkHelper.ParseQueryString(queryParams); + CallbackParameters = NetworkHelper.ParseQueryString(queryParams); } DialogResult = DialogResult.OK; } @@ -102,7 +101,7 @@ namespace GreenshotPlugin.Controls { private void AddressTextBox_KeyPress(object sender, KeyPressEventArgs e) { //Cancel the key press so the user can't enter a new url - e.Handled = true; + e.Handled = true; } } } diff --git a/GreenshotPlugin/Controls/SaveImageFileDialog.cs b/GreenshotPlugin/Controls/SaveImageFileDialog.cs index 0245dc05e..a27eccd15 100644 --- a/GreenshotPlugin/Controls/SaveImageFileDialog.cs +++ b/GreenshotPlugin/Controls/SaveImageFileDialog.cs @@ -53,11 +53,7 @@ namespace GreenshotPlugin.Controls { } } - public SaveImageFileDialog() { - Init(); - } - - public SaveImageFileDialog(ICaptureDetails captureDetails) { + public SaveImageFileDialog(ICaptureDetails captureDetails) { _captureDetails = captureDetails; Init(); } diff --git a/GreenshotPlugin/Controls/ThumbnailForm.cs b/GreenshotPlugin/Controls/ThumbnailForm.cs index 3578b63d3..aae16b46c 100644 --- a/GreenshotPlugin/Controls/ThumbnailForm.cs +++ b/GreenshotPlugin/Controls/ThumbnailForm.cs @@ -22,6 +22,7 @@ using System; using System.Windows.Forms; using GreenshotPlugin.Core; using System.Drawing; +using GreenshotPlugin.Core.Enums; using GreenshotPlugin.IniFile; using GreenshotPlugin.UnmanagedHelpers; using GreenshotPlugin.UnmanagedHelpers.Enums; @@ -32,7 +33,7 @@ namespace GreenshotPlugin.Controls { /// This form allows us to show a Thumbnail preview of a window near the context menu when selecting a window to capture. /// Didn't make it completely "generic" yet, but at least most logic is in here so we don't have it in the mainform. /// - public class ThumbnailForm : FormWithoutActivation { + public sealed class ThumbnailForm : FormWithoutActivation { private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); private IntPtr _thumbnailHandle = IntPtr.Zero; @@ -59,12 +60,13 @@ namespace GreenshotPlugin.Controls { base.Hide(); } - private void UnregisterThumbnail() { - if (_thumbnailHandle != IntPtr.Zero) { - DWM.DwmUnregisterThumbnail(_thumbnailHandle); - _thumbnailHandle = IntPtr.Zero; - } - } + private void UnregisterThumbnail() + { + if (_thumbnailHandle == IntPtr.Zero) return; + + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + _thumbnailHandle = IntPtr.Zero; + } /// /// Show the thumbnail of the supplied window above (or under) the parent Control @@ -75,41 +77,60 @@ namespace GreenshotPlugin.Controls { UnregisterThumbnail(); DWM.DwmRegisterThumbnail(Handle, window.Handle, out _thumbnailHandle); - if (_thumbnailHandle != IntPtr.Zero) { - DWM.DwmQueryThumbnailSourceSize(_thumbnailHandle, out var sourceSize); - int thumbnailHeight = 200; - int thumbnailWidth = (int)(thumbnailHeight * (sourceSize.Width / (float)sourceSize.Height)); - if (parentControl != null && thumbnailWidth > parentControl.Width) { - thumbnailWidth = parentControl.Width; - thumbnailHeight = (int)(thumbnailWidth * (sourceSize.Height / (float)sourceSize.Width)); - } - Width = thumbnailWidth; - Height = thumbnailHeight; - // Prepare the displaying of the Thumbnail - DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES - { - Opacity = 255, - Visible = true, - SourceClientAreaOnly = false, - Destination = new RECT(0, 0, thumbnailWidth, thumbnailHeight) - }; - DWM.DwmUpdateThumbnailProperties(_thumbnailHandle, ref props); - if (parentControl != null) { - AlignToControl(parentControl); - } + if (_thumbnailHandle == IntPtr.Zero) return; - if (!Visible) { - Show(); - } - // Make sure it's on "top"! - if (parentControl != null) { - User32.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE); - } - } - } + var result = DWM.DwmQueryThumbnailSourceSize(_thumbnailHandle, out var sourceSize); + if (result.Failed()) + { + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + return; + } + + if (sourceSize.IsEmpty) + { + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + return; + } + + int thumbnailHeight = 200; + int thumbnailWidth = (int)(thumbnailHeight * (sourceSize.Width / (float)sourceSize.Height)); + if (parentControl != null && thumbnailWidth > parentControl.Width) + { + thumbnailWidth = parentControl.Width; + thumbnailHeight = (int)(thumbnailWidth * (sourceSize.Height / (float)sourceSize.Width)); + } + Width = thumbnailWidth; + Height = thumbnailHeight; + // Prepare the displaying of the Thumbnail + var dwmThumbnailProperties = new DWM_THUMBNAIL_PROPERTIES + { + Opacity = 255, + Visible = true, + SourceClientAreaOnly = false, + Destination = new RECT(0, 0, thumbnailWidth, thumbnailHeight) + }; + result = DWM.DwmUpdateThumbnailProperties(_thumbnailHandle, ref dwmThumbnailProperties); + if (result.Failed()) + { + DWM.DwmUnregisterThumbnail(_thumbnailHandle); + return; + } + + if (parentControl != null) { + AlignToControl(parentControl); + } + + if (!Visible) { + Show(); + } + // Make sure it's on "top"! + if (parentControl != null) { + User32.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE); + } + } public void AlignToControl(Control alignTo) { - Rectangle screenBounds = WindowCapture.GetScreenBounds(); + var screenBounds = WindowCapture.GetScreenBounds(); if (screenBounds.Contains(alignTo.Left, alignTo.Top - Height)) { Location = new Point(alignTo.Left + (alignTo.Width / 2) - (Width / 2), alignTo.Top - Height); } else { diff --git a/GreenshotPlugin/Core/AccessibleHelper.cs b/GreenshotPlugin/Core/AccessibleHelper.cs index 871892e64..36d9e0ed5 100644 --- a/GreenshotPlugin/Core/AccessibleHelper.cs +++ b/GreenshotPlugin/Core/AccessibleHelper.cs @@ -91,35 +91,7 @@ namespace GreenshotPlugin.Core { } } - public void ActivateIETab(string tabCaptionToActivate) { - foreach (Accessible accessor in Children) { - foreach (var child in accessor.Children) { - foreach (var tab in child.Children) { - if (tab.Name == tabCaptionToActivate) { - tab.Activate(); - return; - } - } - } - } - } - - public void CloseIETab(string tabCaptionToClose) { - foreach (Accessible accessor in Children) { - foreach (var child in accessor.Children) { - foreach (var tab in child.Children) { - if (tab.Name == tabCaptionToClose) { - foreach (var CloseTab in tab.Children) { - CloseTab.Activate(); - } - return; - } - } - } - } - } - - public void ActivateIETab(int tabIndexToActivate) { + public void ActivateIETab(int tabIndexToActivate) { var index = 0; foreach (Accessible accessor in Children) { foreach (var child in accessor.Children) { @@ -138,50 +110,7 @@ namespace GreenshotPlugin.Core { } } - public string IEActiveTabUrl { - get { - foreach (Accessible accessor in Children) { - foreach (var child in accessor.Children) { - foreach (var tab in child.Children) { - object tabIndex = tab.accessible.get_accState(CHILDID_SELF); - - if ((int)tabIndex == IE_ACTIVE_TAB) { - var description = tab.accessible.get_accDescription(CHILDID_SELF); - - if (!string.IsNullOrEmpty(description)) { - if (description.Contains(Environment.NewLine)) { - var url = description.Substring(description.IndexOf(Environment.NewLine)).Trim(); - return url; - } - } - } - } - } - } - return string.Empty; - } - } - - public int IEActiveTabIndex { - get { - var index = 0; - foreach (Accessible accessor in Children) { - foreach (var child in accessor.Children) { - foreach (var tab in child.Children) { - object tabIndex = tab.accessible.get_accState(0); - - if ((int)tabIndex == IE_ACTIVE_TAB) { - return index; - } - index++; - } - } - } - return -1; - } - } - - public string IEActiveTabCaption { + public string IEActiveTabCaption { get { foreach (Accessible accessor in Children) { foreach (var child in accessor.Children) { @@ -238,21 +167,8 @@ namespace GreenshotPlugin.Core { } } } - - public int IETabCount { - get { - foreach (Accessible accessor in Children) { - foreach (var child in accessor.Children) { - foreach (var tab in child.Children) { - return child.ChildCount - 1; - } - } - } - return 0; - } - } - private Accessible(IAccessible acc) { + private Accessible(IAccessible acc) { accessible = acc ?? throw new Exception(); } diff --git a/GreenshotPlugin/Core/Capture.cs b/GreenshotPlugin/Core/Capture.cs index 95a7fb872..2b0180de2 100644 --- a/GreenshotPlugin/Core/Capture.cs +++ b/GreenshotPlugin/Core/Capture.cs @@ -1,5 +1,25 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + using System; -using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using GreenshotPlugin.Interfaces; @@ -14,7 +34,6 @@ namespace GreenshotPlugin.Core /// public class Capture : ICapture { private static readonly ILog Log = LogManager.GetLogger(typeof(Capture)); - private List _elements = new List(); private Rectangle _screenBounds; /// @@ -178,15 +197,6 @@ namespace GreenshotPlugin.Core // TODO: Remove invisible lines/words? CaptureDetails.OcrInformation?.Offset(-cropRectangle.Location.X, -cropRectangle.Location.Y); - // Remove invisible elements - var visibleElements = new List(); - foreach(var captureElement in _elements) { - if (captureElement.Bounds.IntersectsWith(cropRectangle)) { - visibleElements.Add(captureElement); - } - } - _elements = visibleElements; - return true; } diff --git a/GreenshotPlugin/Core/CaptureDetails.cs b/GreenshotPlugin/Core/CaptureDetails.cs index f6e0474ea..c600ced26 100644 --- a/GreenshotPlugin/Core/CaptureDetails.cs +++ b/GreenshotPlugin/Core/CaptureDetails.cs @@ -1,3 +1,24 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + using System; using System.Collections.Generic; using GreenshotPlugin.Interfaces; diff --git a/GreenshotPlugin/Core/CaptureElement.cs b/GreenshotPlugin/Core/CaptureElement.cs deleted file mode 100644 index 6b0f3ab73..000000000 --- a/GreenshotPlugin/Core/CaptureElement.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using System.Drawing; -using GreenshotPlugin.Interfaces; - -namespace GreenshotPlugin.Core -{ - /// - /// A class representing an element in the capture - /// - public class CaptureElement : ICaptureElement { - public CaptureElement(Rectangle bounds) { - Bounds = bounds; - } - public CaptureElement(string name) { - Name = name; - } - public CaptureElement(string name, Rectangle bounds) { - Name = name; - Bounds = bounds; - } - - public List Children { get; set; } = new List(); - - public string Name { - get; - set; - } - public Rectangle Bounds { - get; - set; - } - - // CaptureElements are regarded equal if their bounds are equal. this should be sufficient. - public override bool Equals(object obj) { - if (obj == null || GetType() != obj.GetType()) - { - return false; - } - - return obj is CaptureElement other && Bounds.Equals(other.Bounds); - } - - public override int GetHashCode() { - // TODO: Fix this, this is not right... - return Bounds.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/ClipboardHelper.cs b/GreenshotPlugin/Core/ClipboardHelper.cs index 046838716..2d675d24e 100644 --- a/GreenshotPlugin/Core/ClipboardHelper.cs +++ b/GreenshotPlugin/Core/ClipboardHelper.cs @@ -34,7 +34,9 @@ using System.Runtime.InteropServices; using GreenshotPlugin.IniFile; using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces.Plugin; +using GreenshotPlugin.Interop; using log4net; +using HtmlDocument = HtmlAgilityPack.HtmlDocument; namespace GreenshotPlugin.Core { /// @@ -45,7 +47,8 @@ namespace GreenshotPlugin.Core { private static readonly object ClipboardLockObject = new object(); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); private static readonly string FORMAT_FILECONTENTS = "FileContents"; - private static readonly string FORMAT_PNG = "PNG"; + private static readonly string FORMAT_HTML = "text/html"; + private static readonly string FORMAT_PNG = "PNG"; private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art"; private static readonly string FORMAT_17 = "Format17"; private static readonly string FORMAT_JPG = "JPG"; @@ -207,17 +210,8 @@ EndSelection:<<<<<<<4 } return null; } - - /// - /// Wrapper for Clipboard.ContainsText, Created for Bug #3432313 - /// - /// boolean if there is text on the clipboard - public static bool ContainsText() { - IDataObject clipboardData = GetDataObject(); - return ContainsText(clipboardData); - } - /// + /// /// Test if the IDataObject contains Text /// /// @@ -246,41 +240,124 @@ EndSelection:<<<<<<<4 /// /// true if an image is there public static bool ContainsImage(IDataObject dataObject) { - if (dataObject != null) { - if (dataObject.GetDataPresent(DataFormats.Bitmap) - || dataObject.GetDataPresent(DataFormats.Dib) - || dataObject.GetDataPresent(DataFormats.Tiff) - || dataObject.GetDataPresent(DataFormats.EnhancedMetafile) - || dataObject.GetDataPresent(FORMAT_PNG) - || dataObject.GetDataPresent(FORMAT_17) - || dataObject.GetDataPresent(FORMAT_JPG) - || dataObject.GetDataPresent(FORMAT_JFIF) - || dataObject.GetDataPresent(FORMAT_JPEG) - || dataObject.GetDataPresent(FORMAT_GIF)) { - return true; - } - var imageFiles = GetImageFilenames(dataObject); - if (imageFiles.Any()) { - return true; - } - if (dataObject.GetDataPresent(FORMAT_FILECONTENTS)) { - try { - MemoryStream imageStream = dataObject.GetData(FORMAT_FILECONTENTS) as MemoryStream; - if (IsValidStream(imageStream)) { - using (ImageHelper.FromStream(imageStream)) - { - // If we get here, there is an image - return true; - } - } - } catch (Exception) { - // Ignore - } - } - } - return false; + if (dataObject == null) return false; + + if (dataObject.GetDataPresent(DataFormats.Bitmap) + || dataObject.GetDataPresent(DataFormats.Dib) + || dataObject.GetDataPresent(DataFormats.Tiff) + || dataObject.GetDataPresent(DataFormats.EnhancedMetafile) + || dataObject.GetDataPresent(FORMAT_PNG) + || dataObject.GetDataPresent(FORMAT_17) + || dataObject.GetDataPresent(FORMAT_JPG) + || dataObject.GetDataPresent(FORMAT_JFIF) + || dataObject.GetDataPresent(FORMAT_JPEG) + || dataObject.GetDataPresent(FORMAT_GIF)) { + return true; + } + + var imageFiles = GetImageFilenames(dataObject); + if (imageFiles.Any()) { + return true; + } + + var fileDescriptor = (MemoryStream)dataObject.GetData("FileGroupDescriptorW"); + var files = FileDescriptorReader.Read(fileDescriptor); + var fileIndex = 0; + foreach (var fileContentFile in files) + { + if ((fileContentFile.FileAttributes & FileAttributes.Directory) != 0) + { + //Do something with directories? + //Note that directories do not have FileContents + //And will throw if we try to read them + continue; + } + + var fileData = FileDescriptorReader.GetFileContents(dataObject, fileIndex); + try + { + //Do something with the fileContent Stream + if (IsValidStream(fileData)) + { + fileData.Position = 0; + using (ImageHelper.FromStream(fileData)) + { + // If we get here, there is an image + return true; + } + } + } + finally + { + fileData?.Dispose(); + } + fileIndex++; + } + + if (dataObject.GetDataPresent(FORMAT_FILECONTENTS)) + { + try + { + var clipboardContent = dataObject.GetData(FORMAT_FILECONTENTS, true); + var imageStream = clipboardContent as MemoryStream; + if (IsValidStream(imageStream)) + { + using (ImageHelper.FromStream(imageStream)) + { + // If we get here, there is an image + return true; + } + } + } + catch (Exception) + { + // Ignore + } + } + + // Try to get the image from the HTML code + var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8); + if (textObject != null) + { + var doc = new HtmlDocument(); + doc.LoadHtml(textObject); + var imgNodes = doc.DocumentNode.SelectNodes("//img"); + if (imgNodes != null) + { + foreach (var imgNode in imgNodes) + { + var srcAttribute = imgNode.Attributes["src"]; + var imageUrl = srcAttribute.Value; + if (!string.IsNullOrEmpty(imageUrl)) + { + return true; + } + } + } + } + return false; } + /// + /// Get the specified IDataObject format as a string + /// + /// IDataObject + /// string + /// Encoding + /// sting + private static string ContentAsString(IDataObject dataObject, string format, Encoding encoding = null) + { + encoding ??= Encoding.Unicode; + var objectAsFormat = dataObject.GetData(format); + return objectAsFormat switch + { + null => null, + string text => text, + MemoryStream ms => encoding.GetString(ms.ToArray()), + _ => null + }; + } + /// /// Simple helper to check the stream /// @@ -348,9 +425,9 @@ EndSelection:<<<<<<<4 if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib)) { // Outlook ?? Log.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front..."); - retrieveFormats = new[] { DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF }; + retrieveFormats = new[] { DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF, FORMAT_HTML }; } else { - retrieveFormats = new[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_GIF }; + retrieveFormats = new[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_17, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JPEG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP, FORMAT_FILECONTENTS, FORMAT_GIF, FORMAT_HTML }; } foreach (string currentFormat in retrieveFormats) { if (formats != null && formats.Contains(currentFormat)) { @@ -376,8 +453,32 @@ EndSelection:<<<<<<<4 /// IDataObject /// Image or null private static Image GetImageForFormat(string format, IDataObject dataObject) { + if (format == FORMAT_HTML) + { + var textObject = ContentAsString(dataObject, FORMAT_HTML, Encoding.UTF8); + if (textObject != null) + { + var doc = new HtmlDocument(); + doc.LoadHtml(textObject); + var imgNodes = doc.DocumentNode.SelectNodes("//img"); + if (imgNodes != null) + { + foreach (var imgNode in imgNodes) + { + var srcAttribute = imgNode.Attributes["src"]; + var imageUrl = srcAttribute.Value; + Log.Debug(imageUrl); + var image = NetworkHelper.DownloadImage(imageUrl); + if (image != null) + { + return image; + } + } + } + } + } object clipboardObject = GetFromDataObject(dataObject, format); - MemoryStream imageStream = clipboardObject as MemoryStream; + var imageStream = clipboardObject as MemoryStream; if (!IsValidStream(imageStream)) { // TODO: add "HTML Format" support here... return clipboardObject as Image; @@ -390,14 +491,14 @@ EndSelection:<<<<<<<4 { byte[] dibBuffer = new byte[imageStream.Length]; imageStream.Read(dibBuffer, 0, dibBuffer.Length); - BITMAPINFOHEADER infoHeader = BinaryStructHelper.FromByteArray(dibBuffer); + var infoHeader = BinaryStructHelper.FromByteArray(dibBuffer); if (!infoHeader.IsDibV5) { Log.InfoFormat("Using special DIB - /// Wrapper for Clipboard.GetText created for Bug #3432313 - /// - /// string if there is text on the clipboard - public static string GetText() { - return GetText(GetDataObject()); - } - - /// + /// /// Get Text from the DataObject /// /// string if there is text on the clipboard @@ -706,16 +800,8 @@ EndSelection:<<<<<<<4 // Use false to make the object disappear when the application stops. SetDataObject(dataObj, true); } - - /// - /// Retrieve a list of all formats currently on the clipboard - /// - /// List of strings with the current formats - public static List GetFormats() { - return GetFormats(GetDataObject()); - } - /// + /// /// Retrieve a list of all formats currently in the IDataObject /// /// List of string with the current formats @@ -732,16 +818,7 @@ EndSelection:<<<<<<<4 return new List(); } - /// - /// Check if there is currently something in the dataObject which has the supplied format - /// - /// string with format - /// true if one the format is found - public static bool ContainsFormat(string format) { - return ContainsFormat(GetDataObject(), new[]{format}); - } - - /// + /// /// Check if there is currently something on the clipboard which has the supplied format /// /// IDataObject @@ -781,17 +858,7 @@ EndSelection:<<<<<<<4 return formatFound; } - /// - /// Get Object of type Type from the clipboard - /// - /// Type to get - /// object from clipboard - public static object GetClipboardData(Type type) { - string format = type.FullName; - return GetClipboardData(format); - } - - /// + /// /// Get Object for format from IDataObject /// /// IDataObject @@ -837,14 +904,5 @@ EndSelection:<<<<<<<4 } return null; } - - /// - /// Get Object for format from the clipboard - /// - /// format to get - /// object from clipboard - public static object GetClipboardData(string format) { - return GetFromDataObject(GetDataObject(), format); - } - } + } } diff --git a/GreenshotPlugin/Core/CoreConfiguration.cs b/GreenshotPlugin/Core/CoreConfiguration.cs index bf2570ce9..9a5ef5270 100644 --- a/GreenshotPlugin/Core/CoreConfiguration.cs +++ b/GreenshotPlugin/Core/CoreConfiguration.cs @@ -305,25 +305,7 @@ namespace GreenshotPlugin.Core { [IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")] public int WebRequestReadWriteTimeout { get; set; } - /// - /// Specifies what THIS build is - /// - public BuildStates BuildState { - get { - string informationalVersion = Application.ProductVersion; - if (informationalVersion != null) { - if (informationalVersion.ToLowerInvariant().Contains("-rc")) { - return BuildStates.RELEASE_CANDIDATE; - } - if (informationalVersion.ToLowerInvariant().Contains("-unstable")) { - return BuildStates.UNSTABLE; - } - } - return BuildStates.RELEASE; - } - } - - public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32; + public bool UseLargeIcons => IconSize.Width >= 32 || IconSize.Height >= 32; /// /// A helper method which returns true if the supplied experimental feature is enabled diff --git a/GreenshotPlugin/Core/CredentialsHelper.cs b/GreenshotPlugin/Core/CredentialsHelper.cs index 95426e934..49b720b25 100644 --- a/GreenshotPlugin/Core/CredentialsHelper.cs +++ b/GreenshotPlugin/Core/CredentialsHelper.cs @@ -242,68 +242,14 @@ namespace GreenshotPlugin.Core { } } - /// Shows the credentials dialog. - /// Returns a DialogResult indicating the user action. - public DialogResult Show() { - return Show(null, Name, Password, SaveChecked); - } - - /// Shows the credentials dialog with the specified save checkbox status. - /// True if the save checkbox is checked. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(bool saveChecked) { - return Show(null, Name, Password, saveChecked); - } - - /// Shows the credentials dialog with the specified name. + /// Shows the credentials dialog with the specified name. /// The name for the credentials. /// Returns a DialogResult indicating the user action. public DialogResult Show(string name) { return Show(null, name, Password, SaveChecked); } - /// Shows the credentials dialog with the specified name and password. - /// The name for the credentials. - /// The password for the credentials. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(string name, string password) { - return Show(null, name, password, SaveChecked); - } - - /// Shows the credentials dialog with the specified name, password and save checkbox status. - /// The name for the credentials. - /// The password for the credentials. - /// True if the save checkbox is checked. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(string name, string password, bool saveChecked) { - return Show(null, name, password, saveChecked); - } - - /// Shows the credentials dialog with the specified owner. - /// The System.Windows.Forms.IWin32Window the dialog will display in front of. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(IWin32Window owner) { - return Show(owner, Name, Password, SaveChecked); - } - - /// Shows the credentials dialog with the specified owner and save checkbox status. - /// The System.Windows.Forms.IWin32Window the dialog will display in front of. - /// True if the save checkbox is checked. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(IWin32Window owner, bool saveChecked) { - return Show(owner, Name, Password, saveChecked); - } - - /// Shows the credentials dialog with the specified owner, name and password. - /// The System.Windows.Forms.IWin32Window the dialog will display in front of. - /// The name for the credentials. - /// The password for the credentials. - /// Returns a DialogResult indicating the user action. - public DialogResult Show(IWin32Window owner, string name, string password) { - return Show(owner, name, password, SaveChecked); - } - - /// Shows the credentials dialog with the specified owner, name, password and save checkbox status. + /// Shows the credentials dialog with the specified owner, name, password and save checkbox status. /// The System.Windows.Forms.IWin32Window the dialog will display in front of. /// The name for the credentials. /// The password for the credentials. @@ -450,7 +396,6 @@ namespace GreenshotPlugin.Core { public const int MAX_MESSAGE_LENGTH = 100; public const int MAX_CAPTION_LENGTH = 100; public const int MAX_GENERIC_TARGET_LENGTH = 100; - public const int MAX_DOMAIN_TARGET_LENGTH = 100; public const int MAX_USERNAME_LENGTH = 100; public const int MAX_PASSWORD_LENGTH = 100; @@ -463,20 +408,12 @@ namespace GreenshotPlugin.Core { public enum CredFlags { INCORRECT_PASSWORD = 0x1, DO_NOT_PERSIST = 0x2, - REQUEST_ADMINISTRATOR = 0x4, EXCLUDE_CERTIFICATES = 0x8, - REQUIRE_CERTIFICATE = 0x10, SHOW_SAVE_CHECK_BOX = 0x40, ALWAYS_SHOW_UI = 0x80, - REQUIRE_SMARTCARD = 0x100, - PASSWORD_ONLY_OK = 0x200, - VALIDATE_USERNAME = 0x400, - COMPLETE_USERNAME = 0x800, PERSIST = 0x1000, - SERVER_CREDENTIAL = 0x4000, EXPECT_CONFIRMATION = 0x20000, GENERIC_CREDENTIALS = 0x40000, - USERNAME_TARGET_CREDENTIALS = 0x80000, KEEP_USERNAME = 0x100000, } diff --git a/GreenshotPlugin/Core/DpiHelper.cs b/GreenshotPlugin/Core/DpiHelper.cs index 991f2897e..7f98f69a6 100644 --- a/GreenshotPlugin/Core/DpiHelper.cs +++ b/GreenshotPlugin/Core/DpiHelper.cs @@ -1,8 +1,27 @@ -using GreenshotPlugin.Core.Enums; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using GreenshotPlugin.Core.Enums; using GreenshotPlugin.UnmanagedHelpers; -using log4net; using System; -using System.Diagnostics; using System.Drawing; using System.Runtime.InteropServices; using GreenshotPlugin.UnmanagedHelpers.Enums; @@ -16,8 +35,6 @@ namespace GreenshotPlugin.Core /// public static class DpiHelper { - private static readonly ILog Log = LogManager.GetLogger(typeof(DpiHelper)); - /// /// This is the default DPI for the screen /// @@ -59,23 +76,6 @@ namespace GreenshotPlugin.Core return dpiScaleFactor * someNumber; } - /// - /// Scale the supplied number according to the supplied dpi - /// - /// int with e.g. 16 for 16x16 images - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// Scaled width - public static int ScaleWithDpi(int number, uint dpi, Func scaleModifier = null) - { - var dpiScaleFactor = DpiScaleFactor(dpi); - if (scaleModifier != null) - { - dpiScaleFactor = scaleModifier(dpiScaleFactor); - } - return (int)(dpiScaleFactor * number); - } - /// /// Scale the supplied Size according to the supplied dpi /// @@ -93,79 +93,6 @@ namespace GreenshotPlugin.Core return new Size((int)(dpiScaleFactor * size.Width), (int)(dpiScaleFactor * size.Height)); } - /// - /// Scale the supplied NativePoint according to the supplied dpi - /// - /// NativePoint to resize - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// NativePoint scaled - public static Point ScaleWithDpi(Point size, uint dpi, Func scaleModifier = null) - { - var dpiScaleFactor = DpiScaleFactor(dpi); - if (scaleModifier != null) - { - dpiScaleFactor = scaleModifier(dpiScaleFactor); - } - return new Point((int)(dpiScaleFactor * size.X), (int)(dpiScaleFactor * size.Y)); - } - - /// - /// Scale the supplied NativeSizeFloat according to the supplied dpi - /// - /// PointF - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// PointF - public static PointF ScaleWithDpi(PointF point, uint dpi, Func scaleModifier = null) - { - var dpiScaleFactor = DpiScaleFactor(dpi); - if (scaleModifier != null) - { - dpiScaleFactor = scaleModifier(dpiScaleFactor); - } - return new PointF(dpiScaleFactor * point.X, dpiScaleFactor * point.Y); - } - - /// - /// Scale the supplied NativeSizeFloat according to the supplied dpi - /// - /// NativeSizeFloat to resize - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// NativeSize scaled - public static SizeF ScaleWithDpi(SizeF size, uint dpi, Func scaleModifier = null) - { - var dpiScaleFactor = DpiScaleFactor(dpi); - if (scaleModifier != null) - { - dpiScaleFactor = scaleModifier(dpiScaleFactor); - } - return new SizeF(dpiScaleFactor * size.Width, dpiScaleFactor * size.Height); - } - - /// - /// Scale the supplied number to the current dpi - /// - /// double with e.g. a width like 16 for 16x16 images - /// A function which can modify the scale factor - /// double with scaled number - public static float ScaleWithCurrentDpi(float someNumber, Func scaleModifier = null) - { - return ScaleWithDpi(someNumber, Dpi, scaleModifier); - } - - /// - /// Scale the supplied number to the current dpi - /// - /// int with e.g. a width like 16 for 16x16 images - /// A function which can modify the scale factor - /// int with scaled number - public static int ScaleWithCurrentDpi(int someNumber, Func scaleModifier = null) - { - return ScaleWithDpi(someNumber, Dpi, scaleModifier); - } - /// /// Scale the supplied NativeSize to the current dpi /// @@ -177,282 +104,6 @@ namespace GreenshotPlugin.Core return ScaleWithDpi(size, Dpi, scaleModifier); } - /// - /// Scale the supplied NativeSizeFloat to the current dpi - /// - /// NativeSizeFloat to scale - /// A function which can modify the scale factor - /// NativeSizeFloat scaled - public static SizeF ScaleWithCurrentDpi(SizeF size, Func scaleModifier = null) - { - return ScaleWithDpi(size, Dpi, scaleModifier); - } - - /// - /// Scale the supplied NativePoint to the current dpi - /// - /// NativePoint to scale - /// A function which can modify the scale factor - /// NativePoint scaled - public static Point ScaleWithCurrentDpi(Point point, Func scaleModifier = null) - { - return ScaleWithDpi(point, Dpi, scaleModifier); - } - - /// - /// Scale the supplied PointF to the current dpi - /// - /// PointF to scale - /// A function which can modify the scale factor - /// PointF scaled - public static PointF ScaleWithCurrentDpi(PointF point, Func scaleModifier = null) - { - return ScaleWithDpi(point, Dpi, scaleModifier); - } - - /// - /// Calculate a DPI unscale factor - /// - /// uint - /// float - public static float DpiUnscaleFactor(uint dpi) - { - return (float)DefaultScreenDpi / dpi; - } - - /// - /// Unscale the supplied number according to the supplied dpi - /// - /// double with e.g. the scaled width - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// double with the unscaled number - public static float UnscaleWithDpi(float someNumber, uint dpi, Func scaleModifier = null) - { - var dpiUnscaleFactor = DpiUnscaleFactor(dpi); - if (scaleModifier != null) - { - dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor); - } - return dpiUnscaleFactor * someNumber; - } - - /// - /// Unscale the supplied number according to the supplied dpi - /// - /// int with a scaled width - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// Unscaled width - public static int UnscaleWithDpi(int number, uint dpi, Func scaleModifier = null) - { - var dpiUnscaleFactor = DpiUnscaleFactor(dpi); - if (scaleModifier != null) - { - dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor); - } - return (int)(dpiUnscaleFactor * number); - } - - /// - /// Unscale the supplied NativeSize according to the supplied dpi - /// - /// NativeSize to unscale - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// Size unscaled - public static Size UnscaleWithDpi(Size size, uint dpi, Func scaleModifier = null) - { - var dpiUnscaleFactor = DpiUnscaleFactor(dpi); - if (scaleModifier != null) - { - dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor); - } - return new Size((int)(dpiUnscaleFactor * size.Width), (int)(dpiUnscaleFactor * size.Height)); - } - - /// - /// Unscale the supplied Point according to the supplied dpi - /// - /// Point to unscale - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// Point unscaled - public static Point UnscaleWithDpi(Point point, uint dpi, Func scaleModifier = null) - { - var dpiUnscaleFactor = DpiUnscaleFactor(dpi); - if (scaleModifier != null) - { - dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor); - } - return new Point((int)(dpiUnscaleFactor * point.X), (int)(dpiUnscaleFactor * point.Y)); - } - - /// - /// unscale the supplied NativeSizeFloat according to the supplied dpi - /// - /// NativeSizeFloat to resize - /// current dpi, normal is 96. - /// A function which can modify the scale factor - /// SizeF unscaled - public static SizeF UnscaleWithDpi(SizeF size, uint dpi, Func scaleModifier = null) - { - float dpiUnscaleFactor = DpiUnscaleFactor(dpi); - if (scaleModifier != null) - { - dpiUnscaleFactor = scaleModifier(dpiUnscaleFactor); - } - return new SizeF(dpiUnscaleFactor * size.Width, dpiUnscaleFactor * size.Height); - } - - /// - /// Unscale the supplied number to the current dpi - /// - /// double with e.g. a width like 16 for 16x16 images - /// A function which can modify the scale factor - /// double with unscaled number - public static float UnscaleWithCurrentDpi(float someNumber, Func scaleModifier = null) - { - return UnscaleWithDpi(someNumber, Dpi, scaleModifier); - } - - /// - /// Unscale the supplied number to the current dpi - /// - /// int with e.g. a width like 16 for 16x16 images - /// A function which can modify the scale factor - /// int with unscaled number - public static int UnscaleWithCurrentDpi(int someNumber, Func scaleModifier = null) - { - return UnscaleWithDpi(someNumber, Dpi, scaleModifier); - } - - /// - /// Unscale the supplied NativeSize to the current dpi - /// - /// Size to unscale - /// A function which can modify the scale factor - /// Size unscaled - public static Size UnscaleWithCurrentDpi(Size size, Func scaleModifier = null) - { - return UnscaleWithDpi(size, Dpi, scaleModifier); - } - - /// - /// Unscale the supplied NativeSizeFloat to the current dpi - /// - /// NativeSizeFloat to unscale - /// A function which can modify the scale factor - /// NativeSizeFloat unscaled - public static SizeF UnscaleWithCurrentDpi(SizeF size, Func scaleModifier = null) - { - return UnscaleWithDpi(size, Dpi, scaleModifier); - } - - /// - /// Unscale the supplied NativePoint to the current dpi - /// - /// NativePoint to unscale - /// A function which can modify the scale factor - /// NativePoint unscaled - public static Point UnscaleWithCurrentDpi(Point point, Func scaleModifier = null) - { - return UnscaleWithDpi(point, Dpi, scaleModifier); - } - - /// - /// Unscale the supplied NativePointFloat to the current dpi - /// - /// NativePointFloat to unscale - /// A function which can modify the scale factor - /// NativePointFloat unscaled - public static PointF UnscaleWithCurrentDpi(PointF point, Func scaleModifier = null) - { - return ScaleWithDpi(point, Dpi, scaleModifier); - } - - /// - /// public wrapper for EnableNonClientDpiScaling, this also checks if the function is available. - /// - /// IntPtr - /// true if it worked - public static bool TryEnableNonClientDpiScaling(IntPtr hWnd) - { - // EnableNonClientDpiScaling is only available on Windows 10 and later - if (!WindowsVersion.IsWindows10OrLater) - { - return false; - } - - var result = EnableNonClientDpiScaling(hWnd); - if (result.Succeeded()) - { - return true; - } - - var error = Win32.GetLastErrorCode(); - if (Log.IsDebugEnabled) - { - Log.DebugFormat("Error enabling non client dpi scaling : {0}", Win32.GetMessage(error)); - } - - return false; - } - - /// - /// Make the current process DPI Aware, this should be done via the manifest but sometimes this is not possible. - /// - /// bool true if it was possible to change the DPI awareness - public static bool EnableDpiAware() - { - // We can only test this for Windows 8.1 or later - if (!WindowsVersion.IsWindows81OrLater) - { - Log.Debug("An application can only be DPI aware starting with Window 8.1 and later."); - return false; - } - - if (WindowsVersion.IsWindows10BuildOrLater(15063)) - { - if (IsValidDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2)) - { - SetProcessDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2); - } - else - { - SetProcessDpiAwarenessContext(DpiAwarenessContext.PerMonitorAwareV2); - } - - return true; - } - return SetProcessDpiAwareness(DpiAwareness.PerMonitorAware).Succeeded(); - } - - /// - /// Check if the process is DPI Aware, an DpiHandler doesn't make sense if not. - /// - public static bool IsDpiAware - { - get - { - // We can only test this for Windows 8.1 or later - if (!WindowsVersion.IsWindows81OrLater) - { - Log.Debug("An application can only be DPI aware starting with Window 8.1 and later."); - return false; - } - - using var process = Process.GetCurrentProcess(); - GetProcessDpiAwareness(process.Handle, out var dpiAwareness); - if (Log.IsDebugEnabled) - { - Log.DebugFormat("Process {0} has a Dpi awareness {1}", process.ProcessName, dpiAwareness); - } - - return dpiAwareness != DpiAwareness.Unaware && dpiAwareness != DpiAwareness.Invalid; - } - } - /// /// Return the DPI for the screen which the location is located on /// @@ -510,40 +161,6 @@ namespace GreenshotPlugin.Core return (uint)GDI32.GetDeviceCaps(hdc, DeviceCaps.LOGPIXELSX); } - /// - /// See details GetProcessDpiAwareness function - /// Retrieves the dots per inch (dpi) awareness of the specified process. - /// - /// IntPtr with handle of the process that is being queried. If this parameter is NULL, the current process is queried. - /// out DpiAwareness - The DPI awareness of the specified process. Possible values are from the PROCESS_DPI_AWARENESS enumeration. - /// HResult - [DllImport("shcore")] - private static extern HResult GetProcessDpiAwareness(IntPtr processHandle, out DpiAwareness value); - - /// - /// Sets the current process to a specified dots per inch (dpi) awareness level. The DPI awareness levels are from the PROCESS_DPI_AWARENESS enumeration. - /// See SetProcessDpiAwareness function - /// - /// DpiAwareness - /// HResult - [DllImport("shcore")] - private static extern HResult SetProcessDpiAwareness(DpiAwareness dpiAwareness); - - /// - /// It is recommended that you set the process-default DPI awareness via application manifest. See Setting the default DPI awareness for a process for more information. Setting the process-default DPI awareness via API call can lead to unexpected application behavior. - /// - /// Sets the current process to a specified dots per inch (dpi) awareness context. The DPI awareness contexts are from the DPI_AWARENESS_CONTEXT value. - /// Remarks: - /// This API is a more advanced version of the previously existing SetProcessDpiAwareness API, allowing for the process default to be set to the finer-grained DPI_AWARENESS_CONTEXT values. Most importantly, this allows you to programmatically set Per Monitor v2 as the process default value, which is not possible with the previous API. - /// - /// This method sets the default DPI_AWARENESS_CONTEXT for all threads within an application. Individual threads can have their DPI awareness changed from the default with the SetThreadDpiAwarenessContext method. - /// See SetProcessDpiAwarenessContext function - /// - /// DpiAwarenessContext - /// bool - [DllImport("User32.dll", SetLastError = true)] - private static extern bool SetProcessDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext); - /// /// See more at GetDpiForWindow function /// Returns the dots per inch (dpi) value for the associated window. @@ -566,14 +183,6 @@ namespace GreenshotPlugin.Core [DllImport("shcore.dll", SetLastError = true)] private static extern HResult GetDpiForMonitor(IntPtr hMonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY); - /// - /// See EnableNonClientDpiScaling function - /// - /// IntPtr - /// bool - [DllImport("User32.dll", SetLastError = true)] - private static extern HResult EnableNonClientDpiScaling(IntPtr hWnd); - /// /// See GetDpiForSystem function /// Returns the system DPI. @@ -581,151 +190,5 @@ namespace GreenshotPlugin.Core /// uint with the system DPI [DllImport("User32.dll")] private static extern uint GetDpiForSystem(); - - /// - /// Converts a point in a window from logical coordinates into physical coordinates, regardless of the dots per inch (dpi) awareness of the caller. For more information about DPI awareness levels, see PROCESS_DPI_AWARENESS. - /// See more at LogicalToPhysicalPointForPerMonitorDPI function - /// - /// IntPtr A handle to the window whose transform is used for the conversion. - /// A pointer to a POINT structure that specifies the logical coordinates to be converted. The new physical coordinates are copied into this structure if the function succeeds. - /// bool - [DllImport("User32.dll")] - private static extern bool LogicalToPhysicalPointForPerMonitorDPI(IntPtr hWnd, ref POINT point); - - /// - /// Converts a point in a window from logical coordinates into physical coordinates, regardless of the dots per inch (dpi) awareness of the caller. For more information about DPI awareness levels, see PROCESS_DPI_AWARENESS. - /// See more at PhysicalToLogicalPointForPerMonitorDPI function - /// - /// IntPtr A handle to the window whose transform is used for the conversion. - /// NativePoint A pointer to a POINT structure that specifies the physical/screen coordinates to be converted. The new logical coordinates are copied into this structure if the function succeeds. - /// bool - [DllImport("User32.dll")] - private static extern bool PhysicalToLogicalPointForPerMonitorDPI(IntPtr hWnd, ref POINT point); - - /// - /// See SystemParametersInfo function - /// Retrieves the value of one of the system-wide parameters, taking into account the provided DPI value. - /// - /// - /// SystemParametersInfoActions The system-wide parameter to be retrieved. - /// This function is only intended for use with SPI_GETICONTITLELOGFONT, SPI_GETICONMETRICS, or SPI_GETNONCLIENTMETRICS. See SystemParametersInfo for more information on these values. - /// - /// - /// A parameter whose usage and format depends on the system parameter being queried or set. For more - /// information about system-wide parameters, see the uiAction parameter. If not otherwise indicated, you must specify - /// zero for this parameter. - /// - /// IntPtr - /// SystemParametersInfoBehaviors - /// uint with dpi value - /// bool - [DllImport("User32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool SystemParametersInfoForDpi(SystemParametersInfoActions uiAction, uint uiParam, IntPtr pvParam, SystemParametersInfoBehaviors fWinIni, uint dpi); - - /// - /// See GetThreadDpiAwarenessContext function - /// Gets the DPI_AWARENESS_CONTEXT for the current thread. - /// - /// This method will return the latest DPI_AWARENESS_CONTEXT sent to SetThreadDpiAwarenessContext. If SetThreadDpiAwarenessContext was never called for this thread, then the return value will equal the default DPI_AWARENESS_CONTEXT for the process. - /// - /// DpiAwarenessContext - [DllImport("User32.dll")] - private static extern DpiAwarenessContext GetThreadDpiAwarenessContext(); - - /// - /// Set the DPI awareness for the current thread to the provided value. - /// - /// DpiAwarenessContext the new value for the current thread - /// DpiAwarenessContext previous value - [DllImport("User32.dll")] - private static extern DpiAwarenessContext SetThreadDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext); - - /// - /// Retrieves the DpiAwareness value from a DpiAwarenessContext. - /// - /// DpiAwarenessContext - /// DpiAwareness - [DllImport("User32.dll")] - private static extern DpiAwareness GetAwarenessFromDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext); - - /// - /// Retrieves the DPI from a given DPI_AWARENESS_CONTEXT handle. This enables you to determine the DPI of a thread without needed to examine a window created within that thread. - /// - /// DpiAwarenessContext - /// uint with dpi value - [DllImport("User32.dll")] - private static extern uint GetDpiFromDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext); - - /// - /// Determines if a specified DPI_AWARENESS_CONTEXT is valid and supported by the current system. - /// - /// DpiAwarenessContext The context that you want to determine if it is supported. - /// bool true if supported otherwise false - [DllImport("User32.dll")] - private static extern bool IsValidDpiAwarenessContext(DpiAwarenessContext dpiAwarenessContext); - - /// - /// Returns the DPI_HOSTING_BEHAVIOR of the specified window. - /// - /// This API allows you to examine the hosting behavior of a window after it has been created. A window's hosting behavior is the hosting behavior of the thread in which the window was created, as set by a call to SetThreadDpiHostingBehavior. This is a permanent value and cannot be changed after the window is created, even if the thread's hosting behavior is changed. - /// - /// DpiHostingBehavior - [DllImport("User32.dll")] - private static extern DpiHostingBehavior GetWindowDpiHostingBehavior(); - - /// - /// See more at SetThreadDpiHostingBehavior function - /// Sets the thread's DPI_HOSTING_BEHAVIOR. This behavior allows windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT. - /// - /// DPI_HOSTING_BEHAVIOR enables a mixed content hosting behavior, which allows parent windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT value. This property only effects new windows created within this thread while the mixed hosting behavior is active. A parent window with this hosting behavior is able to host child windows with different DPI_AWARENESS_CONTEXT values, regardless of whether the child windows have mixed hosting behavior enabled. - /// - /// This hosting behavior does not allow for windows with per-monitor DPI_AWARENESS_CONTEXT values to be hosted until windows with DPI_AWARENESS_CONTEXT values of system or unaware. - /// - /// To avoid unexpected outcomes, a thread's DPI_HOSTING_BEHAVIOR should be changed to support mixed hosting behaviors only when creating a new window which needs to support those behaviors. Once that window is created, the hosting behavior should be switched back to its default value. - /// - /// This API is used to change the thread's DPI_HOSTING_BEHAVIOR from its default value. This is only necessary if your app needs to host child windows from plugins and third-party components that do not support per-monitor-aware context. This is most likely to occur if you are updating complex applications to support per-monitor DPI_AWARENESS_CONTEXT behaviors. - /// - /// Enabling mixed hosting behavior will not automatically adjust the thread's DPI_AWARENESS_CONTEXT to be compatible with legacy content. The thread's awareness context must still be manually changed before new windows are created to host such content. - /// - /// DpiHostingBehavior - /// previous DpiHostingBehavior - [DllImport("User32.dll")] - private static extern DpiHostingBehavior SetThreadDpiHostingBehavior(DpiHostingBehavior dpiHostingBehavior); - - /// - ///Retrieves the DPI_HOSTING_BEHAVIOR from the current thread. - /// - /// DpiHostingBehavior - [DllImport("User32.dll")] - private static extern DpiHostingBehavior GetThreadDpiHostingBehavior(); - - /// - /// Overrides the default per-monitor DPI scaling behavior of a child window in a dialog. - /// This function returns TRUE if the operation was successful, and FALSE otherwise. To get extended error information, call GetLastError. - /// - /// Possible errors are ERROR_INVALID_HANDLE if passed an invalid HWND, and ERROR_ACCESS_DENIED if the windows belongs to another process. - /// - /// The behaviors are specified as values from the DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS enum. This function follows the typical two-parameter approach to setting flags, where a mask specifies the subset of the flags to be changed. - /// - /// It is valid to set these behaviors on any window. It does not matter if the window is currently a child of a dialog at the point in time that SetDialogControlDpiChangeBehavior is called. The behaviors are retained and will take effect only when the window is an immediate child of a dialog that has per-monitor DPI scaling enabled. - /// - /// This API influences individual controls within dialogs. The dialog-wide per-monitor DPI scaling behavior is controlled by SetDialogDpiChangeBehavior. - /// - /// IntPtr A handle for the window whose behavior will be modified. - /// DialogScalingBehaviors A mask specifying the subset of flags to be changed. - /// DialogScalingBehaviors The desired value to be set for the specified subset of flags. - /// bool - [DllImport("User32.dll")] - private static extern bool SetDialogControlDpiChangeBehavior(IntPtr hWnd, DialogScalingBehaviors mask, DialogScalingBehaviors values); - - /// - /// Retrieves and per-monitor DPI scaling behavior overrides of a child window in a dialog. - /// The flags set on the given window. If passed an invalid handle, this function will return zero, and set its last error to ERROR_INVALID_HANDLE. - /// - /// IntPtr A handle for the window whose behavior will be modified. - /// DialogScalingBehaviors - [DllImport("User32.dll")] - private static extern DialogScalingBehaviors GetDialogControlDpiChangeBehavior(IntPtr hWnd); } } diff --git a/GreenshotPlugin/Core/EnumExtensions.cs b/GreenshotPlugin/Core/EnumExtensions.cs deleted file mode 100644 index 1bda1071f..000000000 --- a/GreenshotPlugin/Core/EnumExtensions.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -using System; -namespace GreenshotPlugin.Core { - public static class EnumerationExtensions { - public static bool Has(this Enum type, T value) { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try { - if (underlyingType == typeof(int)) { - return (((int)(object)type & (int)(object)value) == (int)(object)value); - } else if (underlyingType == typeof(uint)) { - return (((uint)(object)type & (uint)(object)value) == (uint)(object)value); - } - } - catch - { - // ignored - } - return false; - } - - public static bool Is(this Enum type, T value) { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try - { - if (underlyingType == typeof(int)) { - return (int)(object)type == (int)(object)value; - } - if (underlyingType == typeof(uint)) { - return (uint)(object)type == (uint)(object)value; - } - } - catch - { - // ignored - } - return false; - } - - /// - /// Add a flag to an enum - /// - /// - /// - /// - public static T Add(this Enum type, T value) { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try - { - if (underlyingType == typeof(int)) { - return (T)(object)(((int)(object)type | (int)(object)value)); - } - if (underlyingType == typeof(uint)) { - return (T)(object)(((uint)(object)type | (uint)(object)value)); - } - } catch(Exception ex) { - throw new ArgumentException($"Could not append value '{value}' to enumerated type '{typeof(T).Name}'.", ex); - } - throw new ArgumentException($"Could not append value '{value}' to enumerated type '{typeof(T).Name}'."); - } - - /// - /// Remove a flag from an enum type - /// - /// - /// - /// - public static T Remove(this Enum type, T value) { - Type underlyingType = Enum.GetUnderlyingType(value.GetType()); - try - { - if (underlyingType == typeof(int)) { - return (T)(object)(((int)(object)type & ~(int)(object)value)); - } - if (underlyingType == typeof(uint)) { - return (T)(object)(((uint)(object)type & ~(uint)(object)value)); - } - } catch(Exception ex) { - throw new ArgumentException($"Could not remove value '{value}' from enumerated type '{typeof(T).Name}'.", ex); - } - throw new ArgumentException($"Could not remove value '{value}' from enumerated type '{typeof(T).Name}'."); - } - } -} diff --git a/GreenshotPlugin/Core/Enums/DialogDpiChangeBehaviors.cs b/GreenshotPlugin/Core/Enums/DialogDpiChangeBehaviors.cs deleted file mode 100644 index fa5b61635..000000000 --- a/GreenshotPlugin/Core/Enums/DialogDpiChangeBehaviors.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Dapplo and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; - -namespace GreenshotPlugin.Core.Enums -{ - /// - /// In Per Monitor v2 contexts, dialogs will automatically respond to DPI changes by resizing themselves and re-computing the positions of their child windows (here referred to as re-layouting). This enum works in conjunction with SetDialogDpiChangeBehavior in order to override the default DPI scaling behavior for dialogs. - /// This does not affect DPI scaling behavior for the child windows of dialogs(beyond re-layouting), which is controlled by DIALOG_CONTROL_DPI_CHANGE_BEHAVIORS. - /// - [Flags] - public enum DialogDpiChangeBehaviors - { - /// - /// The default behavior of the dialog manager. In response to a DPI change, the dialog manager will re-layout each control, update the font on each control, resize the dialog, and update the dialog's own font. - /// - Default = 0, - - /// - /// Prevents the dialog manager from responding to WM_GETDPISCALEDSIZE and WM_DPICHANGED, disabling all default DPI scaling behavior. - /// - DisableAll = 1, - - /// - /// Prevents the dialog manager from resizing the dialog in response to a DPI change. - /// - DisableResize = 2, - - /// - /// Prevents the dialog manager from re-layouting all of the dialogue's immediate children HWNDs in response to a DPI change. - /// - DisableControlRelayout = 3 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/Enums/DialogScalingBehaviors.cs b/GreenshotPlugin/Core/Enums/DialogScalingBehaviors.cs deleted file mode 100644 index 4de8e4c35..000000000 --- a/GreenshotPlugin/Core/Enums/DialogScalingBehaviors.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Dapplo and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; - -namespace GreenshotPlugin.Core.Enums -{ - /// - /// Describes per-monitor DPI scaling behavior overrides for child windows within dialogs. The values in this enumeration are bitfields and can be combined. - /// - /// This enum is used with SetDialogControlDpiChangeBehavior in order to override the default per-monitor DPI scaling behavior for a child window within a dialog. - /// - /// These settings only apply to individual controls within dialogs. The dialog-wide per-monitor DPI scaling behavior of a dialog is controlled by DIALOG_DPI_CHANGE_BEHAVIORS. - /// - [Flags] - public enum DialogScalingBehaviors - { - /// - /// The default behavior of the dialog manager. The dialog managed will update the font, size, and position of the child window on DPI changes. - /// - Default = 0, - - /// - /// Prevents the dialog manager from sending an updated font to the child window via WM_SETFONT in response to a DPI change. - /// - DisableFontUpdate = 1, - - /// - /// Prevents the dialog manager from resizing and repositioning the child window in response to a DPI change. - /// - DisableRelayout = 2 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/Enums/DpiAwareness.cs b/GreenshotPlugin/Core/Enums/DpiAwareness.cs deleted file mode 100644 index 7dd22431e..000000000 --- a/GreenshotPlugin/Core/Enums/DpiAwareness.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Dapplo and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace GreenshotPlugin.Core.Enums -{ - /// - /// Identifies the dots per inch (dpi) setting for a thread, process, or window. - /// Can be used everywhere ProcessDpiAwareness is passed. - /// - public enum DpiAwareness - { - /// - /// Invalid DPI awareness. This is an invalid DPI awareness value. - /// - Invalid = -1, - - /// - /// DPI unaware. - /// This process does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI). - /// It will be automatically scaled by the system on any other DPI setting. - /// - Unaware = 0, - - /// - /// System DPI aware. - /// This process does not scale for DPI changes. - /// It will query for the DPI once and use that value for the lifetime of the process. - /// If the DPI changes, the process will not adjust to the new DPI value. - /// It will be automatically scaled up or down by the system when the DPI changes from the system value. - /// - SystemAware = 1, - - /// - /// Per monitor DPI aware. - /// This process checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes. - /// These processes are not automatically scaled by the system. - /// - PerMonitorAware = 2 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/Enums/DpiAwarenessContext.cs b/GreenshotPlugin/Core/Enums/DpiAwarenessContext.cs deleted file mode 100644 index 276d73550..000000000 --- a/GreenshotPlugin/Core/Enums/DpiAwarenessContext.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Dapplo and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace GreenshotPlugin.Core.Enums -{ - /// - /// - public enum DpiAwarenessContext - { - /// - /// DPI unaware. - /// This window does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI). - /// It will be automatically scaled by the system on any other DPI setting. - /// - Unaware = -1, - - /// - /// System DPI aware. - /// This window does not scale for DPI changes. - /// It will query for the DPI once and use that value for the lifetime of the process. - /// If the DPI changes, the process will not adjust to the new DPI value. - /// It will be automatically scaled up or down by the system when the DPI changes from the system value. - /// - SystemAware = -2, - - /// - /// Per monitor DPI aware. - /// This window checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes. - /// These processes are not automatically scaled by the system. - /// - PerMonitorAware = -3, - - /// - /// Also known as Per Monitor v2. An advancement over the original per-monitor DPI awareness mode, which enables applications to access new DPI-related scaling behaviors on a per top-level window basis. - /// Per Monitor v2 was made available in the Creators Update of Windows 10, and is not available on earlier versions of the operating system. - /// The additional behaviors introduced are as follows: - /// * Child window DPI change notifications - In Per Monitor v2 contexts, the entire window tree is notified of any DPI changes that occur. - /// * Scaling of non-client area - All windows will automatically have their non-client area drawn in a DPI sensitive fashion. Calls to EnableNonClientDpiScaling are unnecessary. - /// * Scaling of Win32 menus - All NTUSER menus created in Per Monitor v2 contexts will be scaling in a per-monitor fashion. - /// * Dialog Scaling - Win32 dialogs created in Per Monitor v2 contexts will automatically respond to DPI changes. - /// * Improved scaling of comctl32 controls - Various comctl32 controls have improved DPI scaling behavior in Per Monitor v2 contexts. - /// * Improved theming behavior - UxTheme handles opened in the context of a Per Monitor v2 window will operate in terms of the DPI associated with that window. - /// - PerMonitorAwareV2 = -4 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/Enums/DpiHostingBehavior.cs b/GreenshotPlugin/Core/Enums/DpiHostingBehavior.cs deleted file mode 100644 index 0b0abf686..000000000 --- a/GreenshotPlugin/Core/Enums/DpiHostingBehavior.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Dapplo and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace GreenshotPlugin.Core.Enums -{ - /// - /// Identifies the DPI hosting behavior for a window. - /// This behavior allows windows created in the thread to host child windows with a different DPI_AWARENESS_CONTEXT - /// - public enum DpiHostingBehavior - { - /// - /// Invalid DPI hosting behavior. This usually occurs if the previous SetThreadDpiHostingBehavior call used an invalid parameter. - /// - Invalid = -1, - - /// - /// Default DPI hosting behavior. The associated window behaves as normal, and cannot create or re-parent child windows with a different DPI_AWARENESS_CONTEXT. - /// - Default = 0, - - /// - /// Mixed DPI hosting behavior. This enables the creation and re-parenting of child windows with different DPI_AWARENESS_CONTEXT. These child windows will be independently scaled by the OS. - /// - Mixed = 1 - - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/Enums/HResult.cs b/GreenshotPlugin/Core/Enums/HResult.cs index 40bb62a7b..a1d2036d7 100644 --- a/GreenshotPlugin/Core/Enums/HResult.cs +++ b/GreenshotPlugin/Core/Enums/HResult.cs @@ -28,29 +28,6 @@ namespace GreenshotPlugin.Core.Enums [SuppressMessage("ReSharper", "InconsistentNaming")] public enum HResult { -#pragma warning disable 1591 S_OK = 0, - S_FALSE = 1, - E_FAIL = unchecked((int)0x80004005), - E_INVALIDARG = unchecked((int)0x80070057), - E_NOTIMPL = unchecked((int)0x80004001), - E_POINTER = unchecked((int)0x80004003), - E_PENDING = unchecked((int)0x8000000A), - E_NOINTERFACE = unchecked((int)0x80004002), - E_ABORT = unchecked((int)0x80004004), - E_ACCESSDENIED = unchecked((int)0x80070006), - E_HANDLE = unchecked((int)0x80070006), - E_UNEXPECTED = unchecked((int)0x8000FFFF), - E_FILENOTFOUND = unchecked((int)0x80070002), - E_PATHNOTFOUND = unchecked((int)0x80070003), - E_INVALID_DATA = unchecked((int)0x8007000D), - E_OUTOFMEMORY = unchecked((int)0x8007000E), - E_INSUFFICIENT_BUFFER = unchecked((int)0x8007007A), - WSAECONNABORTED = unchecked((int)0x80072745), - WSAECONNRESET = unchecked((int)0x80072746), - ERROR_TOO_MANY_CMDS = unchecked((int)0x80070038), - ERROR_NOT_SUPPORTED = unchecked((int)0x80070032), - TYPE_E_ELEMENTNOTFOUND = unchecked((int)0x8002802B) -#pragma warning restore 1591 } } diff --git a/GreenshotPlugin/Core/Enums/SystemParametersInfoActions.cs b/GreenshotPlugin/Core/Enums/SystemParametersInfoActions.cs deleted file mode 100644 index 62a4eb5f4..000000000 --- a/GreenshotPlugin/Core/Enums/SystemParametersInfoActions.cs +++ /dev/null @@ -1,1390 +0,0 @@ -// Copyright (c) Dapplo and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.Core.Enums -{ - /// - /// SPI_ System-wide parameter - Used in SystemParametersInfo function - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum SystemParametersInfoActions : uint - { - /// - /// No value - /// - SPI_NONE = 0, - - /// - /// Determines whether the warning beeper is on. - /// The pvParam parameter must point to a BOOL variable that receives TRUE if the beeper is on, or FALSE if it is off. - /// - SPI_GETBEEP = 0x0001, - - /// - /// Turns the warning beeper on or off. The uiParam parameter specifies TRUE for on, or FALSE for off. - /// - SPI_SETBEEP = 0x0002, - - /// - /// Retrieves the two mouse threshold values and the mouse speed. - /// - SPI_GETMOUSE = 0x0003, - - /// - /// Sets the two mouse threshold values and the mouse speed. - /// - SPI_SETMOUSE = 0x0004, - - /// - /// Retrieves the border multiplier factor that determines the width of a window's sizing border. - /// The pvParam parameter must point to an integer variable that receives this value. - /// - SPI_GETBORDER = 0x0005, - - /// - /// Sets the border multiplier factor that determines the width of a window's sizing border. - /// The uiParam parameter specifies the new value. - /// - SPI_SETBORDER = 0x0006, - - /// - /// Retrieves the keyboard repeat-speed setting, which is a value in the range from 0 (approximately 2.5 repetitions - /// per second) - /// through 31 (approximately 30 repetitions per second). The actual repeat rates are hardware-dependent and may vary - /// from - /// a linear scale by as much as 20%. The pvParam parameter must point to a DWORD variable that receives the setting - /// - SPI_GETKEYBOARDSPEED = 0x000A, - - /// - /// Sets the keyboard repeat-speed setting. The uiParam parameter must specify a value in the range from 0 - /// (approximately 2.5 repetitions per second) through 31 (approximately 30 repetitions per second). - /// The actual repeat rates are hardware-dependent and may vary from a linear scale by as much as 20%. - /// If uiParam is greater than 31, the parameter is set to 31. - /// - SPI_SETKEYBOARDSPEED = 0x000B, - - /// - /// Not implemented. - /// - SPI_LANGDRIVER = 0x000C, - - /// - /// Sets or retrieves the width, in pixels, of an icon cell. The system uses this rectangle to arrange icons in large - /// icon view. - /// To set this value, set uiParam to the new value and set pvParam to null. You cannot set this value to less than - /// SM_CXICON. - /// To retrieve this value, pvParam must point to an integer that receives the current value. - /// - SPI_ICONHORIZONTALSPACING = 0x000D, - - /// - /// Retrieves the screen saver time-out value, in seconds. The pvParam parameter must point to an integer variable that - /// receives the value. - /// - SPI_GETSCREENSAVETIMEOUT = 0x000E, - - /// - /// Sets the screen saver time-out value to the value of the uiParam parameter. This value is the amount of time, in - /// seconds, - /// that the system must be idle before the screen saver activates. - /// - SPI_SETSCREENSAVETIMEOUT = 0x000F, - - /// - /// Determines whether screen saving is enabled. The pvParam parameter must point to a bool variable that receives TRUE - /// if screen saving is enabled, or FALSE otherwise. - /// Does not work for Windows 7: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724947(v=vs.85).aspx - /// - SPI_GETSCREENSAVEACTIVE = 0x0010, - - /// - /// Sets the state of the screen saver. The uiParam parameter specifies TRUE to activate screen saving, or FALSE to - /// deactivate it. - /// - SPI_SETSCREENSAVEACTIVE = 0x0011, - - /// - /// Retrieves the current granularity value of the desktop sizing grid. The pvParam parameter must point to an integer - /// variable - /// that receives the granularity. - /// - SPI_GETGRIDGRANULARITY = 0x0012, - - /// - /// Sets the granularity of the desktop sizing grid to the value of the uiParam parameter. - /// - SPI_SETGRIDGRANULARITY = 0x0013, - - /// - /// Sets the desktop wallpaper. The value of the pvParam parameter determines the new wallpaper. To specify a wallpaper - /// bitmap, - /// set pvParam to point to a null-terminated string containing the name of a bitmap file. Setting pvParam to "" - /// removes the wallpaper. - /// Setting pvParam to SETWALLPAPER_DEFAULT or null reverts to the default wallpaper. - /// - SPI_SETDESKWALLPAPER = 0x0014, - - /// - /// Sets the current desktop pattern by causing Windows to read the Pattern= setting from the WIN.INI file. - /// - SPI_SETDESKPATTERN = 0x0015, - - /// - /// Retrieves the keyboard repeat-delay setting, which is a value in the range from 0 (approximately 250 ms delay) - /// through 3 - /// (approximately 1 second delay). The actual delay associated with each value may vary depending on the hardware. The - /// pvParam parameter must point to an integer variable that receives the setting. - /// - SPI_GETKEYBOARDDELAY = 0x0016, - - /// - /// Sets the keyboard repeat-delay setting. The uiParam parameter must specify 0, 1, 2, or 3, where zero sets the - /// shortest delay - /// (approximately 250 ms) and 3 sets the longest delay (approximately 1 second). The actual delay associated with each - /// value may - /// vary depending on the hardware. - /// - SPI_SETKEYBOARDDELAY = 0x0017, - - /// - /// Sets or retrieves the height, in pixels, of an icon cell. - /// To set this value, set uiParam to the new value and set pvParam to null. You cannot set this value to less than - /// SM_CYICON. - /// To retrieve this value, pvParam must point to an integer that receives the current value. - /// - SPI_ICONVERTICALSPACING = 0x0018, - - /// - /// Determines whether icon-title wrapping is enabled. The pvParam parameter must point to a bool variable that - /// receives TRUE - /// if enabled, or FALSE otherwise. - /// - SPI_GETICONTITLEWRAP = 0x0019, - - /// - /// Turns icon-title wrapping on or off. The uiParam parameter specifies TRUE for on, or FALSE for off. - /// - SPI_SETICONTITLEWRAP = 0x001A, - - /// - /// Determines whether pop-up menus are left-aligned or right-aligned, relative to the corresponding menu-bar item. - /// The pvParam parameter must point to a bool variable that receives TRUE if left-aligned, or FALSE otherwise. - /// - SPI_GETMENUDROPALIGNMENT = 0x001B, - - /// - /// Sets the alignment value of pop-up menus. The uiParam parameter specifies TRUE for right alignment, or FALSE for - /// left alignment. - /// - SPI_SETMENUDROPALIGNMENT = 0x001C, - - /// - /// Sets the width of the double-click rectangle to the value of the uiParam parameter. - /// The double-click rectangle is the rectangle within which the second click of a double-click must fall for it to be - /// registered - /// as a double-click. - /// To retrieve the width of the double-click rectangle, call GetSystemMetrics with the SM_CXDOUBLECLK flag. - /// - SPI_SETDOUBLECLKWIDTH = 0x001D, - - /// - /// Sets the height of the double-click rectangle to the value of the uiParam parameter. - /// The double-click rectangle is the rectangle within which the second click of a double-click must fall for it to be - /// registered - /// as a double-click. - /// To retrieve the height of the double-click rectangle, call GetSystemMetrics with the SM_CYDOUBLECLK flag. - /// - SPI_SETDOUBLECLKHEIGHT = 0x001E, - - /// - /// Retrieves the logical font information for the current icon-title font. The uiParam parameter specifies the size of - /// a LOGFONT structure, - /// and the pvParam parameter must point to the LOGFONT structure to fill in. - /// - SPI_GETICONTITLELOGFONT = 0x001F, - - /// - /// Sets the double-click time for the mouse to the value of the uiParam parameter. The double-click time is the - /// maximum number - /// of milliseconds that can occur between the first and second clicks of a double-click. You can also call the - /// SetDoubleClickTime - /// function to set the double-click time. To get the current double-click time, call the GetDoubleClickTime function. - /// - SPI_SETDOUBLECLICKTIME = 0x0020, - - /// - /// Swaps or restores the meaning of the left and right mouse buttons. The uiParam parameter specifies TRUE to swap the - /// meanings - /// of the buttons, or FALSE to restore their original meanings. - /// - SPI_SETMOUSEBUTTONSWAP = 0x0021, - - /// - /// Sets the font that is used for icon titles. The uiParam parameter specifies the size of a LOGFONT structure, - /// and the pvParam parameter must point to a LOGFONT structure. - /// - SPI_SETICONTITLELOGFONT = 0x0022, - - /// - /// This flag is obsolete. Previous versions of the system use this flag to determine whether ALT+TAB fast task - /// switching is enabled. - /// For Windows 95, Windows 98, and Windows NT version 4.0 and later, fast task switching is always enabled. - /// - SPI_GETFASTTASKSWITCH = 0x0023, - - /// - /// This flag is obsolete. Previous versions of the system use this flag to enable or disable ALT+TAB fast task - /// switching. - /// For Windows 95, Windows 98, and Windows NT version 4.0 and later, fast task switching is always enabled. - /// - SPI_SETFASTTASKSWITCH = 0x0024, - - /// - /// Sets dragging of full windows either on or off. The uiParam parameter specifies TRUE for on, or FALSE for off. - /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION. - /// - SPI_SETDRAGFULLWINDOWS = 0x0025, - - /// - /// Determines whether dragging of full windows is enabled. The pvParam parameter must point to a BOOL variable that - /// receives TRUE - /// if enabled, or FALSE otherwise. - /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION. - /// - SPI_GETDRAGFULLWINDOWS = 0x0026, - - /// - /// Retrieves the metrics associated with the nonclient area of nonminimized windows. The pvParam parameter must point - /// to a NONCLIENTMETRICS structure that receives the information. Set the cbSize member of this structure and the - /// uiParam parameter - /// to sizeof(NONCLIENTMETRICS). - /// - SPI_GETNONCLIENTMETRICS = 0x0029, - - /// - /// Sets the metrics associated with the nonclient area of nonminimized windows. The pvParam parameter must point - /// to a NONCLIENTMETRICS structure that contains the new parameters. Set the cbSize member of this structure - /// and the uiParam parameter to sizeof(NONCLIENTMETRICS). Also, the lfHeight member of the LOGFONT structure must be a - /// negative value. - /// - SPI_SETNONCLIENTMETRICS = 0x002A, - - /// - /// Retrieves the metrics associated with minimized windows. The pvParam parameter must point to a MINIMIZEDMETRICS - /// structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(MINIMIZEDMETRICS). - /// - SPI_GETMINIMIZEDMETRICS = 0x002B, - - /// - /// Sets the metrics associated with minimized windows. The pvParam parameter must point to a MINIMIZEDMETRICS - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(MINIMIZEDMETRICS). - /// - SPI_SETMINIMIZEDMETRICS = 0x002C, - - /// - /// Retrieves the metrics associated with icons. The pvParam parameter must point to an ICONMETRICS structure that - /// receives - /// the information. Set the cbSize member of this structure and the uiParam parameter to sizeof(ICONMETRICS). - /// - SPI_GETICONMETRICS = 0x002D, - - /// - /// Sets the metrics associated with icons. The pvParam parameter must point to an ICONMETRICS structure that contains - /// the new parameters. Set the cbSize member of this structure and the uiParam parameter to sizeof(ICONMETRICS). - /// - SPI_SETICONMETRICS = 0x002E, - - /// - /// Sets the size of the work area. The work area is the portion of the screen not obscured by the system taskbar - /// or by application desktop toolbars. The pvParam parameter is a pointer to a RECT structure that specifies the new - /// work area rectangle, - /// expressed in virtual screen coordinates. In a system with multiple display monitors, the function sets the work - /// area - /// of the monitor that contains the specified rectangle. - /// - SPI_SETWORKAREA = 0x002F, - - /// - /// Retrieves the size of the work area on the primary display monitor. The work area is the portion of the screen not - /// obscured - /// by the system taskbar or by application desktop toolbars. The pvParam parameter must point to a RECT structure that - /// receives - /// the coordinates of the work area, expressed in virtual screen coordinates. - /// To get the work area of a monitor other than the primary display monitor, call the GetMonitorInfo function. - /// - SPI_GETWORKAREA = 0x0030, - - /// - /// Windows Me/98/95: Pen windows is being loaded or unloaded. The uiParam parameter is TRUE when loading and FALSE - /// when unloading pen windows. The pvParam parameter is null. - /// - SPI_SETPENWINDOWS = 0x0031, - - /// - /// Retrieves information about the HighContrast accessibility feature. The pvParam parameter must point to a - /// HIGHCONTRAST structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(HIGHCONTRAST). - /// For a general discussion, see remarks. - /// Windows NT: This value is not supported. - /// - /// - /// There is a difference between the High Contrast color scheme and the High Contrast Mode. The High Contrast color - /// scheme changes - /// the system colors to colors that have obvious contrast; you switch to this color scheme by using the Display - /// Options in the control panel. - /// The High Contrast Mode, which uses SPI_GETHIGHCONTRAST and SPI_SETHIGHCONTRAST, advises applications to modify - /// their appearance - /// for visually-impaired users. It involves such things as audible warning to users and customized color scheme - /// (using the Accessibility Options in the control panel). For more information, see HIGHCONTRAST on MSDN. - /// For more information on general accessibility features, see Accessibility on MSDN. - /// - SPI_GETHIGHCONTRAST = 0x0042, - - /// - /// Sets the parameters of the HighContrast accessibility feature. The pvParam parameter must point to a HIGHCONTRAST - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(HIGHCONTRAST). - /// Windows NT: This value is not supported. - /// - SPI_SETHIGHCONTRAST = 0x0043, - - /// - /// Determines whether the user relies on the keyboard instead of the mouse, and wants applications to display keyboard - /// interfaces - /// that would otherwise be hidden. The pvParam parameter must point to a BOOL variable that receives TRUE - /// if the user relies on the keyboard; or FALSE otherwise. - /// Windows NT: This value is not supported. - /// - SPI_GETKEYBOARDPREF = 0x0044, - - /// - /// Sets the keyboard preference. The uiParam parameter specifies TRUE if the user relies on the keyboard instead of - /// the mouse, - /// and wants applications to display keyboard interfaces that would otherwise be hidden; uiParam is FALSE otherwise. - /// Windows NT: This value is not supported. - /// - SPI_SETKEYBOARDPREF = 0x0045, - - /// - /// Determines whether a screen reviewer utility is running. A screen reviewer utility directs textual information to - /// an output device, - /// such as a speech synthesizer or Braille display. When this flag is set, an application should provide textual - /// information - /// in situations where it would otherwise present the information graphically. - /// The pvParam parameter is a pointer to a BOOL variable that receives TRUE if a screen reviewer utility is running, - /// or FALSE otherwise. - /// Windows NT: This value is not supported. - /// - SPI_GETSCREENREADER = 0x0046, - - /// - /// Determines whether a screen review utility is running. The uiParam parameter specifies TRUE for on, or FALSE for - /// off. - /// Windows NT: This value is not supported. - /// - SPI_SETSCREENREADER = 0x0047, - - /// - /// Retrieves the animation effects associated with user actions. The pvParam parameter must point to an ANIMATIONINFO - /// structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(ANIMATIONINFO). - /// - SPI_GETANIMATION = 0x0048, - - /// - /// Sets the animation effects associated with user actions. The pvParam parameter must point to an ANIMATIONINFO - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(ANIMATIONINFO). - /// - SPI_SETANIMATION = 0x0049, - - /// - /// Determines whether the font smoothing feature is enabled. This feature uses font antialiasing to make font curves - /// appear smoother - /// by painting pixels at different gray levels. - /// The pvParam parameter must point to a BOOL variable that receives TRUE if the feature is enabled, or FALSE if it is - /// not. - /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION. - /// - SPI_GETFONTSMOOTHING = 0x004A, - - /// - /// Enables or disables the font smoothing feature, which uses font antialiasing to make font curves appear smoother - /// by painting pixels at different gray levels. - /// To enable the feature, set the uiParam parameter to TRUE. To disable the feature, set uiParam to FALSE. - /// Windows 95: This flag is supported only if Windows Plus! is installed. See SPI_GETWINDOWSEXTENSION. - /// - SPI_SETFONTSMOOTHING = 0x004B, - - /// - /// Sets the width, in pixels, of the rectangle used to detect the start of a drag operation. Set uiParam to the new - /// value. - /// To retrieve the drag width, call GetSystemMetrics with the SM_CXDRAG flag. - /// - SPI_SETDRAGWIDTH = 0x004C, - - /// - /// Sets the height, in pixels, of the rectangle used to detect the start of a drag operation. Set uiParam to the new - /// value. - /// To retrieve the drag height, call GetSystemMetrics with the SM_CYDRAG flag. - /// - SPI_SETDRAGHEIGHT = 0x004D, - - /// - /// Used internally; applications should not use this value. - /// - SPI_SETHANDHELD = 0x004E, - - /// - /// Retrieves the time-out value for the low-power phase of screen saving. The pvParam parameter must point to an - /// integer variable - /// that receives the value. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_GETLOWPOWERTIMEOUT = 0x004F, - - /// - /// Retrieves the time-out value for the power-off phase of screen saving. The pvParam parameter must point to an - /// integer variable - /// that receives the value. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_GETPOWEROFFTIMEOUT = 0x0050, - - /// - /// Sets the time-out value, in seconds, for the low-power phase of screen saving. The uiParam parameter specifies the - /// new value. - /// The pvParam parameter must be null. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_SETLOWPOWERTIMEOUT = 0x0051, - - /// - /// Sets the time-out value, in seconds, for the power-off phase of screen saving. The uiParam parameter specifies the - /// new value. - /// The pvParam parameter must be null. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_SETPOWEROFFTIMEOUT = 0x0052, - - /// - /// Determines whether the low-power phase of screen saving is enabled. The pvParam parameter must point to a BOOL - /// variable - /// that receives TRUE if enabled, or FALSE if disabled. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_GETLOWPOWERACTIVE = 0x0053, - - /// - /// Determines whether the power-off phase of screen saving is enabled. The pvParam parameter must point to a BOOL - /// variable - /// that receives TRUE if enabled, or FALSE if disabled. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_GETPOWEROFFACTIVE = 0x0054, - - /// - /// Activates or deactivates the low-power phase of screen saving. Set uiParam to 1 to activate, or zero to deactivate. - /// The pvParam parameter must be null. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_SETLOWPOWERACTIVE = 0x0055, - - /// - /// Activates or deactivates the power-off phase of screen saving. Set uiParam to 1 to activate, or zero to deactivate. - /// The pvParam parameter must be null. This flag is supported for 32-bit applications only. - /// Windows NT, Windows Me/98: This flag is supported for 16-bit and 32-bit applications. - /// Windows 95: This flag is supported for 16-bit applications only. - /// - SPI_SETPOWEROFFACTIVE = 0x0056, - - /// - /// Reloads the system cursors. Set the uiParam parameter to zero and the pvParam parameter to null. - /// - SPI_SETCURSORS = 0x0057, - - /// - /// Reloads the system icons. Set the uiParam parameter to zero and the pvParam parameter to null. - /// - SPI_SETICONS = 0x0058, - - /// - /// Retrieves the input locale identifier for the system default input language. The pvParam parameter must point - /// to an HKL variable that receives this value. For more information, see Languages, Locales, and Keyboard Layouts on - /// MSDN. - /// - SPI_GETDEFAULTINPUTLANG = 0x0059, - - /// - /// Sets the default input language for the system shell and applications. The specified language must be displayable - /// using the current system character set. The pvParam parameter must point to an HKL variable that contains - /// the input locale identifier for the default language. For more information, see Languages, Locales, and Keyboard - /// Layouts on MSDN. - /// - SPI_SETDEFAULTINPUTLANG = 0x005A, - - /// - /// Sets the hot key set for switching between input languages. The uiParam and pvParam parameters are not used. - /// The value sets the shortcut keys in the keyboard property sheets by reading the registry again. The registry must - /// be set before this flag is used. the path in the registry is \HKEY_CURRENT_USER\keyboard layout\toggle. Valid - /// values are "1" = ALT+SHIFT, "2" = CTRL+SHIFT, and "3" = none. - /// - SPI_SETLANGTOGGLE = 0x005B, - - /// - /// Windows 95: Determines whether the Windows extension, Windows Plus!, is installed. Set the uiParam parameter to 1. - /// The pvParam parameter is not used. The function returns TRUE if the extension is installed, or FALSE if it is not. - /// - SPI_GETWINDOWSEXTENSION = 0x005C, - - /// - /// Enables or disables the Mouse Trails feature, which improves the visibility of mouse cursor movements by briefly - /// showing - /// a trail of cursors and quickly erasing them. - /// To disable the feature, set the uiParam parameter to zero or 1. To enable the feature, set uiParam to a value - /// greater than 1 - /// to indicate the number of cursors drawn in the trail. - /// Windows 2000/NT: This value is not supported. - /// - SPI_SETMOUSETRAILS = 0x005D, - - /// - /// Determines whether the Mouse Trails feature is enabled. This feature improves the visibility of mouse cursor - /// movements - /// by briefly showing a trail of cursors and quickly erasing them. - /// The pvParam parameter must point to an integer variable that receives a value. If the value is zero or 1, the - /// feature is disabled. - /// If the value is greater than 1, the feature is enabled and the value indicates the number of cursors drawn in the - /// trail. - /// The uiParam parameter is not used. - /// Windows 2000/NT: This value is not supported. - /// - SPI_GETMOUSETRAILS = 0x005E, - - /// - /// Windows Me/98: Used internally; applications should not use this flag. - /// - SPI_SETSCREENSAVERRUNNING = 0x0061, - - /// - /// Same as SPI_SETSCREENSAVERRUNNING. - /// - SPI_SCREENSAVERRUNNING = SPI_SETSCREENSAVERRUNNING, - //#endif /* WINVER >= 0x0400 */ - - /// - /// Retrieves information about the FilterKeys accessibility feature. The pvParam parameter must point to a FILTERKEYS - /// structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(FILTERKEYS). - /// - SPI_GETFILTERKEYS = 0x0032, - - /// - /// Sets the parameters of the FilterKeys accessibility feature. The pvParam parameter must point to a FILTERKEYS - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(FILTERKEYS). - /// - SPI_SETFILTERKEYS = 0x0033, - - /// - /// Retrieves information about the ToggleKeys accessibility feature. The pvParam parameter must point to a TOGGLEKEYS - /// structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(TOGGLEKEYS). - /// - SPI_GETTOGGLEKEYS = 0x0034, - - /// - /// Sets the parameters of the ToggleKeys accessibility feature. The pvParam parameter must point to a TOGGLEKEYS - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(TOGGLEKEYS). - /// - SPI_SETTOGGLEKEYS = 0x0035, - - /// - /// Retrieves information about the MouseKeys accessibility feature. The pvParam parameter must point to a MOUSEKEYS - /// structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(MOUSEKEYS). - /// - SPI_GETMOUSEKEYS = 0x0036, - - /// - /// Sets the parameters of the MouseKeys accessibility feature. The pvParam parameter must point to a MOUSEKEYS - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(MOUSEKEYS). - /// - SPI_SETMOUSEKEYS = 0x0037, - - /// - /// Determines whether the Show Sounds accessibility flag is on or off. If it is on, the user requires an application - /// to present information visually in situations where it would otherwise present the information only in audible - /// form. - /// The pvParam parameter must point to a BOOL variable that receives TRUE if the feature is on, or FALSE if it is off. - /// Using this value is equivalent to calling GetSystemMetrics (SM_SHOWSOUNDS). That is the recommended call. - /// - SPI_GETSHOWSOUNDS = 0x0038, - - /// - /// Sets the parameters of the SoundSentry accessibility feature. The pvParam parameter must point to a SOUNDSENTRY - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(SOUNDSENTRY). - /// - SPI_SETSHOWSOUNDS = 0x0039, - - /// - /// Retrieves information about the StickyKeys accessibility feature. The pvParam parameter must point to a STICKYKEYS - /// structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(STICKYKEYS). - /// - SPI_GETSTICKYKEYS = 0x003A, - - /// - /// Sets the parameters of the StickyKeys accessibility feature. The pvParam parameter must point to a STICKYKEYS - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(STICKYKEYS). - /// - SPI_SETSTICKYKEYS = 0x003B, - - /// - /// Retrieves information about the time-out period associated with the accessibility features. The pvParam parameter - /// must point - /// to an ACCESSTIMEOUT structure that receives the information. Set the cbSize member of this structure and the - /// uiParam parameter - /// to sizeof(ACCESSTIMEOUT). - /// - SPI_GETACCESSTIMEOUT = 0x003C, - - /// - /// Sets the time-out period associated with the accessibility features. The pvParam parameter must point to an - /// ACCESSTIMEOUT - /// structure that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(ACCESSTIMEOUT). - /// - SPI_SETACCESSTIMEOUT = 0x003D, - - /// - /// Windows Me/98/95: Retrieves information about the SerialKeys accessibility feature. The pvParam parameter must - /// point - /// to a SERIALKEYS structure that receives the information. Set the cbSize member of this structure and the uiParam - /// parameter - /// to sizeof(SERIALKEYS). - /// Windows Server 2003, Windows XP/2000/NT: Not supported. The user controls this feature through the control panel. - /// - SPI_GETSERIALKEYS = 0x003E, - - /// - /// Windows Me/98/95: Sets the parameters of the SerialKeys accessibility feature. The pvParam parameter must point - /// to a SERIALKEYS structure that contains the new parameters. Set the cbSize member of this structure and the uiParam - /// parameter - /// to sizeof(SERIALKEYS). - /// Windows Server 2003, Windows XP/2000/NT: Not supported. The user controls this feature through the control panel. - /// - SPI_SETSERIALKEYS = 0x003F, - //#endif /* WINVER >= 0x0400 */ - - /// - /// Retrieves information about the SoundSentry accessibility feature. The pvParam parameter must point to a - /// SOUNDSENTRY structure - /// that receives the information. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(SOUNDSENTRY). - /// - SPI_GETSOUNDSENTRY = 0x0040, - - /// - /// Sets the parameters of the SoundSentry accessibility feature. The pvParam parameter must point to a SOUNDSENTRY - /// structure - /// that contains the new parameters. Set the cbSize member of this structure and the uiParam parameter to - /// sizeof(SOUNDSENTRY). - /// - SPI_SETSOUNDSENTRY = 0x0041, - - /// - /// Determines whether the snap-to-default-button feature is enabled. If enabled, the mouse cursor automatically moves - /// to the default button, such as OK or Apply, of a dialog box. The pvParam parameter must point to a BOOL variable - /// that receives TRUE if the feature is on, or FALSE if it is off. - /// Windows 95: Not supported. - /// - SPI_GETSNAPTODEFBUTTON = 0x005F, - - /// - /// Enables or disables the snap-to-default-button feature. If enabled, the mouse cursor automatically moves to the - /// default button, - /// such as OK or Apply, of a dialog box. Set the uiParam parameter to TRUE to enable the feature, or FALSE to disable - /// it. - /// Applications should use the ShowWindow function when displaying a dialog box so the dialog manager can position the - /// mouse cursor. - /// Windows 95: Not supported. - /// - SPI_SETSNAPTODEFBUTTON = 0x0060, - - /// - /// Retrieves the width, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent - /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the width. - /// Windows 95: Not supported. - /// - SPI_GETMOUSEHOVERWIDTH = 0x0062, - - /// - /// Retrieves the width, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent - /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the width. - /// Windows 95: Not supported. - /// - SPI_SETMOUSEHOVERWIDTH = 0x0063, - - /// - /// Retrieves the height, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent - /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the height. - /// Windows 95: Not supported. - /// - SPI_GETMOUSEHOVERHEIGHT = 0x0064, - - /// - /// Sets the height, in pixels, of the rectangle within which the mouse pointer has to stay for TrackMouseEvent - /// to generate a WM_MOUSEHOVER message. Set the uiParam parameter to the new height. - /// Windows 95: Not supported. - /// - SPI_SETMOUSEHOVERHEIGHT = 0x0065, - - /// - /// Retrieves the time, in milliseconds, that the mouse pointer has to stay in the hover rectangle for TrackMouseEvent - /// to generate a WM_MOUSEHOVER message. The pvParam parameter must point to a UINT variable that receives the time. - /// Windows 95: Not supported. - /// - SPI_GETMOUSEHOVERTIME = 0x0066, - - /// - /// Sets the time, in milliseconds, that the mouse pointer has to stay in the hover rectangle for TrackMouseEvent - /// to generate a WM_MOUSEHOVER message. This is used only if you pass HOVER_DEFAULT in the dwHoverTime parameter in - /// the call to TrackMouseEvent. Set the uiParam parameter to the new time. - /// Windows 95: Not supported. - /// - SPI_SETMOUSEHOVERTIME = 0x0067, - - /// - /// Retrieves the number of lines to scroll when the mouse wheel is rotated. The pvParam parameter must point - /// to a UINT variable that receives the number of lines. The default value is 3. - /// Windows 95: Not supported. - /// - SPI_GETWHEELSCROLLLINES = 0x0068, - - /// - /// Sets the number of lines to scroll when the mouse wheel is rotated. The number of lines is set from the uiParam - /// parameter. - /// The number of lines is the suggested number of lines to scroll when the mouse wheel is rolled without using - /// modifier keys. - /// If the number is 0, then no scrolling should occur. If the number of lines to scroll is greater than the number of - /// lines viewable, - /// and in particular if it is WHEEL_PAGESCROLL (#defined as UINT_MAX), the scroll operation should be interpreted - /// as clicking once in the page down or page up regions of the scroll bar. - /// Windows 95: Not supported. - /// - SPI_SETWHEELSCROLLLINES = 0x0069, - - /// - /// Retrieves the time, in milliseconds, that the system waits before displaying a shortcut menu when the mouse cursor - /// is - /// over a submenu item. The pvParam parameter must point to a DWORD variable that receives the time of the delay. - /// Windows 95: Not supported. - /// - SPI_GETMENUSHOWDELAY = 0x006A, - - /// - /// Sets uiParam to the time, in milliseconds, that the system waits before displaying a shortcut menu when the mouse - /// cursor is - /// over a submenu item. - /// Windows 95: Not supported. - /// - SPI_SETMENUSHOWDELAY = 0x006B, - - /// - /// Determines whether the IME status window is visible (on a per-user basis). The pvParam parameter must point to a - /// BOOL variable - /// that receives TRUE if the status window is visible, or FALSE if it is not. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETSHOWIMEUI = 0x006E, - - /// - /// Sets whether the IME status window is visible or not on a per-user basis. The uiParam parameter specifies TRUE for - /// on or FALSE for off. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETSHOWIMEUI = 0x006F, - - /// - /// Retrieves the current mouse speed. The mouse speed determines how far the pointer will move based on the distance - /// the mouse moves. - /// The pvParam parameter must point to an integer that receives a value which ranges between 1 (slowest) and 20 - /// (fastest). - /// A value of 10 is the default. The value can be set by an end user using the mouse control panel application or - /// by an application using SPI_SETMOUSESPEED. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETMOUSESPEED = 0x0070, - - /// - /// Sets the current mouse speed. The pvParam parameter is an integer between 1 (slowest) and 20 (fastest). A value of - /// 10 is the default. - /// This value is typically set using the mouse control panel application. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETMOUSESPEED = 0x0071, - - /// - /// Determines whether a screen saver is currently running on the window station of the calling process. - /// The pvParam parameter must point to a BOOL variable that receives TRUE if a screen saver is currently running, or - /// FALSE otherwise. - /// Note that only the interactive window station, "WinSta0", can have a screen saver running. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETSCREENSAVERRUNNING = 0x0072, - - /// - /// Retrieves the full path of the bitmap file for the desktop wallpaper. The pvParam parameter must point to a buffer - /// that receives a null-terminated path string. Set the uiParam parameter to the size, in characters, of the pvParam - /// buffer. The returned string will not exceed MAX_PATH characters. If there is no desktop wallpaper, the returned - /// string is empty. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETDESKWALLPAPER = 0x0073, - - /// - /// Determines whether active window tracking (activating the window the mouse is on) is on or off. The pvParam - /// parameter must point - /// to a BOOL variable that receives TRUE for on, or FALSE for off. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETACTIVEWINDOWTRACKING = 0x1000, - - /// - /// Sets active window tracking (activating the window the mouse is on) either on or off. Set pvParam to TRUE for on or - /// FALSE for off. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETACTIVEWINDOWTRACKING = 0x1001, - - /// - /// Determines whether the menu animation feature is enabled. This master switch must be on to enable menu animation - /// effects. - /// The pvParam parameter must point to a BOOL variable that receives TRUE if animation is enabled and FALSE if it is - /// disabled. - /// If animation is enabled, SPI_GETMENUFADE indicates whether menus use fade or slide animation. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETMENUANIMATION = 0x1002, - - /// - /// Enables or disables menu animation. This master switch must be on for any menu animation to occur. - /// The pvParam parameter is a BOOL variable; set pvParam to TRUE to enable animation and FALSE to disable animation. - /// If animation is enabled, SPI_GETMENUFADE indicates whether menus use fade or slide animation. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETMENUANIMATION = 0x1003, - - /// - /// Determines whether the slide-open effect for combo boxes is enabled. The pvParam parameter must point to a BOOL - /// variable - /// that receives TRUE for enabled, or FALSE for disabled. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETCOMBOBOXANIMATION = 0x1004, - - /// - /// Enables or disables the slide-open effect for combo boxes. Set the pvParam parameter to TRUE to enable the gradient - /// effect, - /// or FALSE to disable it. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETCOMBOBOXANIMATION = 0x1005, - - /// - /// Determines whether the smooth-scrolling effect for list boxes is enabled. The pvParam parameter must point to a - /// BOOL variable - /// that receives TRUE for enabled, or FALSE for disabled. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETLISTBOXSMOOTHSCROLLING = 0x1006, - - /// - /// Enables or disables the smooth-scrolling effect for list boxes. Set the pvParam parameter to TRUE to enable the - /// smooth-scrolling effect, - /// or FALSE to disable it. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETLISTBOXSMOOTHSCROLLING = 0x1007, - - /// - /// Determines whether the gradient effect for window title bars is enabled. The pvParam parameter must point to a BOOL - /// variable - /// that receives TRUE for enabled, or FALSE for disabled. For more information about the gradient effect, see the - /// GetSysColor function. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETGRADIENTCAPTIONS = 0x1008, - - /// - /// Enables or disables the gradient effect for window title bars. Set the pvParam parameter to TRUE to enable it, or - /// FALSE to disable it. - /// The gradient effect is possible only if the system has a color depth of more than 256 colors. For more information - /// about - /// the gradient effect, see the GetSysColor function. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETGRADIENTCAPTIONS = 0x1009, - - /// - /// Determines whether menu access keys are always underlined. The pvParam parameter must point to a BOOL variable that - /// receives TRUE - /// if menu access keys are always underlined, and FALSE if they are underlined only when the menu is activated by the - /// keyboard. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETKEYBOARDCUES = 0x100A, - - /// - /// Sets the underlining of menu access key letters. The pvParam parameter is a BOOL variable. Set pvParam to TRUE to - /// always underline menu - /// access keys, or FALSE to underline menu access keys only when the menu is activated from the keyboard. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETKEYBOARDCUES = 0x100B, - - /// - /// Same as SPI_GETKEYBOARDCUES. - /// - SPI_GETMENUUNDERLINES = SPI_GETKEYBOARDCUES, - - /// - /// Same as SPI_SETKEYBOARDCUES. - /// - SPI_SETMENUUNDERLINES = SPI_SETKEYBOARDCUES, - - /// - /// Determines whether windows activated through active window tracking will be brought to the top. The pvParam - /// parameter must point - /// to a BOOL variable that receives TRUE for on, or FALSE for off. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETACTIVEWNDTRKZORDER = 0x100C, - - /// - /// Determines whether or not windows activated through active window tracking should be brought to the top. Set - /// pvParam to TRUE - /// for on or FALSE for off. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETACTIVEWNDTRKZORDER = 0x100D, - - /// - /// Determines whether hot tracking of user-interface elements, such as menu names on menu bars, is enabled. The - /// pvParam parameter - /// must point to a BOOL variable that receives TRUE for enabled, or FALSE for disabled. - /// Hot tracking means that when the cursor moves over an item, it is highlighted but not selected. You can query this - /// value to decide - /// whether to use hot tracking in the user interface of your application. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETHOTTRACKING = 0x100E, - - /// - /// Enables or disables hot tracking of user-interface elements such as menu names on menu bars. Set the pvParam - /// parameter to TRUE - /// to enable it, or FALSE to disable it. - /// Hot-tracking means that when the cursor moves over an item, it is highlighted but not selected. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETHOTTRACKING = 0x100F, - - /// - /// Determines whether menu fade animation is enabled. The pvParam parameter must point to a BOOL variable that - /// receives TRUE - /// when fade animation is enabled and FALSE when it is disabled. If fade animation is disabled, menus use slide - /// animation. - /// This flag is ignored unless menu animation is enabled, which you can do using the SPI_SETMENUANIMATION flag. - /// For more information, see AnimateWindow. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETMENUFADE = 0x1012, - - /// - /// Enables or disables menu fade animation. Set pvParam to TRUE to enable the menu fade effect or FALSE to disable it. - /// If fade animation is disabled, menus use slide animation. he The menu fade effect is possible only if the system - /// has a color depth of more than 256 colors. This flag is ignored unless SPI_MENUANIMATION is also set. For more - /// information, - /// see AnimateWindow. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETMENUFADE = 0x1013, - - /// - /// Determines whether the selection fade effect is enabled. The pvParam parameter must point to a BOOL variable that - /// receives TRUE - /// if enabled or FALSE if disabled. - /// The selection fade effect causes the menu item selected by the user to remain on the screen briefly while fading - /// out - /// after the menu is dismissed. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETSELECTIONFADE = 0x1014, - - /// - /// Set pvParam to TRUE to enable the selection fade effect or FALSE to disable it. - /// The selection fade effect causes the menu item selected by the user to remain on the screen briefly while fading - /// out - /// after the menu is dismissed. The selection fade effect is possible only if the system has a color depth of more - /// than 256 colors. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETSELECTIONFADE = 0x1015, - - /// - /// Determines whether ToolTip animation is enabled. The pvParam parameter must point to a BOOL variable that receives - /// TRUE - /// if enabled or FALSE if disabled. If ToolTip animation is enabled, SPI_GETTOOLTIPFADE indicates whether ToolTips use - /// fade or slide animation. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETTOOLTIPANIMATION = 0x1016, - - /// - /// Set pvParam to TRUE to enable ToolTip animation or FALSE to disable it. If enabled, you can use SPI_SETTOOLTIPFADE - /// to specify fade or slide animation. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETTOOLTIPANIMATION = 0x1017, - - /// - /// If SPI_SETTOOLTIPANIMATION is enabled, SPI_GETTOOLTIPFADE indicates whether ToolTip animation uses a fade effect or - /// a slide effect. - /// The pvParam parameter must point to a BOOL variable that receives TRUE for fade animation or FALSE for slide - /// animation. - /// For more information on slide and fade effects, see AnimateWindow. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETTOOLTIPFADE = 0x1018, - - /// - /// If the SPI_SETTOOLTIPANIMATION flag is enabled, use SPI_SETTOOLTIPFADE to indicate whether ToolTip animation uses a - /// fade effect - /// or a slide effect. Set pvParam to TRUE for fade animation or FALSE for slide animation. The tooltip fade effect is - /// possible only - /// if the system has a color depth of more than 256 colors. For more information on the slide and fade effects, - /// see the AnimateWindow function. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETTOOLTIPFADE = 0x1019, - - /// - /// Determines whether the cursor has a shadow around it. The pvParam parameter must point to a BOOL variable that - /// receives TRUE - /// if the shadow is enabled, FALSE if it is disabled. This effect appears only if the system has a color depth of more - /// than 256 colors. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETCURSORSHADOW = 0x101A, - - /// - /// Enables or disables a shadow around the cursor. The pvParam parameter is a BOOL variable. Set pvParam to TRUE to - /// enable the shadow - /// or FALSE to disable the shadow. This effect appears only if the system has a color depth of more than 256 colors. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETCURSORSHADOW = 0x101B, - - /// - /// Retrieves the state of the Mouse Sonar feature. The pvParam parameter must point to a BOOL variable that receives - /// TRUE - /// if enabled or FALSE otherwise. For more information, see About Mouse Input on MSDN. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_GETMOUSESONAR = 0x101C, - - /// - /// Turns the Sonar accessibility feature on or off. This feature briefly shows several concentric circles around the - /// mouse pointer when the user presses and releases the CTRL key. The pvParam parameter specifies TRUE for on and FALSE for off. - /// The default is off. - /// For more information, see About Mouse Input. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_SETMOUSESONAR = 0x101D, - - /// - /// Retrieves the state of the Mouse ClickLock feature. The pvParam parameter must point to a BOOL variable that - /// receives TRUE - /// if enabled, or FALSE otherwise. For more information, see About Mouse Input. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_GETMOUSECLICKLOCK = 0x101E, - - /// - /// Turns the Mouse ClickLock accessibility feature on or off. This feature temporarily locks down the primary mouse - /// button - /// when that button is clicked and held down for the time specified by SPI_SETMOUSECLICKLOCKTIME. The uiParam - /// parameter specifies - /// TRUE for on, - /// or FALSE for off. The default is off. For more information, see Remarks and About Mouse Input on MSDN. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_SETMOUSECLICKLOCK = 0x101F, - - /// - /// Retrieves the state of the Mouse Vanish feature. The pvParam parameter must point to a BOOL variable that receives - /// TRUE - /// if enabled or FALSE otherwise. For more information, see About Mouse Input on MSDN. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_GETMOUSEVANISH = 0x1020, - - /// - /// Turns the Vanish feature on or off. This feature hides the mouse pointer when the user types; the pointer reappears - /// when the user moves the mouse. The pvParam parameter specifies TRUE for on and FALSE for off. The default is off. - /// For more information, see About Mouse Input on MSDN. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_SETMOUSEVANISH = 0x1021, - - /// - /// Determines whether native User menus have flat menu appearance. The pvParam parameter must point to a BOOL variable - /// that returns TRUE if the flat menu appearance is set, or FALSE otherwise. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETFLATMENU = 0x1022, - - /// - /// Enables or disables flat menu appearance for native User menus. Set pvParam to TRUE to enable flat menu appearance - /// or FALSE to disable it. - /// When enabled, the menu bar uses COLOR_MENUBAR for the menubar background, COLOR_MENU for the menu-popup background, - /// COLOR_MENUHILIGHT - /// for the fill of the current menu selection, and COLOR_HILIGHT for the outline of the current menu selection. - /// If disabled, menus are drawn using the same metrics and colors as in Windows 2000 and earlier. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETFLATMENU = 0x1023, - - /// - /// Determines whether the drop shadow effect is enabled. The pvParam parameter must point to a BOOL variable that - /// returns TRUE - /// if enabled or FALSE if disabled. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETDROPSHADOW = 0x1024, - - /// - /// Enables or disables the drop shadow effect. Set pvParam to TRUE to enable the drop shadow effect or FALSE to - /// disable it. - /// You must also have CS_DROPSHADOW in the window class style. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETDROPSHADOW = 0x1025, - - /// - /// Retrieves a BOOL indicating whether an application can reset the screensaver's timer by calling the SendInput - /// function - /// to simulate keyboard or mouse input. The pvParam parameter must point to a BOOL variable that receives TRUE - /// if the simulated input will be blocked, or FALSE otherwise. - /// - SPI_GETBLOCKSENDINPUTRESETS = 0x1026, - - /// - /// Determines whether an application can reset the screensaver's timer by calling the SendInput function to simulate - /// keyboard - /// or mouse input. The uiParam parameter specifies TRUE if the screensaver will not be deactivated by simulated input, - /// or FALSE if the screensaver will be deactivated by simulated input. - /// - SPI_SETBLOCKSENDINPUTRESETS = 0x1027, - //#endif /* _WIN32_WINNT >= 0x0501 */ - - /// - /// Determines whether UI effects are enabled or disabled. The pvParam parameter must point to a BOOL variable that - /// receives TRUE - /// if all UI effects are enabled, or FALSE if they are disabled. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETUIEFFECTS = 0x103E, - - /// - /// Enables or disables UI effects. Set the pvParam parameter to TRUE to enable all UI effects or FALSE to disable all - /// UI effects. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETUIEFFECTS = 0x103F, - - /// - /// Retrieves the amount of time following user input, in milliseconds, during which the system will not allow - /// applications - /// to force themselves into the foreground. The pvParam parameter must point to a DWORD variable that receives the - /// time. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000, - - /// - /// Sets the amount of time following user input, in milliseconds, during which the system does not allow applications - /// to force themselves into the foreground. Set pvParam to the new timeout value. - /// The calling thread must be able to change the foreground window, otherwise the call fails. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001, - - /// - /// Retrieves the active window tracking delay, in milliseconds. The pvParam parameter must point to a DWORD variable - /// that receives the time. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETACTIVEWNDTRKTIMEOUT = 0x2002, - - /// - /// Sets the active window tracking delay. Set pvParam to the number of milliseconds to delay before activating the - /// window - /// under the mouse pointer. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETACTIVEWNDTRKTIMEOUT = 0x2003, - - /// - /// Retrieves the number of times SetForegroundWindow will flash the taskbar button when rejecting a foreground switch - /// request. - /// The pvParam parameter must point to a DWORD variable that receives the value. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_GETFOREGROUNDFLASHCOUNT = 0x2004, - - /// - /// Sets the number of times SetForegroundWindow will flash the taskbar button when rejecting a foreground switch - /// request. - /// Set pvParam to the number of times to flash. - /// Windows NT, Windows 95: This value is not supported. - /// - SPI_SETFOREGROUNDFLASHCOUNT = 0x2005, - - /// - /// Retrieves the caret width in edit controls, in pixels. The pvParam parameter must point to a DWORD that receives - /// this value. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETCARETWIDTH = 0x2006, - - /// - /// Sets the caret width in edit controls. Set pvParam to the desired width, in pixels. The default and minimum value - /// is 1. - /// Windows NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETCARETWIDTH = 0x2007, - - /// - /// Retrieves the time delay before the primary mouse button is locked. The pvParam parameter must point to DWORD that - /// receives - /// the time delay. This is only enabled if SPI_SETMOUSECLICKLOCK is set to TRUE. For more information, see About Mouse - /// Input on MSDN. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_GETMOUSECLICKLOCKTIME = 0x2008, - - /// - /// Turns the Mouse ClickLock accessibility feature on or off. This feature temporarily locks down the primary mouse - /// button - /// when that button is clicked and held down for the time specified by SPI_SETMOUSECLICKLOCKTIME. The uiParam - /// parameter - /// specifies TRUE for on, or FALSE for off. The default is off. For more information, see Remarks and About Mouse - /// Input on MSDN. - /// Windows 2000/NT, Windows 98/95: This value is not supported. - /// - SPI_SETMOUSECLICKLOCKTIME = 0x2009, - - /// - /// Retrieves the type of font smoothing. The pvParam parameter must point to a UINT that receives the information. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETFONTSMOOTHINGTYPE = 0x200A, - - /// - /// Sets the font smoothing type. The pvParam parameter points to a UINT that contains either FE_FONTSMOOTHINGSTANDARD, - /// if standard anti-aliasing is used, or FE_FONTSMOOTHINGCLEARTYPE, if ClearType is used. The default is - /// FE_FONTSMOOTHINGSTANDARD. - /// When using this option, the fWinIni parameter must be set to SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE; otherwise, - /// SystemParametersInfo fails. - /// - SPI_SETFONTSMOOTHINGTYPE = 0x200B, - - /// - /// Retrieves a contrast value that is used in ClearType™ smoothing. The pvParam parameter must point to a UINT - /// that receives the information. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETFONTSMOOTHINGCONTRAST = 0x200C, - - /// - /// Sets the contrast value used in ClearType smoothing. The pvParam parameter points to a UINT that holds the contrast - /// value. - /// Valid contrast values are from 1000 to 2200. The default value is 1400. - /// When using this option, the fWinIni parameter must be set to SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE; otherwise, - /// SystemParametersInfo fails. - /// SPI_SETFONTSMOOTHINGTYPE must also be set to FE_FONTSMOOTHINGCLEARTYPE. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETFONTSMOOTHINGCONTRAST = 0x200D, - - /// - /// Retrieves the width, in pixels, of the left and right edges of the focus rectangle drawn with DrawFocusRect. - /// The pvParam parameter must point to a UINT. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETFOCUSBORDERWIDTH = 0x200E, - - /// - /// Sets the height of the left and right edges of the focus rectangle drawn with DrawFocusRect to the value of the - /// pvParam parameter. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETFOCUSBORDERWIDTH = 0x200F, - - /// - /// Retrieves the height, in pixels, of the top and bottom edges of the focus rectangle drawn with DrawFocusRect. - /// The pvParam parameter must point to a UINT. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_GETFOCUSBORDERHEIGHT = 0x2010, - - /// - /// Sets the height of the top and bottom edges of the focus rectangle drawn with DrawFocusRect to the value of the - /// pvParam parameter. - /// Windows 2000/NT, Windows Me/98/95: This value is not supported. - /// - SPI_SETFOCUSBORDERHEIGHT = 0x2011, - - /// - /// Not implemented. - /// - SPI_GETFONTSMOOTHINGORIENTATION = 0x2012, - - /// - /// Not implemented. - /// - SPI_SETFONTSMOOTHINGORIENTATION = 0x2013 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/Enums/SystemParametersInfoBehaviors.cs b/GreenshotPlugin/Core/Enums/SystemParametersInfoBehaviors.cs deleted file mode 100644 index 4b5872ae5..000000000 --- a/GreenshotPlugin/Core/Enums/SystemParametersInfoBehaviors.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Dapplo and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace GreenshotPlugin.Core.Enums -{ - /// - /// If a system parameter is being set, specifies whether the user profile is to be updated, and if so, whether the - /// WM_SETTINGCHANGE message is to be broadcast to all top-level windows to notify them of the change. - /// This parameter can be zero if you do not want to update the user profile or broadcast the WM_SETTINGCHANGE message, - /// or it can be one or more of the following values. - /// - public enum SystemParametersInfoBehaviors : uint - { - /// - /// Do nothing - /// - None = 0x00, - - /// Writes the new system-wide parameter setting to the user profile. - UpdateIniFile = 0x01, - - /// Broadcasts the WM_SETTINGCHANGE message after updating the user profile. - SendChange = 0x02, - - /// Same as SPIF_SENDCHANGE. - SendWinIniChange = SendChange - } -} \ No newline at end of file diff --git a/GreenshotPlugin/Core/EnvironmentInfo.cs b/GreenshotPlugin/Core/EnvironmentInfo.cs new file mode 100644 index 000000000..01eb11772 --- /dev/null +++ b/GreenshotPlugin/Core/EnvironmentInfo.cs @@ -0,0 +1,793 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using GreenshotPlugin.IniFile; +using GreenshotPlugin.UnmanagedHelpers; +using Microsoft.Win32; + +namespace GreenshotPlugin.Core +{ + /// + /// Description of EnvironmentInfo. + /// + public static class EnvironmentInfo + { + private static bool? _isWindows; + + public static bool IsWindows + { + get + { + if (_isWindows.HasValue) + { + return _isWindows.Value; + } + _isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); + return _isWindows.Value; + } + } + + public static bool IsNet45OrNewer() + { + // Class "ReflectionContext" exists from .NET 4.5 onwards. + return Type.GetType("System.Reflection.ReflectionContext", false) != null; + } + + public static string GetGreenshotVersion(bool shortVersion = false) + { + var executingAssembly = Assembly.GetExecutingAssembly(); + + // Use assembly version + string greenshotVersion = executingAssembly.GetName().Version.ToString(); + + // Use AssemblyFileVersion if available + var assemblyFileVersionAttribute = executingAssembly.GetCustomAttribute(); + if (!string.IsNullOrEmpty(assemblyFileVersionAttribute?.Version)) + { + var assemblyFileVersion = new Version(assemblyFileVersionAttribute.Version); + greenshotVersion = assemblyFileVersion.ToString(3); + } + + if (!shortVersion) + { + // Use AssemblyInformationalVersion if available + var informationalVersionAttribute = executingAssembly.GetCustomAttribute(); + if (!string.IsNullOrEmpty(informationalVersionAttribute?.InformationalVersion)) + { + greenshotVersion = informationalVersionAttribute.InformationalVersion; + } + } + + return greenshotVersion.Replace("+", " - "); + } + + public static string EnvironmentToString(bool newline) + { + StringBuilder environment = new StringBuilder(); + environment.Append("Software version: " + GetGreenshotVersion()); + if (IniConfig.IsPortable) { + environment.Append(" Portable"); + } + environment.Append(" (" + OsInfo.Bits + " bit)"); + + if (newline) + { + environment.AppendLine(); + } + else + { + environment.Append(", "); + } + environment.Append(".NET runtime version: " + Environment.Version); + if (IsNet45OrNewer()) + { + environment.Append("+"); + + } + if (newline) + { + environment.AppendLine(); + } + else + { + environment.Append(", "); + } + environment.Append("Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz")); + + if (IsWindows) + { + if (newline) + { + environment.AppendLine(); + } + else + { + environment.Append(", "); + } + + environment.Append($"OS: {OsInfo.Name}"); + if (!string.IsNullOrEmpty(OsInfo.Edition)) + { + environment.Append($" {OsInfo.Edition}"); + + } + if (!string.IsNullOrEmpty(OsInfo.ServicePack)) + { + environment.Append($" {OsInfo.ServicePack}"); + + } + environment.Append($" x{OsInfo.Bits}"); + environment.Append($" {OsInfo.VersionString}"); + if (newline) + { + environment.AppendLine(); + } + else + { + environment.Append(", "); + } + // Get some important information for fixing GDI related Problems + environment.AppendFormat("GDI object count: {0}", User32.GetGuiResourcesGDICount()); + if (newline) + { + environment.AppendLine(); + } + else + { + environment.Append(", "); + } + environment.AppendFormat("User object count: {0}", User32.GetGuiResourcesUserCount()); + } + else + { + if (newline) + { + environment.AppendLine(); + } + else + { + environment.Append(", "); + } + environment.AppendFormat("OS: {0}", Environment.OSVersion.Platform); + } + if (newline) + { + environment.AppendLine(); + } + else + { + environment.Append(", "); + } + // TODO: Is this needed? + // environment.AppendFormat("Surface count: {0}", Surface.Count); + + return environment.ToString(); + } + + public static string ExceptionToString(Exception ex) + { + if (ex == null) + return "null\r\n"; + + StringBuilder report = new StringBuilder(); + + report.AppendLine("Exception: " + ex.GetType()); + report.AppendLine("Message: " + ex.Message); + if (ex.Data.Count > 0) + { + report.AppendLine(); + report.AppendLine("Additional Information:"); + foreach (object key in ex.Data.Keys) + { + object data = ex.Data[key]; + if (data != null) + { + report.AppendLine(key + " : " + data); + } + } + } + if (ex is ExternalException externalException) + { + // e.g. COMException + report.AppendLine().AppendLine("ErrorCode: 0x" + externalException.ErrorCode.ToString("X")); + } + + report.AppendLine().AppendLine("Stack:").AppendLine(ex.StackTrace); + + if (ex is ReflectionTypeLoadException reflectionTypeLoadException) + { + report.AppendLine().AppendLine("LoaderExceptions: "); + foreach (Exception cbE in reflectionTypeLoadException.LoaderExceptions) + { + report.AppendLine(cbE.Message); + } + } + + if (ex.InnerException != null) + { + report.AppendLine("--- InnerException: ---"); + report.AppendLine(ExceptionToString(ex.InnerException)); + } + return report.ToString(); + } + + public static string BuildReport(Exception exception) + { + StringBuilder exceptionText = new StringBuilder(); + exceptionText.AppendLine(EnvironmentToString(true)); + exceptionText.AppendLine(ExceptionToString(exception)); + exceptionText.AppendLine("Configuration dump:"); + + return exceptionText.ToString(); + } + } + + /// + /// Provides detailed information about the host operating system. + /// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/ + /// + public static class OsInfo + { + /// + /// Determines if the current application is 32 or 64-bit. + /// + public static int Bits => IntPtr.Size * 8; + + private static string _sEdition; + + /// + /// Gets the edition of the operating system running on this computer. + /// + public static string Edition + { + get + { + if (_sEdition != null) + { + return _sEdition; //***** RETURN *****// + } + + string edition = string.Empty; + + OperatingSystem osVersion = Environment.OSVersion; + OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create(); + + if (GetVersionEx(ref osVersionInfo)) + { + int majorVersion = osVersion.Version.Major; + int minorVersion = osVersion.Version.Minor; + byte productType = osVersionInfo.ProductType; + ushort suiteMask = osVersionInfo.SuiteMask; + + if (majorVersion == 4) + { + if (productType == VER_NT_WORKSTATION) + { + // Windows NT 4.0 Workstation + edition = "Workstation"; + } + else if (productType == VER_NT_SERVER) + { + edition = (suiteMask & VER_SUITE_ENTERPRISE) != 0 ? "Enterprise Server" : "Standard Server"; + } + } + + else if (majorVersion == 5) + { + if (productType == VER_NT_WORKSTATION) + { + if ((suiteMask & VER_SUITE_PERSONAL) != 0) + { + // Windows XP Home Edition + edition = "Home"; + } + else + { + // Windows XP / Windows 2000 Professional + edition = "Professional"; + } + } + else if (productType == VER_NT_SERVER) + { + if (minorVersion == 0) + { + if ((suiteMask & VER_SUITE_DATACENTER) != 0) + { + // Windows 2000 Datacenter Server + edition = "Datacenter Server"; + } + else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) + { + // Windows 2000 Advanced Server + edition = "Advanced Server"; + } + else + { + // Windows 2000 Server + edition = "Server"; + } + } + else + { + if ((suiteMask & VER_SUITE_DATACENTER) != 0) + { + // Windows Server 2003 Datacenter Edition + edition = "Datacenter"; + } + else if ((suiteMask & VER_SUITE_ENTERPRISE) != 0) + { + // Windows Server 2003 Enterprise Edition + edition = "Enterprise"; + } + else if ((suiteMask & VER_SUITE_BLADE) != 0) + { + // Windows Server 2003 Web Edition + edition = "Web Edition"; + } + else + { + // Windows Server 2003 Standard Edition + edition = "Standard"; + } + } + } + } + + else if (majorVersion == 6) + { + if (GetProductInfo(majorVersion, minorVersion, osVersionInfo.ServicePackMajor, osVersionInfo.ServicePackMinor, out var ed)) + { + switch (ed) + { + case PRODUCT_BUSINESS: + edition = "Business"; + break; + case PRODUCT_BUSINESS_N: + edition = "Business N"; + break; + case PRODUCT_CLUSTER_SERVER: + edition = "HPC Edition"; + break; + case PRODUCT_DATACENTER_SERVER: + edition = "Datacenter Server"; + break; + case PRODUCT_DATACENTER_SERVER_CORE: + edition = "Datacenter Server (core installation)"; + break; + case PRODUCT_ENTERPRISE: + edition = "Enterprise"; + break; + case PRODUCT_ENTERPRISE_N: + edition = "Enterprise N"; + break; + case PRODUCT_ENTERPRISE_SERVER: + edition = "Enterprise Server"; + break; + case PRODUCT_ENTERPRISE_SERVER_CORE: + edition = "Enterprise Server (core installation)"; + break; + case PRODUCT_ENTERPRISE_SERVER_CORE_V: + edition = "Enterprise Server without Hyper-V (core installation)"; + break; + case PRODUCT_ENTERPRISE_SERVER_IA64: + edition = "Enterprise Server for Itanium-based Systems"; + break; + case PRODUCT_ENTERPRISE_SERVER_V: + edition = "Enterprise Server without Hyper-V"; + break; + case PRODUCT_HOME_BASIC: + edition = "Home Basic"; + break; + case PRODUCT_HOME_BASIC_N: + edition = "Home Basic N"; + break; + case PRODUCT_HOME_PREMIUM: + edition = "Home Premium"; + break; + case PRODUCT_HOME_PREMIUM_N: + edition = "Home Premium N"; + break; + case PRODUCT_HYPERV: + edition = "Microsoft Hyper-V Server"; + break; + case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT: + edition = "Windows Essential Business Management Server"; + break; + case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING: + edition = "Windows Essential Business Messaging Server"; + break; + case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY: + edition = "Windows Essential Business Security Server"; + break; + case PRODUCT_SERVER_FOR_SMALLBUSINESS: + edition = "Windows Essential Server Solutions"; + break; + case PRODUCT_SERVER_FOR_SMALLBUSINESS_V: + edition = "Windows Essential Server Solutions without Hyper-V"; + break; + case PRODUCT_SMALLBUSINESS_SERVER: + edition = "Windows Small Business Server"; + break; + case PRODUCT_STANDARD_SERVER: + edition = "Standard Server"; + break; + case PRODUCT_STANDARD_SERVER_CORE: + edition = "Standard Server (core installation)"; + break; + case PRODUCT_STANDARD_SERVER_CORE_V: + edition = "Standard Server without Hyper-V (core installation)"; + break; + case PRODUCT_STANDARD_SERVER_V: + edition = "Standard Server without Hyper-V"; + break; + case PRODUCT_STARTER: + edition = "Starter"; + break; + case PRODUCT_STORAGE_ENTERPRISE_SERVER: + edition = "Enterprise Storage Server"; + break; + case PRODUCT_STORAGE_EXPRESS_SERVER: + edition = "Express Storage Server"; + break; + case PRODUCT_STORAGE_STANDARD_SERVER: + edition = "Standard Storage Server"; + break; + case PRODUCT_STORAGE_WORKGROUP_SERVER: + edition = "Workgroup Storage Server"; + break; + case PRODUCT_UNDEFINED: + edition = "Unknown product"; + break; + case PRODUCT_ULTIMATE: + edition = "Ultimate"; + break; + case PRODUCT_ULTIMATE_N: + edition = "Ultimate N"; + break; + case PRODUCT_WEB_SERVER: + edition = "Web Server"; + break; + case PRODUCT_WEB_SERVER_CORE: + edition = "Web Server (core installation)"; + break; + } + } + } + } + + _sEdition = edition; + return edition; + } + } + + private static string _name; + + /// + /// Gets the name of the operating system running on this computer. + /// + public static string Name + { + get + { + if (_name != null) + { + return _name; //***** RETURN *****// + } + + string name = "unknown"; + + OperatingSystem osVersion = Environment.OSVersion; + OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create(); + if (GetVersionEx(ref osVersionInfo)) + { + int majorVersion = osVersion.Version.Major; + int minorVersion = osVersion.Version.Minor; + byte productType = osVersionInfo.ProductType; + ushort suiteMask = osVersionInfo.SuiteMask; + switch (osVersion.Platform) + { + case PlatformID.Win32Windows: + if (majorVersion == 4) + { + string csdVersion = osVersionInfo.ServicePackVersion; + switch (minorVersion) + { + case 0: + if (csdVersion == "B" || csdVersion == "C") + { + name = "Windows 95 OSR2"; + } + else + { + name = "Windows 95"; + } + + break; + case 10: + name = csdVersion == "A" ? "Windows 98 Second Edition" : "Windows 98"; + break; + case 90: + name = "Windows Me"; + break; + } + } + + break; + case PlatformID.Win32NT: + switch (majorVersion) + { + case 3: + name = "Windows NT 3.51"; + break; + case 4: + switch (productType) + { + case 1: + name = "Windows NT 4.0"; + break; + case 3: + name = "Windows NT 4.0 Server"; + break; + } + + break; + case 5: + switch (minorVersion) + { + case 0: + name = "Windows 2000"; + break; + case 1: + name = suiteMask switch + { + 0x0200 => "Windows XP Professional", + _ => "Windows XP" + }; + break; + case 2: + name = suiteMask switch + { + 0x0200 => "Windows XP Professional x64", + 0x0002 => "Windows Server 2003 Enterprise", + 0x0080 => "Windows Server 2003 Data Center", + 0x0400 => "Windows Server 2003 Web Edition", + 0x8000 => "Windows Home Server", + _ => "Windows Server 2003" + }; + break; + } + + break; + case 6: + switch (minorVersion) + { + case 0: + name = productType switch + { + 3 => "Windows Server 2008", + _ => "Windows Vista" + }; + break; + case 1: + name = productType switch + { + 3 => "Windows Server 2008 R2", + _ => "Windows 7" + }; + break; + case 2: + name = "Windows 8"; + break; + case 3: + name = "Windows 8.1"; + break; + } + + break; + case 10: + string releaseId = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", "").ToString(); + name = $"Windows 10 {releaseId}"; + break; + } + + break; + } + } + + _name = name; + return name; + } + } + + [DllImport("Kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool GetProductInfo( + int osMajorVersion, + int osMinorVersion, + int spMajorVersion, + int spMinorVersion, + out int edition); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private unsafe struct OSVERSIONINFOEX + { + /// + /// The size of this data structure, in bytes. Set this member to sizeof(OSVERSIONINFOEX). + /// + private int _dwOSVersionInfoSize; + + private readonly int _dwMajorVersion; + private readonly int _dwMinorVersion; + private readonly int _dwBuildNumber; + private readonly int _dwPlatformId; + private fixed char _szCSDVersion[128]; + private readonly short _wServicePackMajor; + private readonly short _wServicePackMinor; + private readonly ushort _wSuiteMask; + private readonly byte _wProductType; + private readonly byte _wReserved; + + /// A null-terminated string, such as "Service Pack 3", that indicates the latest Service Pack installed on the system. + /// If no Service Pack has been installed, the string is empty. + /// + public string ServicePackVersion + { + get + { + fixed (char* servicePackVersion = _szCSDVersion) + { + return new string(servicePackVersion); + } + + } + } + + /// + /// The major version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the + /// major version number is 3. + /// If no Service Pack has been installed, the value is zero. + /// + public short ServicePackMajor => _wServicePackMajor; + + /// + /// The minor version number of the latest Service Pack installed on the system. For example, for Service Pack 3, the + /// minor version number is 0. + /// + public short ServicePackMinor => _wServicePackMinor; + + /// + /// A bit mask that identifies the product suites available on the system. This member can be a combination of the + /// following values. + /// + public ushort SuiteMask => _wSuiteMask; + + /// + /// Any additional information about the system. + /// + public byte ProductType => _wProductType; + + /// + /// Factory for an empty OsVersionInfoEx + /// + /// OSVERSIONINFOEX + public static OSVERSIONINFOEX Create() + { + return new OSVERSIONINFOEX + { + _dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)) + }; + } + } + + private const int PRODUCT_UNDEFINED = 0x00000000; + private const int PRODUCT_ULTIMATE = 0x00000001; + private const int PRODUCT_HOME_BASIC = 0x00000002; + private const int PRODUCT_HOME_PREMIUM = 0x00000003; + private const int PRODUCT_ENTERPRISE = 0x00000004; + private const int PRODUCT_HOME_BASIC_N = 0x00000005; + private const int PRODUCT_BUSINESS = 0x00000006; + private const int PRODUCT_STANDARD_SERVER = 0x00000007; + private const int PRODUCT_DATACENTER_SERVER = 0x00000008; + private const int PRODUCT_SMALLBUSINESS_SERVER = 0x00000009; + private const int PRODUCT_ENTERPRISE_SERVER = 0x0000000A; + private const int PRODUCT_STARTER = 0x0000000B; + private const int PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C; + private const int PRODUCT_STANDARD_SERVER_CORE = 0x0000000D; + private const int PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E; + private const int PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F; + private const int PRODUCT_BUSINESS_N = 0x00000010; + private const int PRODUCT_WEB_SERVER = 0x00000011; + private const int PRODUCT_CLUSTER_SERVER = 0x00000012; + private const int PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014; + private const int PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015; + private const int PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016; + private const int PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017; + private const int PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018; + private const int PRODUCT_HOME_PREMIUM_N = 0x0000001A; + private const int PRODUCT_ENTERPRISE_N = 0x0000001B; + private const int PRODUCT_ULTIMATE_N = 0x0000001C; + private const int PRODUCT_WEB_SERVER_CORE = 0x0000001D; + private const int PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E; + private const int PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F; + private const int PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020; + private const int PRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023; + private const int PRODUCT_STANDARD_SERVER_V = 0x00000024; + private const int PRODUCT_ENTERPRISE_SERVER_V = 0x00000026; + private const int PRODUCT_STANDARD_SERVER_CORE_V = 0x00000028; + private const int PRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029; + private const int PRODUCT_HYPERV = 0x0000002A; + + private const int VER_NT_WORKSTATION = 1; + private const int VER_NT_SERVER = 3; + private const int VER_SUITE_ENTERPRISE = 2; + private const int VER_SUITE_DATACENTER = 128; + private const int VER_SUITE_PERSONAL = 512; + private const int VER_SUITE_BLADE = 1024; + + /// + /// Gets the service pack information of the operating system running on this computer. + /// + public static string ServicePack + { + get + { + string servicePack = string.Empty; + OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create(); + + if (GetVersionEx(ref osVersionInfo)) + { + servicePack = osVersionInfo.ServicePackVersion; + } + + return servicePack; + } + } + + /// Gets the full version string of the operating system running on this computer. + /// + public static string VersionString + { + get + { + if (WindowsVersion.IsWindows10OrLater) + { + return $"build {Environment.OSVersion.Version.Build}"; + } + + if (Environment.OSVersion.Version.Revision != 0) + { + return + $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build} revision {Environment.OSVersion.Version.Revision:X}"; + } + + return $"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor} build {Environment.OSVersion.Version.Build}"; + } + } + } +} \ No newline at end of file diff --git a/GreenshotPlugin/Core/FastBitmap.cs b/GreenshotPlugin/Core/FastBitmap.cs index 0e52e04fb..54b11e5ce 100644 --- a/GreenshotPlugin/Core/FastBitmap.cs +++ b/GreenshotPlugin/Core/FastBitmap.cs @@ -355,16 +355,7 @@ namespace GreenshotPlugin.Core { } } - /// - /// Factory for creating a FastBitmap as a destination for the source - /// - /// Bitmap to clone - /// IFastBitmap - public static IFastBitmap CreateCloneOf(Image source) { - return CreateCloneOf(source, source.PixelFormat, Rectangle.Empty); - } - - /// + /// /// Factory for creating a FastBitmap as a destination for the source /// /// Bitmap to clone diff --git a/GreenshotPlugin/Core/HResultExtensions.cs b/GreenshotPlugin/Core/HResultExtensions.cs index a85bd7600..450636ef7 100644 --- a/GreenshotPlugin/Core/HResultExtensions.cs +++ b/GreenshotPlugin/Core/HResultExtensions.cs @@ -19,7 +19,6 @@ using GreenshotPlugin.Core.Enums; using System.Diagnostics.Contracts; -using System.Runtime.InteropServices; namespace GreenshotPlugin.Core { @@ -29,7 +28,7 @@ namespace GreenshotPlugin.Core public static class HResultExtensions { /// - /// Test if the HResult respresents a fail + /// Test if the HResult represents a fail /// /// HResult /// bool @@ -40,7 +39,7 @@ namespace GreenshotPlugin.Core } /// - /// Test if the HResult respresents a success + /// Test if the HResult represents a success /// /// HResult /// bool @@ -49,17 +48,5 @@ namespace GreenshotPlugin.Core { return hResult >= HResult.S_OK; } - - /// - /// Throw an exception on Failure - /// - /// HResult - public static void ThrowOnFailure(this HResult hResult) - { - if (hResult.Failed()) - { - throw Marshal.GetExceptionForHR((int)hResult); - } - } } } diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs index b80879141..0f19462bd 100644 --- a/GreenshotPlugin/Core/ImageHelper.cs +++ b/GreenshotPlugin/Core/ImageHelper.cs @@ -467,17 +467,7 @@ namespace GreenshotPlugin.Core { return returnIcon; } - /// - /// Get the number of icon in the file - /// - /// Location of the EXE or DLL - /// - public static int CountAssociatedIcons(string location) - { - return Shell32.ExtractIconEx(location, -1, out _, out _, 0); - } - - /// + /// /// Apply the effect to the bitmap /// /// Bitmap @@ -1063,17 +1053,7 @@ namespace GreenshotPlugin.Core { ApplyImageAttributes(source, sourceRect, dest, destRect, imageAttributes); } - /// - /// Apply image attributes to the image - /// - /// Image to apply matrix to - /// ImageAttributes to apply - public static void ApplyColorMatrix(Bitmap source, ImageAttributes imageAttributes) - { - ApplyImageAttributes(source, Rectangle.Empty, source, Rectangle.Empty, imageAttributes); - } - - /// + /// /// Apply a color matrix by copying from the source to the destination /// /// Image to copy from @@ -1242,17 +1222,7 @@ namespace GreenshotPlugin.Core { return clone; } - /// - /// Checks if the supplied Bitmap has a PixelFormat we support - /// - /// bitmap to check - /// bool if we support it - public static bool SupportsPixelFormat(Image image) - { - return SupportsPixelFormat(image.PixelFormat); - } - - /// + /// /// Checks if we support the pixel format /// /// PixelFormat to check @@ -1462,31 +1432,7 @@ namespace GreenshotPlugin.Core { return newImage; } - /// - /// Get a scaled version of the sourceBitmap - /// - /// - /// 1-99 to make smaller, use 101 and more to make the picture bigger - /// - public static Bitmap ScaleByPercent(Bitmap sourceBitmap, int percent) - { - float nPercent = (float)percent / 100; - - int sourceWidth = sourceBitmap.Width; - int sourceHeight = sourceBitmap.Height; - int destWidth = (int)(sourceWidth * nPercent); - int destHeight = (int)(sourceHeight * nPercent); - - Bitmap scaledBitmap = CreateEmpty(destWidth, destHeight, sourceBitmap.PixelFormat, Color.Empty, sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution); - using (Graphics graphics = Graphics.FromImage(scaledBitmap)) - { - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, destWidth, destHeight), new Rectangle(0, 0, sourceWidth, sourceHeight), GraphicsUnit.Pixel); - } - return scaledBitmap; - } - - /// + /// /// Resize canvas with pixel to the left, right, top and bottom /// /// diff --git a/GreenshotPlugin/Core/ImageWrapper.cs b/GreenshotPlugin/Core/ImageWrapper.cs index f4cc03247..270164cb7 100644 --- a/GreenshotPlugin/Core/ImageWrapper.cs +++ b/GreenshotPlugin/Core/ImageWrapper.cs @@ -12,16 +12,6 @@ namespace GreenshotPlugin.Core private readonly Image _image; private Image _imageClone; - /// - /// Factory method - /// - /// Image - /// IImage - public static IImage FromImage(Image image) - { - return image == null ? null : new ImageWrapper(image); - } - public ImageWrapper(Image image) { // Make sure the orientation is set correctly so Greenshot can process the image correctly diff --git a/GreenshotPlugin/Core/InterfaceUtils.cs b/GreenshotPlugin/Core/InterfaceUtils.cs index 89c8079f0..7dca0f172 100644 --- a/GreenshotPlugin/Core/InterfaceUtils.cs +++ b/GreenshotPlugin/Core/InterfaceUtils.cs @@ -20,9 +20,7 @@ */ using System; using System.Collections.Generic; -using System.Reflection; using System.Threading; -using GreenshotPlugin.Interfaces; using log4net; namespace GreenshotPlugin.Core { @@ -33,42 +31,28 @@ namespace GreenshotPlugin.Core { private static readonly ILog LOG = LogManager.GetLogger(typeof(InterfaceUtils)); public static List GetSubclassesOf(Type type, bool excludeSystemTypes) { - List list = new List(); - foreach(Assembly currentAssembly in Thread.GetDomain().GetAssemblies()) { + var list = new List(); + foreach(var currentAssembly in Thread.GetDomain().GetAssemblies()) { try { Type[] types = currentAssembly.GetTypes(); - if (!excludeSystemTypes || (excludeSystemTypes && !currentAssembly.FullName.StartsWith("System."))) { - foreach(Type currentType in types) { - if (type.IsInterface) { - if (currentType.GetInterface(type.FullName) != null) { - list.Add(currentType); - } - } else if (currentType.IsSubclassOf(type)) { - list.Add(currentType); - } - } - } - } catch (Exception ex) { + if (excludeSystemTypes && (!excludeSystemTypes || currentAssembly.FullName.StartsWith("System."))) + { + continue; + } + foreach(var currentType in types) { + if (type.IsInterface) { + if (currentType.GetInterface(type.FullName) != null) { + list.Add(currentType); + } + } else if (currentType.IsSubclassOf(type)) { + list.Add(currentType); + } + } + } catch (Exception ex) { LOG.WarnFormat("Problem getting subclasses of type: {0}, message: {1}", type.FullName, ex.Message); } } return list; } - - public static List GetProcessors() { - List processors = new List(); - foreach(Type processorType in GetSubclassesOf(typeof(IProcessor), true)) { - if (!processorType.IsAbstract) { - IProcessor processor = (IProcessor)Activator.CreateInstance(processorType); - if (processor.isActive) { - LOG.DebugFormat("Found processor {0} with designation {1}", processorType.Name, processor.Designation); - processors.Add(processor); - } else { - LOG.DebugFormat("Ignoring processor {0} with designation {1}", processorType.Name, processor.Designation); - } - } - } - return processors; - } - } + } } diff --git a/GreenshotPlugin/Core/Language.cs b/GreenshotPlugin/Core/Language.cs index f5f2caa26..1b60b6dc8 100644 --- a/GreenshotPlugin/Core/Language.cs +++ b/GreenshotPlugin/Core/Language.cs @@ -476,32 +476,7 @@ namespace GreenshotPlugin.Core { } } - /// - /// Check if a resource with prefix.key exists - /// - /// - /// - /// true if available - public static bool HasKey(string prefix, Enum key) { - if (key == null) { - return false; - } - return HasKey(prefix + "." + key); - } - - /// - /// Check if a resource with key exists - /// - /// - /// true if available - public static bool HasKey(Enum key) { - if (key == null) { - return false; - } - return HasKey(key.ToString()); - } - - /// + /// /// Check if a resource with prefix.key exists /// /// diff --git a/GreenshotPlugin/Core/NetworkHelper.cs b/GreenshotPlugin/Core/NetworkHelper.cs index c07208710..3159c9dcc 100644 --- a/GreenshotPlugin/Core/NetworkHelper.cs +++ b/GreenshotPlugin/Core/NetworkHelper.cs @@ -32,111 +32,83 @@ using GreenshotPlugin.IniFile; using GreenshotPlugin.Interfaces; using GreenshotPlugin.Interfaces.Plugin; -namespace GreenshotPlugin.Core { - /// - /// HTTP Method to make sure we have the correct method - /// - public enum HTTPMethod { - GET, - POST, - PUT, - DELETE, - HEAD - }; +namespace GreenshotPlugin.Core +{ + /// + /// HTTP Method to make sure we have the correct method + /// + public enum HTTPMethod + { + GET, + POST, + PUT, + DELETE + }; - /// - /// Description of NetworkHelper. - /// - public static class NetworkHelper { - private static readonly ILog Log = LogManager.GetLogger(typeof(NetworkHelper)); - private static readonly CoreConfiguration Config = IniConfig.GetIniSection(); + /// + /// Description of NetworkHelper. + /// + public static class NetworkHelper + { + private static readonly ILog Log = LogManager.GetLogger(typeof(NetworkHelper)); + private static readonly CoreConfiguration Config = IniConfig.GetIniSection(); - static NetworkHelper() { - try - { - // Disable certificate checking - ServicePointManager.ServerCertificateValidationCallback += delegate { - return true; - }; - } - catch (Exception ex) - { - Log.Warn("An error has occured while allowing self-signed certificates:", ex); - } - } + static NetworkHelper() + { + try + { + // Disable certificate checking + ServicePointManager.ServerCertificateValidationCallback += delegate { return true; }; + } + catch (Exception ex) + { + Log.Warn("An error has occurred while allowing self-signed certificates:", ex); + } + } - /// - /// Download a uri response as string - /// - /// An Uri to specify the download location - /// string with the file content - public static string GetAsString(Uri uri) { - return GetResponseAsString(CreateWebRequest(uri)); - } - - /// - /// Download the FavIcon as a Bitmap - /// - /// - /// Bitmap with the FavIcon - public static Bitmap DownloadFavIcon(Uri baseUri) { - Uri url = new Uri(baseUri, new Uri("favicon.ico")); - try { - HttpWebRequest request = CreateWebRequest(url); - using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); - if (request.HaveResponse) - { - using Stream responseStream = response.GetResponseStream(); - if (responseStream != null) - { - using Image image = ImageHelper.FromStream(responseStream); - return image.Height > 16 && image.Width > 16 ? new Bitmap(image, 16, 16) : new Bitmap(image); - } - } - } catch (Exception e) { - Log.Error("Problem downloading the FavIcon from: " + baseUri, e); - } - return null; - } - - /// - /// Download the uri into a memory stream, without catching exceptions - /// - /// Of an image - /// MemoryStream which is already seek-ed to 0 - public static MemoryStream GetAsMemoryStream(string url) { - HttpWebRequest request = CreateWebRequest(url); - using HttpWebResponse response = (HttpWebResponse)request.GetResponse(); - MemoryStream memoryStream = new MemoryStream(); - using (Stream responseStream = response.GetResponseStream()) { + /// + /// Download the uri into a memory stream, without catching exceptions + /// + /// Of an image + /// MemoryStream which is already seek-ed to 0 + public static MemoryStream GetAsMemoryStream(string url) + { + var request = CreateWebRequest(url); + using var response = (HttpWebResponse)request.GetResponse(); + var memoryStream = new MemoryStream(); + using (var responseStream = response.GetResponseStream()) + { responseStream?.CopyTo(memoryStream); // Make sure it can be used directly memoryStream.Seek(0, SeekOrigin.Begin); } + return memoryStream; } - /// - /// Download the uri to Bitmap - /// - /// Of an image - /// Bitmap - public static Image DownloadImage(string url) - { - StringBuilder extensions = new StringBuilder(); - foreach (var extension in ImageHelper.StreamConverters.Keys) - { - if (string.IsNullOrEmpty(extension)) - { - continue; - } - extensions.AppendFormat(@"\.{0}|", extension); - } - extensions.Length--; + /// + /// Download the uri to Bitmap + /// + /// Of an image + /// Bitmap + public static Image DownloadImage(string url) + { + var extensions = new StringBuilder(); + foreach (var extension in ImageHelper.StreamConverters.Keys) + { + if (string.IsNullOrEmpty(extension)) + { + continue; + } + + extensions.AppendFormat(@"\.{0}|", extension); + } + + extensions.Length--; var imageUrlRegex = new Regex($@"(http|https)://.*(?{extensions})"); - var match = imageUrlRegex.Match(url); - try + var match = imageUrlRegex.Match(url); + try { using var memoryStream = GetAsMemoryStream(url); try @@ -147,14 +119,16 @@ namespace GreenshotPlugin.Core { { // If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead. string content; - using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8, true)) + using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true)) { content = streamReader.ReadLine(); } + if (string.IsNullOrEmpty(content)) { throw; } + match = imageUrlRegex.Match(content); if (!match.Success) { @@ -165,618 +139,588 @@ namespace GreenshotPlugin.Core { return ImageHelper.FromStream(memoryStream2, match.Groups["extension"]?.Value); } } - catch (Exception e) - { - Log.Error("Problem downloading the image from: " + url, e); - } - return null; - } + catch (Exception e) + { + Log.Error("Problem downloading the image from: " + url, e); + } - /// - /// Helper method to create a web request with a lot of default settings - /// - /// string with uri to connect to - /// WebRequest - public static HttpWebRequest CreateWebRequest(string uri) { - return CreateWebRequest(new Uri(uri)); - } + return null; + } - /// - /// Helper method to create a web request with a lot of default settings - /// - /// string with uri to connect to - /// /// Method to use - /// WebRequest - public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method) { - return CreateWebRequest(new Uri(uri), method); - } + /// + /// Helper method to create a web request with a lot of default settings + /// + /// string with uri to connect to + /// WebRequest + public static HttpWebRequest CreateWebRequest(string uri) + { + return CreateWebRequest(new Uri(uri)); + } - /// - /// Helper method to create a web request with a lot of default settings - /// - /// Uri with uri to connect to - /// Method to use - /// WebRequest - public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) { - HttpWebRequest webRequest = CreateWebRequest(uri); - webRequest.Method = method.ToString(); - return webRequest; - } + /// + /// Helper method to create a web request with a lot of default settings + /// + /// string with uri to connect to + /// /// Method to use + /// WebRequest + public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method) + { + return CreateWebRequest(new Uri(uri), method); + } - /// - /// Helper method to create a web request, eventually with proxy - /// - /// Uri with uri to connect to - /// WebRequest - public static HttpWebRequest CreateWebRequest(Uri uri) { - HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri); - webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null; - // Make sure the default credentials are available - webRequest.Credentials = CredentialCache.DefaultCredentials; + /// + /// Helper method to create a web request with a lot of default settings + /// + /// Uri with uri to connect to + /// Method to use + /// WebRequest + public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method) + { + var webRequest = CreateWebRequest(uri); + webRequest.Method = method.ToString(); + return webRequest; + } - // Allow redirect, this is usually needed so that we don't get a problem when a service moves - webRequest.AllowAutoRedirect = true; - // Set default timeouts - webRequest.Timeout = Config.WebRequestTimeout*1000; - webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout*1000; - return webRequest; - } + /// + /// Helper method to create a web request, eventually with proxy + /// + /// Uri with uri to connect to + /// WebRequest + public static HttpWebRequest CreateWebRequest(Uri uri) + { + var webRequest = (HttpWebRequest)WebRequest.Create(uri); + webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null; + // Make sure the default credentials are available + webRequest.Credentials = CredentialCache.DefaultCredentials; - /// - /// Create a IWebProxy Object which can be used to access the Internet - /// This method will check the configuration if the proxy is allowed to be used. - /// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins - /// - /// - /// IWebProxy filled with all the proxy details or null if none is set/wanted - public static IWebProxy CreateProxy(Uri uri) { - IWebProxy proxyToUse = null; - if (Config.UseProxy) { - proxyToUse = WebRequest.DefaultWebProxy; - if (proxyToUse != null) { - proxyToUse.Credentials = CredentialCache.DefaultCredentials; - if (Log.IsDebugEnabled) { - // check the proxy for the Uri - if (!proxyToUse.IsBypassed(uri)) { - Uri proxyUri = proxyToUse.GetProxy(uri); - if (proxyUri != null) { - Log.Debug("Using proxy: " + proxyUri + " for " + uri); - } else { - Log.Debug("No proxy found!"); - } - } else { - Log.Debug("Proxy bypass for: " + uri); - } - } - } else { - Log.Debug("No proxy found!"); - } - } - return proxyToUse; - } + // Allow redirect, this is usually needed so that we don't get a problem when a service moves + webRequest.AllowAutoRedirect = true; + // Set default timeouts + webRequest.Timeout = Config.WebRequestTimeout * 1000; + webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout * 1000; + return webRequest; + } - /// - /// UrlEncodes a string without the requirement for System.Web - /// - /// - /// - // [Obsolete("Use System.Uri.EscapeDataString instead")] - public static string UrlEncode(string text) { - if (!string.IsNullOrEmpty(text)) { - // Sytem.Uri provides reliable parsing, but doesn't encode spaces. - return Uri.EscapeDataString(text).Replace("%20", "+"); - } - return null; - } + /// + /// Create a IWebProxy Object which can be used to access the Internet + /// This method will check the configuration if the proxy is allowed to be used. + /// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins + /// + /// + /// IWebProxy filled with all the proxy details or null if none is set/wanted + public static IWebProxy CreateProxy(Uri uri) + { + IWebProxy proxyToUse = null; + if (!Config.UseProxy) + { + return proxyToUse; + } - /// - /// A wrapper around the EscapeDataString, as the limit is 32766 characters - /// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx - /// - /// - /// escaped data string - public static string EscapeDataString(string text) { - if (!string.IsNullOrEmpty(text)) { - StringBuilder result = new StringBuilder(); - int currentLocation = 0; - while (currentLocation < text.Length) { - string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation)); - result.Append(Uri.EscapeDataString(process)); - currentLocation += 16384; - } - return result.ToString(); - } - return null; - } + proxyToUse = WebRequest.DefaultWebProxy; + if (proxyToUse != null) + { + proxyToUse.Credentials = CredentialCache.DefaultCredentials; + if (!Log.IsDebugEnabled) + { + return proxyToUse; + } - /// - /// UrlDecodes a string without requiring System.Web - /// - /// String to decode. - /// decoded string - public static string UrlDecode(string text) { - // pre-process for + sign space formatting since System.Uri doesn't handle it - // plus literals are encoded as %2b normally so this should be safe - text = text.Replace("+", " "); - return Uri.UnescapeDataString(text); - } + // check the proxy for the Uri + if (!proxyToUse.IsBypassed(uri)) + { + var proxyUri = proxyToUse.GetProxy(uri); + if (proxyUri != null) + { + Log.Debug("Using proxy: " + proxyUri + " for " + uri); + } + else + { + Log.Debug("No proxy found!"); + } + } + else + { + Log.Debug("Proxy bypass for: " + uri); + } + } + else + { + Log.Debug("No proxy found!"); + } - /// - /// ParseQueryString without the requirement for System.Web - /// - /// - /// IDictionary string, string - public static IDictionary ParseQueryString(string queryString) { - IDictionary parameters = new SortedDictionary(); - // remove anything other than query string from uri - if (queryString.Contains("?")) { - queryString = queryString.Substring(queryString.IndexOf('?') + 1); - } - foreach (string vp in Regex.Split(queryString, "&")) { - if (string.IsNullOrEmpty(vp)) { - continue; - } - string[] singlePair = Regex.Split(vp, "="); - if (parameters.ContainsKey(singlePair[0])) { - parameters.Remove(singlePair[0]); - } - parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty); - } - return parameters; - } + return proxyToUse; + } - /// - /// Generate the query paramters - /// - /// the list of query parameters - /// a string with the query parameters - public static string GenerateQueryParameters(IDictionary queryParameters) { - if (queryParameters == null || queryParameters.Count == 0) { - return string.Empty; - } + /// + /// UrlEncodes a string without the requirement for System.Web + /// + /// + /// + // [Obsolete("Use System.Uri.EscapeDataString instead")] + public static string UrlEncode(string text) + { + if (!string.IsNullOrEmpty(text)) + { + // System.Uri provides reliable parsing, but doesn't encode spaces. + return Uri.EscapeDataString(text).Replace("%20", "+"); + } - queryParameters = new SortedDictionary(queryParameters); + return null; + } - StringBuilder sb = new StringBuilder(); - foreach(string key in queryParameters.Keys) { - sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode($"{queryParameters[key]}")); - } - sb.Remove(sb.Length-1,1); + /// + /// A wrapper around the EscapeDataString, as the limit is 32766 characters + /// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx + /// + /// + /// escaped data string + public static string EscapeDataString(string text) + { + if (!string.IsNullOrEmpty(text)) + { + var result = new StringBuilder(); + int currentLocation = 0; + while (currentLocation < text.Length) + { + string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation)); + result.Append(Uri.EscapeDataString(process)); + currentLocation += 16384; + } - return sb.ToString(); - } + return result.ToString(); + } - /// - /// Write Multipart Form Data directly to the HttpWebRequest - /// - /// HttpWebRequest to write the multipart form data to - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary postParameters) { - string boundary = $"----------{Guid.NewGuid():N}"; - webRequest.ContentType = "multipart/form-data; boundary=" + boundary; + return null; + } + + /// + /// UrlDecodes a string without requiring System.Web + /// + /// String to decode. + /// decoded string + public static string UrlDecode(string text) + { + // pre-process for + sign space formatting since System.Uri doesn't handle it + // plus literals are encoded as %2b normally so this should be safe + text = text.Replace("+", " "); + return Uri.UnescapeDataString(text); + } + + /// + /// ParseQueryString without the requirement for System.Web + /// + /// + /// IDictionary string, string + public static IDictionary ParseQueryString(string queryString) + { + IDictionary parameters = new SortedDictionary(); + // remove anything other than query string from uri + if (queryString.Contains("?")) + { + queryString = queryString.Substring(queryString.IndexOf('?') + 1); + } + + foreach (string vp in Regex.Split(queryString, "&")) + { + if (string.IsNullOrEmpty(vp)) + { + continue; + } + + string[] singlePair = Regex.Split(vp, "="); + if (parameters.ContainsKey(singlePair[0])) + { + parameters.Remove(singlePair[0]); + } + + parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty); + } + + return parameters; + } + + /// + /// Generate the query parameters + /// + /// the list of query parameters + /// a string with the query parameters + public static string GenerateQueryParameters(IDictionary queryParameters) + { + if (queryParameters == null || queryParameters.Count == 0) + { + return string.Empty; + } + + queryParameters = new SortedDictionary(queryParameters); + + var sb = new StringBuilder(); + foreach (string key in queryParameters.Keys) + { + sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode($"{queryParameters[key]}")); + } + + sb.Remove(sb.Length - 1, 1); + + return sb.ToString(); + } + + /// + /// Write Multipart Form Data directly to the HttpWebRequest + /// + /// HttpWebRequest to write the multipart form data to + /// Parameters to include in the multipart form data + public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary postParameters) + { + string boundary = $"----------{Guid.NewGuid():N}"; + webRequest.ContentType = "multipart/form-data; boundary=" + boundary; using Stream formDataStream = webRequest.GetRequestStream(); WriteMultipartFormData(formDataStream, boundary, postParameters); } - /// - /// Write Multipart Form Data to the HttpListenerResponse - /// - /// HttpListenerResponse - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary postParameters) { - string boundary = $"----------{Guid.NewGuid():N}"; - response.ContentType = "multipart/form-data; boundary=" + boundary; - WriteMultipartFormData(response.OutputStream, boundary, postParameters); - } + /// + /// Write Multipart Form Data to a Stream, content-type should be set before this! + /// + /// Stream to write the multipart form data to + /// String boundary for the multipart/form-data + /// Parameters to include in the multipart form data + public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary postParameters) + { + bool needsClrf = false; + foreach (var param in postParameters) + { + // Add a CRLF to allow multiple parameters to be added. + // Skip it on the first parameter, add it to subsequent parameters. + if (needsClrf) + { + formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); + } - /// - /// Write Multipart Form Data to a Stream, content-type should be set before this! - /// - /// Stream to write the multipart form data to - /// String boundary for the multipart/form-data - /// Parameters to include in the multipart form data - public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary postParameters) { - bool needsClrf = false; - foreach (var param in postParameters) { - // Add a CRLF to allow multiple parameters to be added. - // Skip it on the first parameter, add it to subsequent parameters. - if (needsClrf) { - formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); - } + needsClrf = true; - needsClrf = true; + if (param.Value is IBinaryContainer binaryContainer) + { + binaryContainer.WriteFormDataToStream(boundary, param.Key, formDataStream); + } + else + { + string postData = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{param.Key}\"\r\n\r\n{param.Value}"; + formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); + } + } - if (param.Value is IBinaryContainer binaryContainer) { - binaryContainer.WriteFormDataToStream(boundary, param.Key, formDataStream); - } else { - string postData = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{param.Key}\"\r\n\r\n{param.Value}"; - formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); - } - } + // Add the end of the request. Start with a newline + string footer = "\r\n--" + boundary + "--\r\n"; + formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); + } - // Add the end of the request. Start with a newline - string footer = "\r\n--" + boundary + "--\r\n"; - formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); - } + /// + /// Post content HttpWebRequest + /// + /// HttpWebRequest to write the multipart form data to + /// IDictionary with the headers + /// IBinaryContainer + public static void Post(HttpWebRequest webRequest, IDictionary headers, IBinaryContainer binaryContainer = null) + { + foreach (var header in headers) + { + switch (header.Key) + { + case "Content-Type": + webRequest.ContentType = header.Value as string; + break; + case "Accept": + webRequest.Accept = header.Value as string; + break; + default: + webRequest.Headers.Add(header.Key, Convert.ToString(header.Value)); + break; + } + } + if (!headers.ContainsKey("Content-Type")) + { + webRequest.ContentType = "application/octet-stream"; + } - /// - /// Post the parameters "x-www-form-urlencoded" - /// - /// - /// - public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary parameters) { - webRequest.ContentType = "application/x-www-form-urlencoded"; - string urlEncoded = GenerateQueryParameters(parameters); + if (binaryContainer != null) + { + using var requestStream = webRequest.GetRequestStream(); + binaryContainer.WriteToStream(requestStream); + } + } - byte[] data = Encoding.UTF8.GetBytes(urlEncoded); + /// + /// Post content HttpWebRequest + /// + /// HttpWebRequest to write the multipart form data to + /// IDictionary with the headers + /// string + public static void Post(HttpWebRequest webRequest, IDictionary headers, string jsonString) + { + if (headers != null) + { + foreach (var header in headers) + { + switch (header.Key) + { + case "Content-Type": + webRequest.ContentType = header.Value as string; + break; + case "Accept": + webRequest.Accept = header.Value as string; + break; + default: + webRequest.Headers.Add(header.Key, Convert.ToString(header.Value)); + break; + } + } + if (!headers.ContainsKey("Content-Type")) + { + webRequest.ContentType = "application/json"; + } + } + else + { + webRequest.ContentType = "application/json"; + } + + if (jsonString != null) + { + using var requestStream = webRequest.GetRequestStream(); + using var streamWriter = new StreamWriter(requestStream); + streamWriter.Write(jsonString); + } + } + + /// + /// Post the parameters "x-www-form-urlencoded" + /// + /// + /// + public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary parameters) + { + webRequest.ContentType = "application/x-www-form-urlencoded"; + string urlEncoded = GenerateQueryParameters(parameters); + + byte[] data = Encoding.UTF8.GetBytes(urlEncoded); using var requestStream = webRequest.GetRequestStream(); requestStream.Write(data, 0, data.Length); } - /// - /// Log the headers of the WebResponse, if IsDebugEnabled - /// - /// WebResponse - private static void DebugHeaders(WebResponse response) { - if (!Log.IsDebugEnabled) { - return; - } - Log.DebugFormat("Debug information on the response from {0} :", response.ResponseUri); - foreach (string key in response.Headers.AllKeys) { - Log.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]); - } - } + /// + /// Log the headers of the WebResponse, if IsDebugEnabled + /// + /// WebResponse + private static void DebugHeaders(WebResponse response) + { + if (!Log.IsDebugEnabled) + { + return; + } - /// - /// Process the web response. - /// - /// The request object. - /// The response data. - /// TODO: This method should handle the StatusCode better! - public static string GetResponseAsString(HttpWebRequest webRequest) { - return GetResponseAsString(webRequest, false); - } + Log.DebugFormat("Debug information on the response from {0} :", response.ResponseUri); + foreach (string key in response.Headers.AllKeys) + { + Log.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]); + } + } - /// - /// Read the response as string - /// - /// - /// string or null - private static string GetResponseAsString(HttpWebResponse response) - { - string responseData = null; - if (response == null) - { - return null; - } - using (response) - { - Stream responseStream = response.GetResponseStream(); - if (responseStream != null) + /// + /// Process the web response. + /// + /// The request object. + /// The response data. + /// TODO: This method should handle the StatusCode better! + public static string GetResponseAsString(HttpWebRequest webRequest) + { + return GetResponseAsString(webRequest, false); + } + + /// + /// Read the response as string + /// + /// + /// string or null + private static string GetResponseAsString(HttpWebResponse response) + { + string responseData = null; + if (response == null) + { + return null; + } + + using (response) + { + Stream responseStream = response.GetResponseStream(); + if (responseStream != null) { using StreamReader reader = new StreamReader(responseStream, true); responseData = reader.ReadToEnd(); } - } - return responseData; - } + } - /// - /// - /// - /// - /// - /// - public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) { - string responseData = null; - HttpWebResponse response = null; - bool isHttpError = false; - try { - response = (HttpWebResponse)webRequest.GetResponse(); - Log.InfoFormat("Response status: {0}", response.StatusCode); - isHttpError = (int)response.StatusCode >= 300; - if (isHttpError) - { - Log.ErrorFormat("HTTP error {0}", response.StatusCode); - } - DebugHeaders(response); - responseData = GetResponseAsString(response); - if (isHttpError) - { - Log.ErrorFormat("HTTP response {0}", responseData); - } - } - catch (WebException e) { - response = (HttpWebResponse) e.Response; - HttpStatusCode statusCode = HttpStatusCode.Unused; - if (response != null) { - statusCode = response.StatusCode; - Log.ErrorFormat("HTTP error {0}", statusCode); - string errorContent = GetResponseAsString(response); - if (alsoReturnContentOnError) - { - return errorContent; - } - Log.ErrorFormat("Content: {0}", errorContent); - } - Log.Error("WebException: ", e); - if (statusCode == HttpStatusCode.Unauthorized) - { - throw new UnauthorizedAccessException(e.Message); - } - throw; - } - finally - { - if (response != null) - { - if (isHttpError) - { - Log.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); - } - response.Close(); - } - } - return responseData; - } - - /// - /// Get LastModified for a URI - /// - /// Uri - /// DateTime - public static DateTime GetLastModified(Uri uri) { - try { - HttpWebRequest webRequest = CreateWebRequest(uri); - webRequest.Method = HTTPMethod.HEAD.ToString(); - using HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); - Log.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified); - return webResponse.LastModified; - } catch (Exception wE) { - Log.WarnFormat("Problem requesting HTTP - HEAD on uri {0}", uri); - Log.Warn(wE.Message); - // Pretend it is old - return DateTime.MinValue; - } - } - } - - /// - /// This interface can be used to pass binary information around, like byte[] or Image - /// - public interface IBinaryContainer { - void WriteFormDataToStream(string boundary, string name, Stream formDataStream); - void WriteToStream(Stream formDataStream); - string ToBase64String(Base64FormattingOptions formattingOptions); - byte[] ToByteArray(); - void Upload(HttpWebRequest webRequest); - - string ContentType { get; } - string Filename { get; set; } - } - - /// - /// A container to supply files to a Multi-part form data upload - /// - public class ByteContainer : IBinaryContainer { - private readonly byte[] _file; - private readonly string _contentType; - private readonly int _fileSize; - public ByteContainer(byte[] file) : this(file, null) { - } - public ByteContainer(byte[] file, string filename) : this(file, filename, null) { - } - public ByteContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0) { - } - public ByteContainer(byte[] file, string filename, string contenttype, int filesize) { - _file = file; - Filename = filename; - _contentType = contenttype; - _fileSize = filesize == 0 ? file.Length : filesize; - } - - /// - /// Create a Base64String from the byte[] - /// - /// string - public string ToBase64String(Base64FormattingOptions formattingOptions) { - return Convert.ToBase64String(_file, 0, _fileSize, formattingOptions); - } - - /// - /// Returns the initial byte-array which was supplied when creating the FileParameter - /// - /// byte[] - public byte[] ToByteArray() { - return _file; - } - - /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream - /// - /// Separator - /// name - /// Stream to write to - public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) { - // Add just the first part of this param, since we will write the file data directly to the Stream - string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {_contentType ?? "application/octet-stream"}\r\n\r\n"; - - formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); - - // Write the file data directly to the Stream, rather than serializing it to a string. - formDataStream.Write(_file, 0, _fileSize); - } - - /// - /// A plain "write data to stream" - /// - /// Stream to write to - public void WriteToStream(Stream dataStream) { - // Write the file data directly to the Stream, rather than serializing it to a string. - dataStream.Write(_file, 0, _fileSize); - } - - /// - /// Upload the file to the webrequest - /// - /// - public void Upload(HttpWebRequest webRequest) { - webRequest.ContentType = _contentType; - webRequest.ContentLength = _fileSize; - using var requestStream = webRequest.GetRequestStream(); - WriteToStream(requestStream); + return responseData; } - public string ContentType => _contentType; - public string Filename { get; set; } - } - - /// - /// A container to supply images to a Multi-part form data upload - /// - public class BitmapContainer : IBinaryContainer { - private readonly Bitmap _bitmap; - private readonly SurfaceOutputSettings _outputSettings; - - public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename) { - _bitmap = bitmap; - _outputSettings = outputSettings; - Filename = filename; - } - - /// - /// Create a Base64String from the image by saving it to a memory stream and converting it. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// string - public string ToBase64String(Base64FormattingOptions formattingOptions) + /// + /// + /// + /// + /// + /// + public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError) { - using MemoryStream stream = new MemoryStream(); - ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings); - return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions); + string responseData = null; + HttpWebResponse response = null; + bool isHttpError = false; + try + { + response = (HttpWebResponse)webRequest.GetResponse(); + Log.InfoFormat("Response status: {0}", response.StatusCode); + isHttpError = (int)response.StatusCode >= 300; + if (isHttpError) + { + Log.ErrorFormat("HTTP error {0}", response.StatusCode); + } + + DebugHeaders(response); + responseData = GetResponseAsString(response); + if (isHttpError) + { + Log.ErrorFormat("HTTP response {0}", responseData); + } + } + catch (WebException e) + { + response = (HttpWebResponse)e.Response; + HttpStatusCode statusCode = HttpStatusCode.Unused; + if (response != null) + { + statusCode = response.StatusCode; + Log.ErrorFormat("HTTP error {0}", statusCode); + string errorContent = GetResponseAsString(response); + if (alsoReturnContentOnError) + { + return errorContent; + } + + Log.ErrorFormat("Content: {0}", errorContent); + } + + Log.Error("WebException: ", e); + if (statusCode == HttpStatusCode.Unauthorized) + { + throw new UnauthorizedAccessException(e.Message); + } + + throw; + } + finally + { + if (response != null) + { + if (isHttpError) + { + Log.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData); + } + + response.Close(); + } + } + + return responseData; } - /// - /// Create a byte[] from the image by saving it to a memory stream. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// byte[] - public byte[] ToByteArray() + } + /// + /// This interface can be used to pass binary information around, like byte[] or Image + /// + public interface IBinaryContainer + { + void WriteFormDataToStream(string boundary, string name, Stream formDataStream); + void WriteToStream(Stream formDataStream); + string ToBase64String(Base64FormattingOptions formattingOptions); + byte[] ToByteArray(); + void Upload(HttpWebRequest webRequest); + + string ContentType { get; } + string Filename { get; set; } + } + + /// A container to supply surfaces to a Multi-part form data upload + /// + public class SurfaceContainer : IBinaryContainer + { + private readonly ISurface _surface; + private readonly SurfaceOutputSettings _outputSettings; + + public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename) { - using MemoryStream stream = new MemoryStream(); - ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings); - return stream.ToArray(); + _surface = surface; + _outputSettings = outputSettings; + Filename = filename; } - /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream - /// - /// Separator - /// Name of the thing/file - /// Stream to write to - public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) { - // Add just the first part of this param, since we will write the file data directly to the Stream - string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n"; - - formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); - ImageOutput.SaveToStream(_bitmap, null, formDataStream, _outputSettings); - } - - /// - /// A plain "write data to stream" - /// - /// - public void WriteToStream(Stream dataStream) { - // Write the file data directly to the Stream, rather than serializing it to a string. - ImageOutput.SaveToStream(_bitmap, null, dataStream, _outputSettings); - } - - /// - /// Upload the image to the webrequest - /// - /// - public void Upload(HttpWebRequest webRequest) { - webRequest.ContentType = "image/" + _outputSettings.Format; - using var requestStream = webRequest.GetRequestStream(); - WriteToStream(requestStream); - } - - public string ContentType => "image/" + _outputSettings.Format; - - public string Filename { get; set; } - } - - /// - /// A container to supply surfaces to a Multi-part form data upload - /// - public class SurfaceContainer : IBinaryContainer { - private readonly ISurface _surface; - private readonly SurfaceOutputSettings _outputSettings; - - public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename) { - _surface = surface; - _outputSettings = outputSettings; - Filename = filename; - } - - /// - /// Create a Base64String from the Surface by saving it to a memory stream and converting it. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// string - public string ToBase64String(Base64FormattingOptions formattingOptions) + /// + /// Create a Base64String from the Surface by saving it to a memory stream and converting it. + /// Should be avoided if possible, as this uses a lot of memory. + /// + /// string + public string ToBase64String(Base64FormattingOptions formattingOptions) { using MemoryStream stream = new MemoryStream(); ImageOutput.SaveToStream(_surface, stream, _outputSettings); return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions); } - /// - /// Create a byte[] from the image by saving it to a memory stream. - /// Should be avoided if possible, as this uses a lot of memory. - /// - /// byte[] - public byte[] ToByteArray() + /// + /// Create a byte[] from the image by saving it to a memory stream. + /// Should be avoided if possible, as this uses a lot of memory. + /// + /// byte[] + public byte[] ToByteArray() { using MemoryStream stream = new MemoryStream(); ImageOutput.SaveToStream(_surface, stream, _outputSettings); return stream.ToArray(); } - /// - /// Write Multipart Form Data directly to the HttpWebRequest response stream - /// - /// Multipart separator - /// Name of the thing - /// Stream to write to - public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) { - // Add just the first part of this param, since we will write the file data directly to the Stream - string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n"; + /// + /// Write Multipart Form Data directly to the HttpWebRequest response stream + /// + /// Multipart separator + /// Name of the thing + /// Stream to write to + public void WriteFormDataToStream(string boundary, string name, Stream formDataStream) + { + // Add just the first part of this param, since we will write the file data directly to the Stream + string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n"; - formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); - ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings); - } + formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header)); + ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings); + } - /// - /// A plain "write data to stream" - /// - /// - public void WriteToStream(Stream dataStream) { - // Write the file data directly to the Stream, rather than serializing it to a string. - ImageOutput.SaveToStream(_surface, dataStream, _outputSettings); - } + /// + /// A plain "write data to stream" + /// + /// + public void WriteToStream(Stream dataStream) + { + // Write the file data directly to the Stream, rather than serializing it to a string. + ImageOutput.SaveToStream(_surface, dataStream, _outputSettings); + } - /// - /// Upload the Surface as image to the webrequest - /// - /// - public void Upload(HttpWebRequest webRequest) { - webRequest.ContentType = ContentType; + /// + /// Upload the Surface as image to the webrequest + /// + /// + public void Upload(HttpWebRequest webRequest) + { + webRequest.ContentType = ContentType; using var requestStream = webRequest.GetRequestStream(); WriteToStream(requestStream); } - public string ContentType => "image/" + _outputSettings.Format; - public string Filename { get; set; } - } -} + public string ContentType => "image/" + _outputSettings.Format; + public string Filename { get; set; } + } +} \ No newline at end of file diff --git a/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs b/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs new file mode 100644 index 000000000..7b363b2fa --- /dev/null +++ b/GreenshotPlugin/Core/OAuth/LocalJsonReceiver.cs @@ -0,0 +1,191 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using log4net; +using Newtonsoft.Json; + +namespace GreenshotPlugin.Core.OAuth +{ + /// + /// OAuth 2.0 verification code receiver that runs a local server on a free port + /// and waits for a call with the authorization verification code. + /// + public class LocalJsonReceiver + { + private static readonly ILog Log = LogManager.GetLogger(typeof(LocalJsonReceiver)); + private readonly ManualResetEvent _ready = new ManualResetEvent(true); + private IDictionary _returnValues; + + /// + /// The url format for the website to post to. Expects one port parameter. + /// Default: http://localhost:{0}/authorize/ + /// + public string ListeningUrlFormat { get; set; } = "http://localhost:{0}/authorize/"; + + private string _listeningUri; + /// + /// The URL where the server is listening + /// + public string ListeningUri { + get { + if (string.IsNullOrEmpty(_listeningUri)) + { + _listeningUri = string.Format(ListeningUrlFormat, GetRandomUnusedPort()); + } + return _listeningUri; + } + set => _listeningUri = value; + } + + /// + /// This action is called when the URI must be opened, default is just to run Process.Start + /// + public Action OpenUriAction + { + set; + get; + } = authorizationUrl => + { + Log.DebugFormat("Open a browser with: {0}", authorizationUrl); + using var process = Process.Start(authorizationUrl); + }; + + /// + /// Timeout for waiting for the website to respond + /// + public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(4); + + /// + /// The OAuth code receiver + /// + /// OAuth2Settings + /// Dictionary with values + public IDictionary ReceiveCode(OAuth2Settings oauth2Settings) { + using var listener = new HttpListener(); + // Make sure the port is stored in the state, so the website can process this. + oauth2Settings.State = new Uri(ListeningUri).Port.ToString(); + listener.Prefixes.Add(ListeningUri); + try { + listener.Start(); + _ready.Reset(); + + listener.BeginGetContext(ListenerCallback, listener); + OpenUriAction(oauth2Settings.FormattedAuthUrl); + _ready.WaitOne(Timeout, true); + } catch (Exception) { + // Make sure we can clean up, also if the thead is aborted + _ready.Set(); + throw; + } finally { + listener.Close(); + } + + return _returnValues; + } + + /// + /// Handle a connection async, this allows us to break the waiting + /// + /// IAsyncResult + private void ListenerCallback(IAsyncResult result) { + HttpListener listener = (HttpListener)result.AsyncState; + + //If not listening return immediately as this method is called one last time after Close() + if (!listener.IsListening) { + return; + } + + // Use EndGetContext to complete the asynchronous operation. + HttpListenerContext context = listener.EndGetContext(result); + + // Handle request + HttpListenerRequest request = context.Request; + + if (request.HasEntityBody) + { + // Process the body + using var body = request.InputStream; + using var reader = new StreamReader(body, request.ContentEncoding); + using var jsonTextReader = new JsonTextReader(reader); + var serializer = new JsonSerializer(); + _returnValues = serializer.Deserialize>(jsonTextReader); + } + + // Create the response. + using (HttpListenerResponse response = context.Response) + { + if (request.HttpMethod == "OPTIONS") + { + response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With"); + response.AddHeader("Access-Control-Allow-Methods", "POST"); + response.AddHeader("Access-Control-Max-Age", "1728000"); + } + + response.AppendHeader("Access-Control-Allow-Origin", "*"); + if (request.HasEntityBody) + { + response.ContentType = "application/json"; + // currently only return the version, more can be added later + string jsonContent = "{\"version\": \"" + EnvironmentInfo.GetGreenshotVersion(true) + "\"}"; + + // Write a "close" response. + byte[] buffer = Encoding.UTF8.GetBytes(jsonContent); + // Write to response stream. + response.ContentLength64 = buffer.Length; + using var stream = response.OutputStream; + stream.Write(buffer, 0, buffer.Length); + } + } + + if (_returnValues != null) + { + _ready.Set(); + } + else + { + // Make sure the next request is processed + listener.BeginGetContext(ListenerCallback, listener); + } + } + + /// + /// Returns a random, unused port. + /// + /// port to use + private static int GetRandomUnusedPort() { + var listener = new TcpListener(IPAddress.Loopback, 0); + try { + listener.Start(); + return ((IPEndPoint)listener.LocalEndpoint).Port; + } finally { + listener.Stop(); + } + } + } +} \ No newline at end of file diff --git a/GreenshotPlugin/Core/OAuth/LocalServerCodeReceiver.cs b/GreenshotPlugin/Core/OAuth/LocalServerCodeReceiver.cs new file mode 100644 index 000000000..a4915e8b6 --- /dev/null +++ b/GreenshotPlugin/Core/OAuth/LocalServerCodeReceiver.cs @@ -0,0 +1,183 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using log4net; + +namespace GreenshotPlugin.Core.OAuth +{ + /// + /// OAuth 2.0 verification code receiver that runs a local server on a free port + /// and waits for a call with the authorization verification code. + /// + public class LocalServerCodeReceiver { + private static readonly ILog Log = LogManager.GetLogger(typeof(LocalServerCodeReceiver)); + private readonly ManualResetEvent _ready = new ManualResetEvent(true); + + /// + /// The call back format. Expects one port parameter. + /// Default: http://localhost:{0}/authorize/ + /// + public string LoopbackCallbackUrl { get; set; } = "http://localhost:{0}/authorize/"; + + /// + /// HTML code to to return the _browser, default it will try to close the _browser / tab, this won't always work. + /// You can use CloudServiceName where you want to show the CloudServiceName from your OAuth2 settings + /// + public string ClosePageResponse { get; set; } = @" +OAuth 2.0 Authentication CloudServiceName + +Greenshot received information from CloudServiceName. You can close this browser / tab if it is not closed itself... + + +"; + + private string _redirectUri; + /// + /// The URL to redirect to + /// + protected string RedirectUri { + get { + if (!string.IsNullOrEmpty(_redirectUri)) { + return _redirectUri; + } + + return _redirectUri = string.Format(LoopbackCallbackUrl, GetRandomUnusedPort()); + } + } + + private string _cloudServiceName; + + private readonly IDictionary _returnValues = new Dictionary(); + + + /// + /// The OAuth code receiver + /// + /// + /// Dictionary with values + public IDictionary ReceiveCode(OAuth2Settings oauth2Settings) { + // Set the redirect URL on the settings + oauth2Settings.RedirectUrl = RedirectUri; + _cloudServiceName = oauth2Settings.CloudServiceName; + using (var listener = new HttpListener()) { + listener.Prefixes.Add(oauth2Settings.RedirectUrl); + try { + listener.Start(); + + // Get the formatted FormattedAuthUrl + string authorizationUrl = oauth2Settings.FormattedAuthUrl; + Log.DebugFormat("Open a browser with: {0}", authorizationUrl); + Process.Start(authorizationUrl); + + // Wait to get the authorization code response. + var context = listener.BeginGetContext(ListenerCallback, listener); + _ready.Reset(); + + while (!context.AsyncWaitHandle.WaitOne(1000, true)) { + Log.Debug("Waiting for response"); + } + } catch (Exception) { + // Make sure we can clean up, also if the thead is aborted + _ready.Set(); + throw; + } finally { + _ready.WaitOne(); + listener.Close(); + } + } + return _returnValues; + } + + /// + /// Handle a connection async, this allows us to break the waiting + /// + /// IAsyncResult + private void ListenerCallback(IAsyncResult result) { + HttpListener listener = (HttpListener)result.AsyncState; + + //If not listening return immediately as this method is called one last time after Close() + if (!listener.IsListening) { + return; + } + + // Use EndGetContext to complete the asynchronous operation. + HttpListenerContext context = listener.EndGetContext(result); + + + // Handle request + HttpListenerRequest request = context.Request; + try { + NameValueCollection nameValueCollection = request.QueryString; + + // Get response object. + using (HttpListenerResponse response = context.Response) { + // Write a "close" response. + byte[] buffer = Encoding.UTF8.GetBytes(ClosePageResponse.Replace("CloudServiceName", _cloudServiceName)); + // Write to response stream. + response.ContentLength64 = buffer.Length; + using var stream = response.OutputStream; + stream.Write(buffer, 0, buffer.Length); + } + + // Create a new response URL with a dictionary that contains all the response query parameters. + foreach (var name in nameValueCollection.AllKeys) { + if (!_returnValues.ContainsKey(name)) { + _returnValues.Add(name, nameValueCollection[name]); + } + } + } catch (Exception) { + context.Response.OutputStream.Close(); + throw; + } + _ready.Set(); + } + + /// + /// Returns a random, unused port. + /// + /// port to use + private static int GetRandomUnusedPort() { + var listener = new TcpListener(IPAddress.Loopback, 0); + try { + listener.Start(); + return ((IPEndPoint)listener.LocalEndpoint).Port; + } finally { + listener.Stop(); + } + } + } +} \ No newline at end of file diff --git a/GreenshotPlugin/Interfaces/ICaptureElement.cs b/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs similarity index 57% rename from GreenshotPlugin/Interfaces/ICaptureElement.cs rename to GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs index fc84c1536..98d4515f9 100644 --- a/GreenshotPlugin/Interfaces/ICaptureElement.cs +++ b/GreenshotPlugin/Core/OAuth/OAuth2AuthorizeMode.cs @@ -1,6 +1,6 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot @@ -19,23 +19,15 @@ * along with this program. If not, see . */ -using System.Collections.Generic; -using System.Drawing; - -namespace GreenshotPlugin.Interfaces +namespace GreenshotPlugin.Core.OAuth { - public interface ICaptureElement { - List Children { - get; - set; - } - Rectangle Bounds { - get; - set; - } - string Name { - get; - set; - } + /// + /// Specify the authorize mode that is used to get the token from the cloud service. + /// + public enum OAuth2AuthorizeMode { + Unknown, // Will give an exception, caller needs to specify another value + LocalServer, // Will specify a redirect URL to http://localhost:port/authorize, while having a HttpListener + JsonReceiver, // Will start a local HttpListener and wait for a Json post + EmbeddedBrowser // Will open into an embedded _browser (OAuthLoginForm), and catch the redirect } } \ No newline at end of file diff --git a/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs b/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs new file mode 100644 index 000000000..b80d62b3d --- /dev/null +++ b/GreenshotPlugin/Core/OAuth/OAuth2Helper.cs @@ -0,0 +1,372 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Net; +using GreenshotPlugin.Controls; + +namespace GreenshotPlugin.Core.OAuth { + /// + /// Code to simplify OAuth 2 + /// + public static class OAuth2Helper { + private const string RefreshToken = "refresh_token"; + private const string AccessToken = "access_token"; + private const string Code = "code"; + private const string Error = "error"; + private const string ClientId = "client_id"; + private const string ClientSecret = "client_secret"; + private const string GrantType = "grant_type"; + private const string AuthorizationCode = "authorization_code"; + private const string RedirectUri = "redirect_uri"; + private const string ExpiresIn = "expires_in"; + + /// + /// Generate an OAuth 2 Token by using the supplied code + /// + /// OAuth2Settings to update with the information that was retrieved + public static void GenerateRefreshToken(OAuth2Settings settings) { + IDictionary data = new Dictionary + { + // Use the returned code to get a refresh code + { Code, settings.Code }, + { ClientId, settings.ClientId }, + { ClientSecret, settings.ClientSecret }, + { GrantType, AuthorizationCode } + }; + foreach (string key in settings.AdditionalAttributes.Keys) { + data.Add(key, settings.AdditionalAttributes[key]); + } + + HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(settings.TokenUrl, HTTPMethod.POST); + NetworkHelper.UploadFormUrlEncoded(webRequest, data); + string accessTokenJsonResult = NetworkHelper.GetResponseAsString(webRequest, true); + + IDictionary refreshTokenResult = JSONHelper.JsonDecode(accessTokenJsonResult); + if (refreshTokenResult.ContainsKey("error")) + { + if (refreshTokenResult.ContainsKey("error_description")) { + throw new Exception($"{refreshTokenResult["error"]} - {refreshTokenResult["error_description"]}"); + } + throw new Exception((string)refreshTokenResult["error"]); + } + + // gives as described here: https://developers.google.com/identity/protocols/OAuth2InstalledApp + // "access_token":"1/fFAGRNJru1FTz70BzhT3Zg", + // "expires_in":3920, + // "token_type":"Bearer", + // "refresh_token":"1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" + if (refreshTokenResult.ContainsKey(AccessToken)) + { + settings.AccessToken = (string)refreshTokenResult[AccessToken]; + } + if (refreshTokenResult.ContainsKey(RefreshToken)) + { + settings.RefreshToken = (string)refreshTokenResult[RefreshToken]; + } + if (refreshTokenResult.ContainsKey(ExpiresIn)) + { + object seconds = refreshTokenResult[ExpiresIn]; + if (seconds != null) + { + settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double)seconds); + } + } + settings.Code = null; + } + + /// + /// Used to update the settings with the callback information + /// + /// OAuth2Settings + /// IDictionary + /// true if the access token is already in the callback + private static bool UpdateFromCallback(OAuth2Settings settings, IDictionary callbackParameters) + { + if (!callbackParameters.ContainsKey(AccessToken)) + { + return false; + } + if (callbackParameters.ContainsKey(RefreshToken)) + { + // Refresh the refresh token :) + settings.RefreshToken = callbackParameters[RefreshToken]; + } + if (callbackParameters.ContainsKey(ExpiresIn)) + { + var expiresIn = callbackParameters[ExpiresIn]; + settings.AccessTokenExpires = DateTimeOffset.MaxValue; + if (expiresIn != null) + { + if (double.TryParse(expiresIn, out var seconds)) + { + settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds(seconds); + } + } + } + settings.AccessToken = callbackParameters[AccessToken]; + return true; + } + + /// + /// Go out and retrieve a new access token via refresh-token with the TokenUrl in the settings + /// Will update the access token, refresh token, expire date + /// + /// + public static void GenerateAccessToken(OAuth2Settings settings) { + IDictionary data = new Dictionary + { + { RefreshToken, settings.RefreshToken }, + { ClientId, settings.ClientId }, + { ClientSecret, settings.ClientSecret }, + { GrantType, RefreshToken } + }; + foreach (string key in settings.AdditionalAttributes.Keys) { + data.Add(key, settings.AdditionalAttributes[key]); + } + + HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(settings.TokenUrl, HTTPMethod.POST); + NetworkHelper.UploadFormUrlEncoded(webRequest, data); + string accessTokenJsonResult = NetworkHelper.GetResponseAsString(webRequest, true); + + // gives as described here: https://developers.google.com/identity/protocols/OAuth2InstalledApp + // "access_token":"1/fFAGRNJru1FTz70BzhT3Zg", + // "expires_in":3920, + // "token_type":"Bearer", + + IDictionary accessTokenResult = JSONHelper.JsonDecode(accessTokenJsonResult); + if (accessTokenResult.ContainsKey("error")) + { + if ("invalid_grant" == (string)accessTokenResult["error"]) { + // Refresh token has also expired, we need a new one! + settings.RefreshToken = null; + settings.AccessToken = null; + settings.AccessTokenExpires = DateTimeOffset.MinValue; + settings.Code = null; + return; + } + + if (accessTokenResult.ContainsKey("error_description")) { + throw new Exception($"{accessTokenResult["error"]} - {accessTokenResult["error_description"]}"); + } + + throw new Exception((string)accessTokenResult["error"]); + } + + if (accessTokenResult.ContainsKey(AccessToken)) + { + settings.AccessToken = (string) accessTokenResult[AccessToken]; + settings.AccessTokenExpires = DateTimeOffset.MaxValue; + } + if (accessTokenResult.ContainsKey(RefreshToken)) { + // Refresh the refresh token :) + settings.RefreshToken = (string)accessTokenResult[RefreshToken]; + } + if (accessTokenResult.ContainsKey(ExpiresIn)) + { + object seconds = accessTokenResult[ExpiresIn]; + if (seconds != null) + { + settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double) seconds); + } + } + } + + /// + /// Authorize by using the mode specified in the settings + /// + /// OAuth2Settings + /// false if it was canceled, true if it worked, exception if not + public static bool Authorize(OAuth2Settings settings) { + var completed = settings.AuthorizeMode switch + { + OAuth2AuthorizeMode.LocalServer => AuthorizeViaLocalServer(settings), + OAuth2AuthorizeMode.EmbeddedBrowser => AuthorizeViaEmbeddedBrowser(settings), + OAuth2AuthorizeMode.JsonReceiver => AuthorizeViaDefaultBrowser(settings), + _ => throw new NotImplementedException($"Authorize mode '{settings.AuthorizeMode}' is not 'yet' implemented."), + }; + return completed; + } + + /// + /// Authorize via the default browser, via the Greenshot website. + /// It will wait for a Json post. + /// If this works, return the code + /// + /// OAuth2Settings with the Auth / Token url etc + /// true if completed, false if canceled + private static bool AuthorizeViaDefaultBrowser(OAuth2Settings settings) + { + var codeReceiver = new LocalJsonReceiver(); + IDictionary result = codeReceiver.ReceiveCode(settings); + + if (result == null || result.Count == 0) + { + return false; + } + foreach (var key in result.Keys) + { + switch (key) + { + case AccessToken: + settings.AccessToken = result[key]; + break; + case ExpiresIn: + if (int.TryParse(result[key], out var seconds)) + { + settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds(seconds); + } + break; + case RefreshToken: + settings.RefreshToken = result[key]; + break; + } + } + + if (result.TryGetValue("error", out var error)) + { + if (result.TryGetValue("error_description", out var errorDescription)) + { + throw new Exception(errorDescription); + } + if ("access_denied" == error) + { + throw new UnauthorizedAccessException("Access denied"); + } + throw new Exception(error); + } + if (result.TryGetValue(Code, out var code) && !string.IsNullOrEmpty(code)) + { + settings.Code = code; + GenerateRefreshToken(settings); + return !string.IsNullOrEmpty(settings.AccessToken); + } + + return true; + } + + /// + /// Authorize via an embedded browser + /// If this works, return the code + /// + /// OAuth2Settings with the Auth / Token url etc + /// true if completed, false if canceled + private static bool AuthorizeViaEmbeddedBrowser(OAuth2Settings settings) { + if (string.IsNullOrEmpty(settings.CloudServiceName)) { + throw new ArgumentNullException(nameof(settings.CloudServiceName)); + } + if (settings.BrowserSize == Size.Empty) { + throw new ArgumentNullException(nameof(settings.BrowserSize)); + } + OAuthLoginForm loginForm = new OAuthLoginForm($"Authorize {settings.CloudServiceName}", settings.BrowserSize, settings.FormattedAuthUrl, settings.RedirectUrl); + loginForm.ShowDialog(); + if (!loginForm.IsOk) return false; + if (loginForm.CallbackParameters.TryGetValue(Code, out var code) && !string.IsNullOrEmpty(code)) { + settings.Code = code; + GenerateRefreshToken(settings); + return true; + } + return UpdateFromCallback(settings, loginForm.CallbackParameters); + } + + /// + /// Authorize via a local server by using the LocalServerCodeReceiver + /// If this works, return the code + /// + /// OAuth2Settings with the Auth / Token url etc + /// true if completed + private static bool AuthorizeViaLocalServer(OAuth2Settings settings) { + var codeReceiver = new LocalServerCodeReceiver(); + IDictionary result = codeReceiver.ReceiveCode(settings); + + if (result.TryGetValue(Code, out var code) && !string.IsNullOrEmpty(code)) { + settings.Code = code; + GenerateRefreshToken(settings); + return true; + } + + if (result.TryGetValue("error", out var error)) { + if (result.TryGetValue("error_description", out var errorDescription)) { + throw new Exception(errorDescription); + } + if ("access_denied" == error) { + throw new UnauthorizedAccessException("Access denied"); + } + throw new Exception(error); + } + return false; + } + + /// + /// Simple helper to add the Authorization Bearer header + /// + /// WebRequest + /// OAuth2Settings + public static void AddOAuth2Credentials(HttpWebRequest webRequest, OAuth2Settings settings) { + if (!string.IsNullOrEmpty(settings.AccessToken)) { + webRequest.Headers.Add("Authorization", "Bearer " + settings.AccessToken); + } + } + + /// + /// Check and authenticate or refresh tokens + /// + /// OAuth2Settings + public static void CheckAndAuthenticateOrRefresh(OAuth2Settings settings) { + // Get Refresh / Access token + if (string.IsNullOrEmpty(settings.RefreshToken)) { + if (!Authorize(settings)) { + throw new Exception("Authentication cancelled"); + } + } + if (settings.IsAccessTokenExpired) { + GenerateAccessToken(settings); + // Get Refresh / Access token + if (string.IsNullOrEmpty(settings.RefreshToken)) { + if (!Authorize(settings)) { + throw new Exception("Authentication cancelled"); + } + GenerateAccessToken(settings); + } + } + if (settings.IsAccessTokenExpired) { + throw new Exception("Authentication failed"); + } + } + + /// + /// CreateWebRequest ready for OAuth 2 access + /// + /// HTTPMethod + /// + /// OAuth2Settings + /// HttpWebRequest + public static HttpWebRequest CreateOAuth2WebRequest(HTTPMethod method, string url, OAuth2Settings settings) { + CheckAndAuthenticateOrRefresh(settings); + + HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, method); + AddOAuth2Credentials(webRequest, settings); + return webRequest; + } + } +} diff --git a/GreenshotPlugin/Core/OAuth/OAuth2Settings.cs b/GreenshotPlugin/Core/OAuth/OAuth2Settings.cs new file mode 100644 index 000000000..57b566aaa --- /dev/null +++ b/GreenshotPlugin/Core/OAuth/OAuth2Settings.cs @@ -0,0 +1,181 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace GreenshotPlugin.Core.OAuth +{ + /// + /// Settings for the OAuth 2 protocol + /// + public class OAuth2Settings { + public OAuth2Settings() { + AdditionalAttributes = new Dictionary(); + // Create a default state + var state = Guid.NewGuid().ToString(); + // Only store a small part of the GUID + State = state.Substring(0, state.IndexOf('-')-1); + AuthorizeMode = OAuth2AuthorizeMode.Unknown; + } + + public OAuth2AuthorizeMode AuthorizeMode { + get; + set; + } + + /// + /// Specify the name of the cloud service, so it can be used in window titles, logs etc + /// + public string CloudServiceName { + get; + set; + } + + /// + /// Specify the size of the embedded Browser, if using this + /// + public Size BrowserSize { + get; + set; + } + + /// + /// The OAuth 2 client id + /// + public string ClientId { + get; + set; + } + + /// + /// The OAuth 2 client secret + /// + public string ClientSecret { + get; + set; + } + + /// + /// The OAuth 2 state, this is something that is passed to the server, is not processed but returned back to the client. + /// e.g. a correlation ID + /// Default this is filled with a new Guid + /// + public string State { + get; + set; + } + + /// + /// The authorization URL where the values of this class can be "injected" + /// + public string AuthUrlPattern { + get; + set; + } + + /// + /// Get formatted Auth url (this will call a FormatWith(this) on the AuthUrlPattern + /// + public string FormattedAuthUrl => AuthUrlPattern.FormatWith(this); + + /// + /// The URL to get a Token + /// + public string TokenUrl { + get; + set; + } + + /// + /// This is the redirect URL, in some implementations this is automatically set (LocalServerCodeReceiver) + /// In some implementations this could be e.g. urn:ietf:wg:oauth:2.0:oob or urn:ietf:wg:oauth:2.0:oob:auto + /// + public string RedirectUrl { + get; + set; + } + + /// + /// Bearer token for accessing OAuth 2 services + /// + public string AccessToken { + get; + set; + } + + /// + /// Expire time for the AccessToken, this this time (-60 seconds) is passed a new AccessToken needs to be generated with the RefreshToken + /// + public DateTimeOffset AccessTokenExpires { + get; + set; + } + + /// + /// Return true if the access token is expired. + /// Important "side-effect": if true is returned the AccessToken will be set to null! + /// + public bool IsAccessTokenExpired { + get { + if (AccessTokenExpires == default) + { + return false; + } + bool expired = true; + if (!string.IsNullOrEmpty(AccessToken)) { + expired = DateTimeOffset.Now.AddSeconds(60) > AccessTokenExpires; + } + // Make sure the token is not usable + if (expired) { + AccessToken = null; + } + return expired; + } + } + + /// + /// Token used to get a new Access Token + /// + public string RefreshToken { + get; + set; + } + + /// + /// Put anything in here which is needed for the OAuth 2 implementation of this specific service but isn't generic, e.g. for Google there is a "scope" + /// + public IDictionary AdditionalAttributes { + get; + set; + } + + /// + /// This contains the code returned from the authorization, but only shortly after it was received. + /// It will be cleared as soon as it was used. + /// + public string Code { + get; + set; + } + } +} \ No newline at end of file diff --git a/GreenshotPlugin/Core/OAuth/OAuthSession.cs b/GreenshotPlugin/Core/OAuth/OAuthSession.cs new file mode 100644 index 000000000..9a40c0b8d --- /dev/null +++ b/GreenshotPlugin/Core/OAuth/OAuthSession.cs @@ -0,0 +1,629 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Globalization; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using GreenshotPlugin.Controls; +using log4net; + +namespace GreenshotPlugin.Core.OAuth +{ + /// + /// An OAuth 1 session object + /// + public class OAuthSession { + private static readonly ILog Log = LogManager.GetLogger(typeof(OAuthSession)); + protected const string OAUTH_VERSION = "1.0"; + protected const string OAUTH_PARAMETER_PREFIX = "oauth_"; + + // + // List of know and used oauth parameters' names + // + protected const string OAUTH_CONSUMER_KEY_KEY = "oauth_consumer_key"; + protected const string OAUTH_CALLBACK_KEY = "oauth_callback"; + protected const string OAUTH_VERSION_KEY = "oauth_version"; + protected const string OAUTH_SIGNATURE_METHOD_KEY = "oauth_signature_method"; + protected const string OAUTH_TIMESTAMP_KEY = "oauth_timestamp"; + protected const string OAUTH_NONCE_KEY = "oauth_nonce"; + protected const string OAUTH_TOKEN_KEY = "oauth_token"; + protected const string OAUTH_VERIFIER_KEY = "oauth_verifier"; + protected const string OAUTH_TOKEN_SECRET_KEY = "oauth_token_secret"; + protected const string OAUTH_SIGNATURE_KEY = "oauth_signature"; + + protected const string HMACSHA1SignatureType = "HMAC-SHA1"; + protected const string PlainTextSignatureType = "PLAINTEXT"; + + protected static Random random = new Random(); + + protected const string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"; + + private string _userAgent = "Greenshot"; + private IDictionary _requestTokenResponseParameters; + + public IDictionary RequestTokenParameters { get; } = new Dictionary(); + + /// + /// Parameters of the last called getAccessToken + /// + public IDictionary AccessTokenResponseParameters { get; private set; } + + /// + /// Parameters of the last called getRequestToken + /// + public IDictionary RequestTokenResponseParameters => _requestTokenResponseParameters; + + private readonly string _consumerKey; + private readonly string _consumerSecret; + + // default _browser size + + public HTTPMethod RequestTokenMethod { + get; + set; + } + public HTTPMethod AccessTokenMethod { + get; + set; + } + public string RequestTokenUrl { + get; + set; + } + public string AuthorizeUrl { + get; + set; + } + public string AccessTokenUrl { + get; + set; + } + public string Token { + get; + set; + } + public string TokenSecret { + get; + set; + } + public string Verifier { + get; + set; + } + public OAuthSignatureTypes SignatureType { + get; + set; + } + + public bool UseMultipartFormData { get; set; } + public string UserAgent { + get { + return _userAgent; + } + set { + _userAgent = value; + } + } + public string CallbackUrl { get; set; } = "http://getgreenshot.org"; + + public bool CheckVerifier { get; set; } = true; + + public Size BrowserSize { get; set; } = new Size(864, 587); + + public string LoginTitle { get; set; } = "Authorize Greenshot access"; + + public bool UseHttpHeadersForAuthorization { get; set; } = true; + + public bool AutoLogin { + get; + set; + } + + /// + /// Create an OAuthSession with the consumerKey / consumerSecret + /// + /// "Public" key for the encoding. When using RSASHA1 this is the path to the private key file + /// "Private" key for the encoding. when usin RSASHA1 this is the password for the private key file + public OAuthSession(string consumerKey, string consumerSecret) { + _consumerKey = consumerKey; + _consumerSecret = consumerSecret; + UseMultipartFormData = true; + RequestTokenMethod = HTTPMethod.GET; + AccessTokenMethod = HTTPMethod.GET; + SignatureType = OAuthSignatureTypes.HMACSHA1; + AutoLogin = true; + } + + /// + /// Helper function to compute a hash value + /// + /// The hashing algorithm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function + /// The data to hash + /// a Base64 string of the hash value + private static string ComputeHash(HashAlgorithm hashAlgorithm, string data) { + if (hashAlgorithm == null) { + throw new ArgumentNullException(nameof(hashAlgorithm)); + } + + if (string.IsNullOrEmpty(data)) { + throw new ArgumentNullException(nameof(data)); + } + + byte[] dataBuffer = Encoding.UTF8.GetBytes(data); + byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer); + + return Convert.ToBase64String(hashBytes); + } + + /// + /// Generate the normalized paramter string + /// + /// the list of query parameters + /// a string with the normalized query parameters + private static string GenerateNormalizedParametersString(IDictionary queryParameters) { + if (queryParameters == null || queryParameters.Count == 0) { + return string.Empty; + } + + queryParameters = new SortedDictionary(queryParameters); + + StringBuilder sb = new StringBuilder(); + foreach (string key in queryParameters.Keys) { + if (queryParameters[key] is string) { + sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode3986($"{queryParameters[key]}")); + } + } + sb.Remove(sb.Length - 1, 1); + + return sb.ToString(); + } + + /// + /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case. + /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth + /// The resulting string is for UTF-8 encoding! + /// + /// The value to Url encode + /// Returns a Url encoded string (unicode) with UTF-8 encoded % values + public static string UrlEncode3986(string value) { + StringBuilder result = new StringBuilder(); + + foreach (char symbol in value) { + if (UnreservedChars.IndexOf(symbol) != -1) { + result.Append(symbol); + } else { + byte[] utf8Bytes = Encoding.UTF8.GetBytes(symbol.ToString()); + foreach(byte utf8Byte in utf8Bytes) { + result.AppendFormat("%{0:X2}", utf8Byte); + } + } + } + + return result.ToString(); + } + + /// + /// Generate the timestamp for the signature + /// + /// + public static string GenerateTimeStamp() { + // Default implementation of UNIX time of the current UTC time + TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return Convert.ToInt64(ts.TotalSeconds).ToString(); + } + + /// + /// Generate a nonce + /// + /// + public static string GenerateNonce() { + // Just a simple implementation of a random number between 123400 and 9999999 + return random.Next(123400, 9999999).ToString(); + } + + /// + /// Get the request token using the consumer key and secret. Also initializes tokensecret + /// + /// response, this doesn't need to be used!! + private string GetRequestToken() { + IDictionary parameters = new Dictionary(); + foreach(var value in RequestTokenParameters) { + parameters.Add(value); + } + Sign(RequestTokenMethod, RequestTokenUrl, parameters); + string response = MakeRequest(RequestTokenMethod, RequestTokenUrl, null, parameters, null); + if (!string.IsNullOrEmpty(response)) { + response = NetworkHelper.UrlDecode(response); + Log.DebugFormat("Request token response: {0}", response); + _requestTokenResponseParameters = NetworkHelper.ParseQueryString(response); + if (_requestTokenResponseParameters.TryGetValue(OAUTH_TOKEN_KEY, out var value)) { + Token = value; + TokenSecret = _requestTokenResponseParameters[OAUTH_TOKEN_SECRET_KEY]; + } + } + return response; + } + + /// + /// Authorize the token by showing the dialog + /// + /// Pass the response from the server's request token, so if there is something wrong we can show it. + /// The request token. + private string GetAuthorizeToken(string requestTokenResponse) { + if (string.IsNullOrEmpty(Token)) { + Exception e = new Exception("The request token is not set, service responded with: " + requestTokenResponse); + throw e; + } + Log.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink); + OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(LoginTitle, BrowserSize, AuthorizationLink, CallbackUrl); + oAuthLoginForm.ShowDialog(); + if (oAuthLoginForm.IsOk) { + if (oAuthLoginForm.CallbackParameters != null) { + if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_TOKEN_KEY, out var tokenValue)) { + Token = tokenValue; + } + + if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_VERIFIER_KEY, out var verifierValue)) { + Verifier = verifierValue; + } + } + } + if (CheckVerifier) { + if (!string.IsNullOrEmpty(Verifier)) { + return Token; + } + return null; + } + return Token; + } + + /// + /// Get the access token + /// + /// The access token. + private string GetAccessToken() { + if (string.IsNullOrEmpty(Token) || (CheckVerifier && string.IsNullOrEmpty(Verifier))) { + Exception e = new Exception("The request token and verifier were not set"); + throw e; + } + + IDictionary parameters = new Dictionary(); + Sign(AccessTokenMethod, AccessTokenUrl, parameters); + string response = MakeRequest(AccessTokenMethod, AccessTokenUrl, null, parameters, null); + if (!string.IsNullOrEmpty(response)) { + response = NetworkHelper.UrlDecode(response); + Log.DebugFormat("Access token response: {0}", response); + AccessTokenResponseParameters = NetworkHelper.ParseQueryString(response); + if (AccessTokenResponseParameters.TryGetValue(OAUTH_TOKEN_KEY, out var tokenValue) && tokenValue != null) { + Token = tokenValue; + } + + if (AccessTokenResponseParameters.TryGetValue(OAUTH_TOKEN_SECRET_KEY, out var secretValue) && secretValue != null) { + TokenSecret = secretValue; + } + } + + return Token; + } + + /// + /// This method goes through the whole authorize process, including a Authorization window. + /// + /// true if the process is completed + public bool Authorize() { + Token = null; + TokenSecret = null; + Verifier = null; + Log.Debug("Creating Token"); + string requestTokenResponse; + try { + requestTokenResponse = GetRequestToken(); + } catch (Exception ex) { + Log.Error(ex); + throw new NotSupportedException("Service is not available: " + ex.Message); + } + if (string.IsNullOrEmpty(GetAuthorizeToken(requestTokenResponse))) { + Log.Debug("User didn't authenticate!"); + return false; + } + try { + Thread.Sleep(1000); + return GetAccessToken() != null; + } catch (Exception ex) { + Log.Error(ex); + throw; + } + } + + /// + /// Get the link to the authorization page for this application. + /// + /// The url with a valid request token, or a null string. + private string AuthorizationLink => AuthorizeUrl + "?" + OAUTH_TOKEN_KEY + "=" + Token + "&" + OAUTH_CALLBACK_KEY + "=" + UrlEncode3986(CallbackUrl); + + /// + /// Submit a web request using oAuth. + /// + /// GET or POST + /// The full url, including the querystring for the signing/request + /// Parameters for the request, which need to be signed + /// Parameters for the request, which do not need to be signed + /// Data to post (MemoryStream) + /// The web server response. + public string MakeOAuthRequest(HTTPMethod method, string requestUrl, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { + return MakeOAuthRequest(method, requestUrl, requestUrl, null, parametersToSign, additionalParameters, postData); + } + + /// + /// Submit a web request using oAuth. + /// + /// GET or POST + /// The full url, including the querystring for the signing/request + /// Header values + /// Parameters for the request, which need to be signed + /// Parameters for the request, which do not need to be signed + /// Data to post (MemoryStream) + /// The web server response. + public string MakeOAuthRequest(HTTPMethod method, string requestUrl, IDictionary headers, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { + return MakeOAuthRequest(method, requestUrl, requestUrl, headers, parametersToSign, additionalParameters, postData); + } + + /// + /// Submit a web request using oAuth. + /// + /// GET or POST + /// The full url, including the querystring for the signing + /// The full url, including the querystring for the request + /// Parameters for the request, which need to be signed + /// Parameters for the request, which do not need to be signed + /// Data to post (MemoryStream) + /// The web server response. + public string MakeOAuthRequest(HTTPMethod method, string signUrl, string requestUrl, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { + return MakeOAuthRequest(method, signUrl, requestUrl, null, parametersToSign, additionalParameters, postData); + } + + /// + /// Submit a web request using oAuth. + /// + /// GET or POST + /// The full url, including the querystring for the signing + /// The full url, including the querystring for the request + /// Headers for the request + /// Parameters for the request, which need to be signed + /// Parameters for the request, which do not need to be signed + /// Data to post (MemoryStream) + /// The web server response. + public string MakeOAuthRequest(HTTPMethod method, string signUrl, string requestUrl, IDictionary headers, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { + if (parametersToSign == null) { + parametersToSign = new Dictionary(); + } + int retries = 2; + Exception lastException = null; + while (retries-- > 0) { + // If we are not trying to get a Authorization or Accestoken, and we don't have a token, create one + if (string.IsNullOrEmpty(Token)) { + if (!AutoLogin || !Authorize()) { + throw new Exception("Not authorized"); + } + } + try { + Sign(method, signUrl, parametersToSign); + + // Join all parameters + IDictionary newParameters = new Dictionary(); + foreach (var parameter in parametersToSign) { + newParameters.Add(parameter); + } + if (additionalParameters != null) { + foreach (var parameter in additionalParameters) { + newParameters.Add(parameter); + } + } + return MakeRequest(method, requestUrl, headers, newParameters, postData); + } catch (UnauthorizedAccessException uaEx) { + lastException = uaEx; + Token = null; + TokenSecret = null; + // Remove oauth keys, so they aren't added double + List keysToDelete = new List(); + foreach (string parameterKey in parametersToSign.Keys) + { + if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) + { + keysToDelete.Add(parameterKey); + } + } + foreach (string keyToDelete in keysToDelete) + { + parametersToSign.Remove(keyToDelete); + } + } + } + if (lastException != null) { + throw lastException; + } + throw new Exception("Not authorized"); + } + + /// + /// OAuth sign the parameters, meaning all oauth parameters are added to the supplied dictionary. + /// And additionally a signature is added. + /// + /// Method (POST,PUT,GET) + /// Url to call + /// IDictionary of string and string + private void Sign(HTTPMethod method, string requestUrl, IDictionary parameters) { + if (parameters == null) { + throw new ArgumentNullException(nameof(parameters)); + } + // Build the signature base + StringBuilder signatureBase = new StringBuilder(); + + // Add Method to signature base + signatureBase.Append(method).Append("&"); + + // Add normalized URL + Uri url = new Uri(requestUrl); + string normalizedUrl = string.Format(CultureInfo.InvariantCulture, "{0}://{1}", url.Scheme, url.Host); + if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) { + normalizedUrl += ":" + url.Port; + } + normalizedUrl += url.AbsolutePath; + signatureBase.Append(UrlEncode3986(normalizedUrl)).Append("&"); + + // Add normalized parameters + parameters.Add(OAUTH_VERSION_KEY, OAUTH_VERSION); + parameters.Add(OAUTH_NONCE_KEY, GenerateNonce()); + parameters.Add(OAUTH_TIMESTAMP_KEY, GenerateTimeStamp()); + switch(SignatureType) { + case OAuthSignatureTypes.PLAINTEXT: + parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, PlainTextSignatureType); + break; + default: + parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, HMACSHA1SignatureType); + break; + } + parameters.Add(OAUTH_CONSUMER_KEY_KEY, _consumerKey); + if (CallbackUrl != null && RequestTokenUrl != null && requestUrl.StartsWith(RequestTokenUrl)) { + parameters.Add(OAUTH_CALLBACK_KEY, CallbackUrl); + } + if (!string.IsNullOrEmpty(Verifier)) { + parameters.Add(OAUTH_VERIFIER_KEY, Verifier); + } + if (!string.IsNullOrEmpty(Token)) { + parameters.Add(OAUTH_TOKEN_KEY, Token); + } + signatureBase.Append(UrlEncode3986(GenerateNormalizedParametersString(parameters))); + Log.DebugFormat("Signature base: {0}", signatureBase); + string key = string.Format(CultureInfo.InvariantCulture, "{0}&{1}", UrlEncode3986(_consumerSecret), string.IsNullOrEmpty(TokenSecret) ? string.Empty : UrlEncode3986(TokenSecret)); + switch (SignatureType) { + case OAuthSignatureTypes.PLAINTEXT: + parameters.Add(OAUTH_SIGNATURE_KEY, key); + break; + default: + // Generate Signature and add it to the parameters + HMACSHA1 hmacsha1 = new HMACSHA1 {Key = Encoding.UTF8.GetBytes(key)}; + string signature = ComputeHash(hmacsha1, signatureBase.ToString()); + parameters.Add(OAUTH_SIGNATURE_KEY, signature); + break; + } + } + + /// + /// Make the actual OAuth request, all oauth parameters are passed as header (default) and the others are placed in the url or post data. + /// Any additional parameters added after the Sign call are not in the signature, this could be by design! + /// + /// + /// + /// + /// + /// IBinaryParameter + /// Response from server + private string MakeRequest(HTTPMethod method, string requestUrl, IDictionary headers, IDictionary parameters, IBinaryContainer postData) { + if (parameters == null) { + throw new ArgumentNullException(nameof(parameters)); + } + IDictionary requestParameters; + // Add oAuth values as HTTP headers, if this is allowed + StringBuilder authHeader = null; + if (UseHttpHeadersForAuthorization) { + authHeader = new StringBuilder(); + requestParameters = new Dictionary(); + foreach (string parameterKey in parameters.Keys) { + if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) { + authHeader.AppendFormat(CultureInfo.InvariantCulture, "{0}=\"{1}\", ", parameterKey, UrlEncode3986($"{parameters[parameterKey]}")); + } else if (!requestParameters.ContainsKey(parameterKey)) { + requestParameters.Add(parameterKey, parameters[parameterKey]); + } + } + // Remove trailing comma and space and add it to the headers + if (authHeader.Length > 0) { + authHeader.Remove(authHeader.Length - 2, 2); + } + } else { + requestParameters = parameters; + } + + if (HTTPMethod.GET == method || postData != null) { + if (requestParameters.Count > 0) { + // Add the parameters to the request + requestUrl += "?" + NetworkHelper.GenerateQueryParameters(requestParameters); + } + } + // Create webrequest + HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(requestUrl, method); + webRequest.ServicePoint.Expect100Continue = false; + webRequest.UserAgent = _userAgent; + + if (UseHttpHeadersForAuthorization && authHeader != null) { + Log.DebugFormat("Authorization: OAuth {0}", authHeader); + webRequest.Headers.Add("Authorization: OAuth " + authHeader); + } + + if (headers != null) { + foreach(string key in headers.Keys) { + webRequest.Headers.Add(key, headers[key]); + } + } + + if ((HTTPMethod.POST == method || HTTPMethod.PUT == method) && postData == null && requestParameters.Count > 0) { + if (UseMultipartFormData) { + NetworkHelper.WriteMultipartFormData(webRequest, requestParameters); + } else { + StringBuilder form = new StringBuilder(); + foreach (string parameterKey in requestParameters.Keys) + { + var binaryParameter = parameters[parameterKey] as IBinaryContainer; + form.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", UrlEncode3986(parameterKey), binaryParameter != null ? UrlEncode3986(binaryParameter.ToBase64String(Base64FormattingOptions.None)) : UrlEncode3986($"{parameters[parameterKey]}")); + } + // Remove trailing & + if (form.Length > 0) { + form.Remove(form.Length - 1, 1); + } + webRequest.ContentType = "application/x-www-form-urlencoded"; + byte[] data = Encoding.UTF8.GetBytes(form.ToString()); + using var requestStream = webRequest.GetRequestStream(); + requestStream.Write(data, 0, data.Length); + } + } else if (postData != null) { + postData.Upload(webRequest); + } else { + webRequest.ContentLength = 0; + } + + string responseData; + try { + responseData = NetworkHelper.GetResponseAsString(webRequest); + Log.DebugFormat("Response: {0}", responseData); + } catch (Exception ex) { + Log.Error("Couldn't retrieve response: ", ex); + throw; + } + + return responseData; + } + } +} \ No newline at end of file diff --git a/GreenshotPlugin/Interfaces/VerticalAlignment.cs b/GreenshotPlugin/Core/OAuth/OAuthSignatureTypes.cs similarity index 75% rename from GreenshotPlugin/Interfaces/VerticalAlignment.cs rename to GreenshotPlugin/Core/OAuth/OAuthSignatureTypes.cs index f5cb71f0f..af2bfc710 100644 --- a/GreenshotPlugin/Interfaces/VerticalAlignment.cs +++ b/GreenshotPlugin/Core/OAuth/OAuthSignatureTypes.cs @@ -1,6 +1,6 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot @@ -19,16 +19,13 @@ * along with this program. If not, see . */ -namespace GreenshotPlugin.Interfaces +namespace GreenshotPlugin.Core.OAuth { /// - /// Alignment Enums for positioning + /// Provides a predefined set of algorithms that are supported officially by the OAuth 1.x protocol /// - //public enum HorizontalAlignment {LEFT, CENTER, RIGHT}; - public enum VerticalAlignment - { - TOP, - CENTER, - BOTTOM - }; + public enum OAuthSignatureTypes { + HMACSHA1, + PLAINTEXT, + } } \ No newline at end of file diff --git a/GreenshotPlugin/Core/OAuthHelper.cs b/GreenshotPlugin/Core/OAuthHelper.cs deleted file mode 100644 index 5370697b6..000000000 --- a/GreenshotPlugin/Core/OAuthHelper.cs +++ /dev/null @@ -1,1269 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using GreenshotPlugin.Controls; -using log4net; -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Diagnostics; -using System.Drawing; -using System.Globalization; -using System.Net; -using System.Net.Sockets; -using System.Security.Cryptography; -using System.Text; -using System.Threading; -using System.Windows.Forms; -using GreenshotPlugin.Hooking; - -namespace GreenshotPlugin.Core { - /// - /// Provides a predefined set of algorithms that are supported officially by the OAuth 1.x protocol - /// - public enum OAuthSignatureTypes { - HMACSHA1, - PLAINTEXT, - } - - /// - /// Specify the authorize mode that is used to get the token from the cloud service. - /// - public enum OAuth2AuthorizeMode { - Unknown, // Will give an exception, caller needs to specify another value - LocalServer, // Will specify a redirect URL to http://localhost:port/authorize, while having a HttpListener - MonitorTitle, // Not implemented yet: Will monitor for title changes - Pin, // Not implemented yet: Will ask the user to enter the shown PIN - EmbeddedBrowser, // Will open into an embedded _browser (OAuthLoginForm), and catch the redirect - OutOfBoundAuto - } - - /// - /// Settings for the OAuth 2 protocol - /// - public class OAuth2Settings { - public OAuth2Settings() { - AdditionalAttributes = new Dictionary(); - // Create a default state - State = Guid.NewGuid().ToString(); - AuthorizeMode = OAuth2AuthorizeMode.Unknown; - } - - public OAuth2AuthorizeMode AuthorizeMode { - get; - set; - } - - /// - /// Specify the name of the cloud service, so it can be used in window titles, logs etc - /// - public string CloudServiceName { - get; - set; - } - - /// - /// Specify the size of the embedded Browser, if using this - /// - public Size BrowserSize { - get; - set; - } - - /// - /// The OAuth 2 client id - /// - public string ClientId { - get; - set; - } - - /// - /// The OAuth 2 client secret - /// - public string ClientSecret { - get; - set; - } - - /// - /// The OAuth 2 state, this is something that is passed to the server, is not processed but returned back to the client. - /// e.g. a correlation ID - /// Default this is filled with a new Guid - /// - public string State { - get; - set; - } - - /// - /// The autorization URL where the values of this class can be "injected" - /// - public string AuthUrlPattern { - get; - set; - } - - /// - /// Get formatted Auth url (this will call a FormatWith(this) on the AuthUrlPattern - /// - public string FormattedAuthUrl => AuthUrlPattern.FormatWith(this); - - /// - /// The URL to get a Token - /// - public string TokenUrl { - get; - set; - } - - /// - /// This is the redirect URL, in some implementations this is automatically set (LocalServerCodeReceiver) - /// In some implementations this could be e.g. urn:ietf:wg:oauth:2.0:oob or urn:ietf:wg:oauth:2.0:oob:auto - /// - public string RedirectUrl { - get; - set; - } - - /// - /// Bearer token for accessing OAuth 2 services - /// - public string AccessToken { - get; - set; - } - - /// - /// Expire time for the AccessToken, this this time (-60 seconds) is passed a new AccessToken needs to be generated with the RefreshToken - /// - public DateTimeOffset AccessTokenExpires { - get; - set; - } - - /// - /// Return true if the access token is expired. - /// Important "side-effect": if true is returned the AccessToken will be set to null! - /// - public bool IsAccessTokenExpired { - get { - bool expired = true; - if (!string.IsNullOrEmpty(AccessToken)) { - expired = DateTimeOffset.Now.AddSeconds(60) > AccessTokenExpires; - } - // Make sure the token is not usable - if (expired) { - AccessToken = null; - } - return expired; - } - } - - /// - /// Token used to get a new Access Token - /// - public string RefreshToken { - get; - set; - } - - /// - /// Put anything in here which is needed for the OAuth 2 implementation of this specific service but isn't generic, e.g. for Google there is a "scope" - /// - public IDictionary AdditionalAttributes { - get; - set; - } - - /// - /// This contains the code returned from the authorization, but only shortly after it was received. - /// It will be cleared as soon as it was used. - /// - public string Code { - get; - set; - } - } - - /// - /// An OAuth 1 session object - /// - public class OAuthSession { - private static readonly ILog Log = LogManager.GetLogger(typeof(OAuthSession)); - protected const string OAUTH_VERSION = "1.0"; - protected const string OAUTH_PARAMETER_PREFIX = "oauth_"; - - // - // List of know and used oauth parameters' names - // - protected const string OAUTH_CONSUMER_KEY_KEY = "oauth_consumer_key"; - protected const string OAUTH_CALLBACK_KEY = "oauth_callback"; - protected const string OAUTH_VERSION_KEY = "oauth_version"; - protected const string OAUTH_SIGNATURE_METHOD_KEY = "oauth_signature_method"; - protected const string OAUTH_TIMESTAMP_KEY = "oauth_timestamp"; - protected const string OAUTH_NONCE_KEY = "oauth_nonce"; - protected const string OAUTH_TOKEN_KEY = "oauth_token"; - protected const string OAUTH_VERIFIER_KEY = "oauth_verifier"; - protected const string OAUTH_TOKEN_SECRET_KEY = "oauth_token_secret"; - protected const string OAUTH_SIGNATURE_KEY = "oauth_signature"; - - protected const string HMACSHA1SignatureType = "HMAC-SHA1"; - protected const string PlainTextSignatureType = "PLAINTEXT"; - - protected static Random random = new Random(); - - protected const string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"; - - private string _userAgent = "Greenshot"; - private IDictionary _requestTokenResponseParameters; - - public IDictionary RequestTokenParameters { get; } = new Dictionary(); - - /// - /// Parameters of the last called getAccessToken - /// - public IDictionary AccessTokenResponseParameters { get; private set; } - - /// - /// Parameters of the last called getRequestToken - /// - public IDictionary RequestTokenResponseParameters => _requestTokenResponseParameters; - - private readonly string _consumerKey; - private readonly string _consumerSecret; - - // default _browser size - - public HTTPMethod RequestTokenMethod { - get; - set; - } - public HTTPMethod AccessTokenMethod { - get; - set; - } - public string RequestTokenUrl { - get; - set; - } - public string AuthorizeUrl { - get; - set; - } - public string AccessTokenUrl { - get; - set; - } - public string Token { - get; - set; - } - public string TokenSecret { - get; - set; - } - public string Verifier { - get; - set; - } - public OAuthSignatureTypes SignatureType { - get; - set; - } - - public bool UseMultipartFormData { get; set; } - public string UserAgent { - get { - return _userAgent; - } - set { - _userAgent = value; - } - } - public string CallbackUrl { get; set; } = "http://getgreenshot.org"; - - public bool CheckVerifier { get; set; } = true; - - public Size BrowserSize { get; set; } = new Size(864, 587); - - public string LoginTitle { get; set; } = "Authorize Greenshot access"; - - public bool UseHttpHeadersForAuthorization { get; set; } = true; - - public bool AutoLogin { - get; - set; - } - - /// - /// Create an OAuthSession with the consumerKey / consumerSecret - /// - /// "Public" key for the encoding. When using RSASHA1 this is the path to the private key file - /// "Private" key for the encoding. when usin RSASHA1 this is the password for the private key file - public OAuthSession(string consumerKey, string consumerSecret) { - _consumerKey = consumerKey; - _consumerSecret = consumerSecret; - UseMultipartFormData = true; - RequestTokenMethod = HTTPMethod.GET; - AccessTokenMethod = HTTPMethod.GET; - SignatureType = OAuthSignatureTypes.HMACSHA1; - AutoLogin = true; - } - - /// - /// Helper function to compute a hash value - /// - /// The hashing algorithm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function - /// The data to hash - /// a Base64 string of the hash value - private static string ComputeHash(HashAlgorithm hashAlgorithm, string data) { - if (hashAlgorithm == null) { - throw new ArgumentNullException(nameof(hashAlgorithm)); - } - - if (string.IsNullOrEmpty(data)) { - throw new ArgumentNullException(nameof(data)); - } - - byte[] dataBuffer = Encoding.UTF8.GetBytes(data); - byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer); - - return Convert.ToBase64String(hashBytes); - } - - /// - /// Generate the normalized paramter string - /// - /// the list of query parameters - /// a string with the normalized query parameters - private static string GenerateNormalizedParametersString(IDictionary queryParameters) { - if (queryParameters == null || queryParameters.Count == 0) { - return string.Empty; - } - - queryParameters = new SortedDictionary(queryParameters); - - StringBuilder sb = new StringBuilder(); - foreach (string key in queryParameters.Keys) { - if (queryParameters[key] is string) { - sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode3986($"{queryParameters[key]}")); - } - } - sb.Remove(sb.Length - 1, 1); - - return sb.ToString(); - } - - /// - /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case. - /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth - /// The resulting string is for UTF-8 encoding! - /// - /// The value to Url encode - /// Returns a Url encoded string (unicode) with UTF-8 encoded % values - public static string UrlEncode3986(string value) { - StringBuilder result = new StringBuilder(); - - foreach (char symbol in value) { - if (UnreservedChars.IndexOf(symbol) != -1) { - result.Append(symbol); - } else { - byte[] utf8Bytes = Encoding.UTF8.GetBytes(symbol.ToString()); - foreach(byte utf8Byte in utf8Bytes) { - result.AppendFormat("%{0:X2}", utf8Byte); - } - } - } - - return result.ToString(); - } - - /// - /// Generate the timestamp for the signature - /// - /// - public static string GenerateTimeStamp() { - // Default implementation of UNIX time of the current UTC time - TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); - return Convert.ToInt64(ts.TotalSeconds).ToString(); - } - - /// - /// Generate a nonce - /// - /// - public static string GenerateNonce() { - // Just a simple implementation of a random number between 123400 and 9999999 - return random.Next(123400, 9999999).ToString(); - } - - /// - /// Get the request token using the consumer key and secret. Also initializes tokensecret - /// - /// response, this doesn't need to be used!! - private string GetRequestToken() { - IDictionary parameters = new Dictionary(); - foreach(var value in RequestTokenParameters) { - parameters.Add(value); - } - Sign(RequestTokenMethod, RequestTokenUrl, parameters); - string response = MakeRequest(RequestTokenMethod, RequestTokenUrl, null, parameters, null); - if (!string.IsNullOrEmpty(response)) { - response = NetworkHelper.UrlDecode(response); - Log.DebugFormat("Request token response: {0}", response); - _requestTokenResponseParameters = NetworkHelper.ParseQueryString(response); - if (_requestTokenResponseParameters.TryGetValue(OAUTH_TOKEN_KEY, out var value)) { - Token = value; - TokenSecret = _requestTokenResponseParameters[OAUTH_TOKEN_SECRET_KEY]; - } - } - return response; - } - - /// - /// Authorize the token by showing the dialog - /// - /// Pass the response from the server's request token, so if there is something wrong we can show it. - /// The request token. - private string GetAuthorizeToken(string requestTokenResponse) { - if (string.IsNullOrEmpty(Token)) { - Exception e = new Exception("The request token is not set, service responded with: " + requestTokenResponse); - throw e; - } - Log.DebugFormat("Opening AuthorizationLink: {0}", AuthorizationLink); - OAuthLoginForm oAuthLoginForm = new OAuthLoginForm(LoginTitle, BrowserSize, AuthorizationLink, CallbackUrl); - oAuthLoginForm.ShowDialog(); - if (oAuthLoginForm.IsOk) { - if (oAuthLoginForm.CallbackParameters != null) { - if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_TOKEN_KEY, out var tokenValue)) { - Token = tokenValue; - } - - if (oAuthLoginForm.CallbackParameters.TryGetValue(OAUTH_VERIFIER_KEY, out var verifierValue)) { - Verifier = verifierValue; - } - } - } - if (CheckVerifier) { - if (!string.IsNullOrEmpty(Verifier)) { - return Token; - } - return null; - } - return Token; - } - - /// - /// Get the access token - /// - /// The access token. - private string GetAccessToken() { - if (string.IsNullOrEmpty(Token) || (CheckVerifier && string.IsNullOrEmpty(Verifier))) { - Exception e = new Exception("The request token and verifier were not set"); - throw e; - } - - IDictionary parameters = new Dictionary(); - Sign(AccessTokenMethod, AccessTokenUrl, parameters); - string response = MakeRequest(AccessTokenMethod, AccessTokenUrl, null, parameters, null); - if (!string.IsNullOrEmpty(response)) { - response = NetworkHelper.UrlDecode(response); - Log.DebugFormat("Access token response: {0}", response); - AccessTokenResponseParameters = NetworkHelper.ParseQueryString(response); - if (AccessTokenResponseParameters.TryGetValue(OAUTH_TOKEN_KEY, out var tokenValue) && tokenValue != null) { - Token = tokenValue; - } - - if (AccessTokenResponseParameters.TryGetValue(OAUTH_TOKEN_SECRET_KEY, out var secretValue) && secretValue != null) { - TokenSecret = secretValue; - } - } - - return Token; - } - - /// - /// This method goes through the whole authorize process, including a Authorization window. - /// - /// true if the process is completed - public bool Authorize() { - Token = null; - TokenSecret = null; - Verifier = null; - Log.Debug("Creating Token"); - string requestTokenResponse; - try { - requestTokenResponse = GetRequestToken(); - } catch (Exception ex) { - Log.Error(ex); - throw new NotSupportedException("Service is not available: " + ex.Message); - } - if (string.IsNullOrEmpty(GetAuthorizeToken(requestTokenResponse))) { - Log.Debug("User didn't authenticate!"); - return false; - } - try { - Thread.Sleep(1000); - return GetAccessToken() != null; - } catch (Exception ex) { - Log.Error(ex); - throw; - } - } - - /// - /// Get the link to the authorization page for this application. - /// - /// The url with a valid request token, or a null string. - private string AuthorizationLink => AuthorizeUrl + "?" + OAUTH_TOKEN_KEY + "=" + Token + "&" + OAUTH_CALLBACK_KEY + "=" + UrlEncode3986(CallbackUrl); - - /// - /// Submit a web request using oAuth. - /// - /// GET or POST - /// The full url, including the querystring for the signing/request - /// Parameters for the request, which need to be signed - /// Parameters for the request, which do not need to be signed - /// Data to post (MemoryStream) - /// The web server response. - public string MakeOAuthRequest(HTTPMethod method, string requestUrl, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { - return MakeOAuthRequest(method, requestUrl, requestUrl, null, parametersToSign, additionalParameters, postData); - } - - /// - /// Submit a web request using oAuth. - /// - /// GET or POST - /// The full url, including the querystring for the signing/request - /// Header values - /// Parameters for the request, which need to be signed - /// Parameters for the request, which do not need to be signed - /// Data to post (MemoryStream) - /// The web server response. - public string MakeOAuthRequest(HTTPMethod method, string requestUrl, IDictionary headers, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { - return MakeOAuthRequest(method, requestUrl, requestUrl, headers, parametersToSign, additionalParameters, postData); - } - - /// - /// Submit a web request using oAuth. - /// - /// GET or POST - /// The full url, including the querystring for the signing - /// The full url, including the querystring for the request - /// Parameters for the request, which need to be signed - /// Parameters for the request, which do not need to be signed - /// Data to post (MemoryStream) - /// The web server response. - public string MakeOAuthRequest(HTTPMethod method, string signUrl, string requestUrl, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { - return MakeOAuthRequest(method, signUrl, requestUrl, null, parametersToSign, additionalParameters, postData); - } - - /// - /// Submit a web request using oAuth. - /// - /// GET or POST - /// The full url, including the querystring for the signing - /// The full url, including the querystring for the request - /// Headers for the request - /// Parameters for the request, which need to be signed - /// Parameters for the request, which do not need to be signed - /// Data to post (MemoryStream) - /// The web server response. - public string MakeOAuthRequest(HTTPMethod method, string signUrl, string requestUrl, IDictionary headers, IDictionary parametersToSign, IDictionary additionalParameters, IBinaryContainer postData) { - if (parametersToSign == null) { - parametersToSign = new Dictionary(); - } - int retries = 2; - Exception lastException = null; - while (retries-- > 0) { - // If we are not trying to get a Authorization or Accestoken, and we don't have a token, create one - if (string.IsNullOrEmpty(Token)) { - if (!AutoLogin || !Authorize()) { - throw new Exception("Not authorized"); - } - } - try { - Sign(method, signUrl, parametersToSign); - - // Join all parameters - IDictionary newParameters = new Dictionary(); - foreach (var parameter in parametersToSign) { - newParameters.Add(parameter); - } - if (additionalParameters != null) { - foreach (var parameter in additionalParameters) { - newParameters.Add(parameter); - } - } - return MakeRequest(method, requestUrl, headers, newParameters, postData); - } catch (UnauthorizedAccessException uaEx) { - lastException = uaEx; - Token = null; - TokenSecret = null; - // Remove oauth keys, so they aren't added double - List keysToDelete = new List(); - foreach (string parameterKey in parametersToSign.Keys) - { - if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) - { - keysToDelete.Add(parameterKey); - } - } - foreach (string keyToDelete in keysToDelete) - { - parametersToSign.Remove(keyToDelete); - } - } - } - if (lastException != null) { - throw lastException; - } - throw new Exception("Not authorized"); - } - - /// - /// OAuth sign the parameters, meaning all oauth parameters are added to the supplied dictionary. - /// And additionally a signature is added. - /// - /// Method (POST,PUT,GET) - /// Url to call - /// IDictionary of string and string - private void Sign(HTTPMethod method, string requestUrl, IDictionary parameters) { - if (parameters == null) { - throw new ArgumentNullException(nameof(parameters)); - } - // Build the signature base - StringBuilder signatureBase = new StringBuilder(); - - // Add Method to signature base - signatureBase.Append(method).Append("&"); - - // Add normalized URL - Uri url = new Uri(requestUrl); - string normalizedUrl = string.Format(CultureInfo.InvariantCulture, "{0}://{1}", url.Scheme, url.Host); - if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) { - normalizedUrl += ":" + url.Port; - } - normalizedUrl += url.AbsolutePath; - signatureBase.Append(UrlEncode3986(normalizedUrl)).Append("&"); - - // Add normalized parameters - parameters.Add(OAUTH_VERSION_KEY, OAUTH_VERSION); - parameters.Add(OAUTH_NONCE_KEY, GenerateNonce()); - parameters.Add(OAUTH_TIMESTAMP_KEY, GenerateTimeStamp()); - switch(SignatureType) { - case OAuthSignatureTypes.PLAINTEXT: - parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, PlainTextSignatureType); - break; - default: - parameters.Add(OAUTH_SIGNATURE_METHOD_KEY, HMACSHA1SignatureType); - break; - } - parameters.Add(OAUTH_CONSUMER_KEY_KEY, _consumerKey); - if (CallbackUrl != null && RequestTokenUrl != null && requestUrl.StartsWith(RequestTokenUrl)) { - parameters.Add(OAUTH_CALLBACK_KEY, CallbackUrl); - } - if (!string.IsNullOrEmpty(Verifier)) { - parameters.Add(OAUTH_VERIFIER_KEY, Verifier); - } - if (!string.IsNullOrEmpty(Token)) { - parameters.Add(OAUTH_TOKEN_KEY, Token); - } - signatureBase.Append(UrlEncode3986(GenerateNormalizedParametersString(parameters))); - Log.DebugFormat("Signature base: {0}", signatureBase); - string key = string.Format(CultureInfo.InvariantCulture, "{0}&{1}", UrlEncode3986(_consumerSecret), string.IsNullOrEmpty(TokenSecret) ? string.Empty : UrlEncode3986(TokenSecret)); - switch (SignatureType) { - case OAuthSignatureTypes.PLAINTEXT: - parameters.Add(OAUTH_SIGNATURE_KEY, key); - break; - default: - // Generate Signature and add it to the parameters - HMACSHA1 hmacsha1 = new HMACSHA1 {Key = Encoding.UTF8.GetBytes(key)}; - string signature = ComputeHash(hmacsha1, signatureBase.ToString()); - parameters.Add(OAUTH_SIGNATURE_KEY, signature); - break; - } - } - - /// - /// Make the actual OAuth request, all oauth parameters are passed as header (default) and the others are placed in the url or post data. - /// Any additional parameters added after the Sign call are not in the signature, this could be by design! - /// - /// - /// - /// - /// - /// IBinaryParameter - /// Response from server - private string MakeRequest(HTTPMethod method, string requestUrl, IDictionary headers, IDictionary parameters, IBinaryContainer postData) { - if (parameters == null) { - throw new ArgumentNullException(nameof(parameters)); - } - IDictionary requestParameters; - // Add oAuth values as HTTP headers, if this is allowed - StringBuilder authHeader = null; - if (UseHttpHeadersForAuthorization) { - authHeader = new StringBuilder(); - requestParameters = new Dictionary(); - foreach (string parameterKey in parameters.Keys) { - if (parameterKey.StartsWith(OAUTH_PARAMETER_PREFIX)) { - authHeader.AppendFormat(CultureInfo.InvariantCulture, "{0}=\"{1}\", ", parameterKey, UrlEncode3986($"{parameters[parameterKey]}")); - } else if (!requestParameters.ContainsKey(parameterKey)) { - requestParameters.Add(parameterKey, parameters[parameterKey]); - } - } - // Remove trailing comma and space and add it to the headers - if (authHeader.Length > 0) { - authHeader.Remove(authHeader.Length - 2, 2); - } - } else { - requestParameters = parameters; - } - - if (HTTPMethod.GET == method || postData != null) { - if (requestParameters.Count > 0) { - // Add the parameters to the request - requestUrl += "?" + NetworkHelper.GenerateQueryParameters(requestParameters); - } - } - // Create webrequest - HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(requestUrl, method); - webRequest.ServicePoint.Expect100Continue = false; - webRequest.UserAgent = _userAgent; - - if (UseHttpHeadersForAuthorization && authHeader != null) { - Log.DebugFormat("Authorization: OAuth {0}", authHeader); - webRequest.Headers.Add("Authorization: OAuth " + authHeader); - } - - if (headers != null) { - foreach(string key in headers.Keys) { - webRequest.Headers.Add(key, headers[key]); - } - } - - if ((HTTPMethod.POST == method || HTTPMethod.PUT == method) && postData == null && requestParameters.Count > 0) { - if (UseMultipartFormData) { - NetworkHelper.WriteMultipartFormData(webRequest, requestParameters); - } else { - StringBuilder form = new StringBuilder(); - foreach (string parameterKey in requestParameters.Keys) - { - var binaryParameter = parameters[parameterKey] as IBinaryContainer; - form.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", UrlEncode3986(parameterKey), binaryParameter != null ? UrlEncode3986(binaryParameter.ToBase64String(Base64FormattingOptions.None)) : UrlEncode3986($"{parameters[parameterKey]}")); - } - // Remove trailing & - if (form.Length > 0) { - form.Remove(form.Length - 1, 1); - } - webRequest.ContentType = "application/x-www-form-urlencoded"; - byte[] data = Encoding.UTF8.GetBytes(form.ToString()); - using var requestStream = webRequest.GetRequestStream(); - requestStream.Write(data, 0, data.Length); - } - } else if (postData != null) { - postData.Upload(webRequest); - } else { - webRequest.ContentLength = 0; - } - - string responseData; - try { - responseData = NetworkHelper.GetResponseAsString(webRequest); - Log.DebugFormat("Response: {0}", responseData); - } catch (Exception ex) { - Log.Error("Couldn't retrieve response: ", ex); - throw; - } - - return responseData; - } - } - - /// - /// OAuth 2.0 verification code receiver that runs a local server on a free port - /// and waits for a call with the authorization verification code. - /// - public class LocalServerCodeReceiver { - private static readonly ILog Log = LogManager.GetLogger(typeof(LocalServerCodeReceiver)); - private readonly ManualResetEvent _ready = new ManualResetEvent(true); - - /// - /// The call back format. Expects one port parameter. - /// Default: http://localhost:{0}/authorize/ - /// - public string LoopbackCallbackUrl { get; set; } = "http://localhost:{0}/authorize/"; - - /// - /// HTML code to to return the _browser, default it will try to close the _browser / tab, this won't always work. - /// You can use CloudServiceName where you want to show the CloudServiceName from your OAuth2 settings - /// - public string ClosePageResponse { get; set; } = @" -OAuth 2.0 Authentication CloudServiceName - -Greenshot received information from CloudServiceName. You can close this browser / tab if it is not closed itself... - - -"; - - private string _redirectUri; - /// - /// The URL to redirect to - /// - protected string RedirectUri { - get { - if (!string.IsNullOrEmpty(_redirectUri)) { - return _redirectUri; - } - - return _redirectUri = string.Format(LoopbackCallbackUrl, GetRandomUnusedPort()); - } - } - - private string _cloudServiceName; - - private readonly IDictionary _returnValues = new Dictionary(); - - - /// - /// The OAuth code receiver - /// - /// - /// Dictionary with values - public IDictionary ReceiveCode(OAuth2Settings oauth2Settings) { - // Set the redirect URL on the settings - oauth2Settings.RedirectUrl = RedirectUri; - _cloudServiceName = oauth2Settings.CloudServiceName; - using (var listener = new HttpListener()) { - listener.Prefixes.Add(oauth2Settings.RedirectUrl); - try { - listener.Start(); - - // Get the formatted FormattedAuthUrl - string authorizationUrl = oauth2Settings.FormattedAuthUrl; - Log.DebugFormat("Open a browser with: {0}", authorizationUrl); - Process.Start(authorizationUrl); - - // Wait to get the authorization code response. - var context = listener.BeginGetContext(ListenerCallback, listener); - _ready.Reset(); - - while (!context.AsyncWaitHandle.WaitOne(1000, true)) { - Log.Debug("Waiting for response"); - } - } catch (Exception) { - // Make sure we can clean up, also if the thead is aborted - _ready.Set(); - throw; - } finally { - _ready.WaitOne(); - listener.Close(); - } - } - return _returnValues; - } - - /// - /// Handle a connection async, this allows us to break the waiting - /// - /// IAsyncResult - private void ListenerCallback(IAsyncResult result) { - HttpListener listener = (HttpListener)result.AsyncState; - - //If not listening return immediately as this method is called one last time after Close() - if (!listener.IsListening) { - return; - } - - // Use EndGetContext to complete the asynchronous operation. - HttpListenerContext context = listener.EndGetContext(result); - - - // Handle request - HttpListenerRequest request = context.Request; - try { - NameValueCollection nameValueCollection = request.QueryString; - - // Get response object. - using (HttpListenerResponse response = context.Response) { - // Write a "close" response. - byte[] buffer = Encoding.UTF8.GetBytes(ClosePageResponse.Replace("CloudServiceName", _cloudServiceName)); - // Write to response stream. - response.ContentLength64 = buffer.Length; - using var stream = response.OutputStream; - stream.Write(buffer, 0, buffer.Length); - } - - // Create a new response URL with a dictionary that contains all the response query parameters. - foreach (var name in nameValueCollection.AllKeys) { - if (!_returnValues.ContainsKey(name)) { - _returnValues.Add(name, nameValueCollection[name]); - } - } - } catch (Exception) { - context.Response.OutputStream.Close(); - throw; - } - _ready.Set(); - } - - /// - /// Returns a random, unused port. - /// - /// port to use - private static int GetRandomUnusedPort() { - var listener = new TcpListener(IPAddress.Loopback, 0); - try { - listener.Start(); - return ((IPEndPoint)listener.LocalEndpoint).Port; - } finally { - listener.Stop(); - } - } - } - - /// - /// Code to simplify OAuth 2 - /// - public static class OAuth2Helper { - private const string RefreshToken = "refresh_token"; - private const string AccessToken = "access_token"; - private const string Code = "code"; - private const string ClientId = "client_id"; - private const string ClientSecret = "client_secret"; - private const string GrantType = "grant_type"; - private const string AuthorizationCode = "authorization_code"; - private const string RedirectUri = "redirect_uri"; - private const string ExpiresIn = "expires_in"; - - /// - /// Generate an OAuth 2 Token by using the supplied code - /// - /// OAuth2Settings to update with the information that was retrieved - public static void GenerateRefreshToken(OAuth2Settings settings) { - IDictionary data = new Dictionary - { - // Use the returned code to get a refresh code - { Code, settings.Code }, - { ClientId, settings.ClientId }, - { RedirectUri, settings.RedirectUrl }, - { ClientSecret, settings.ClientSecret }, - { GrantType, AuthorizationCode } - }; - foreach (string key in settings.AdditionalAttributes.Keys) { - data.Add(key, settings.AdditionalAttributes[key]); - } - - HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(settings.TokenUrl, HTTPMethod.POST); - NetworkHelper.UploadFormUrlEncoded(webRequest, data); - string accessTokenJsonResult = NetworkHelper.GetResponseAsString(webRequest, true); - - IDictionary refreshTokenResult = JSONHelper.JsonDecode(accessTokenJsonResult); - if (refreshTokenResult.ContainsKey("error")) - { - if (refreshTokenResult.ContainsKey("error_description")) { - throw new Exception($"{refreshTokenResult["error"]} - {refreshTokenResult["error_description"]}"); - } - throw new Exception((string)refreshTokenResult["error"]); - } - - // gives as described here: https://developers.google.com/identity/protocols/OAuth2InstalledApp - // "access_token":"1/fFAGRNJru1FTz70BzhT3Zg", - // "expires_in":3920, - // "token_type":"Bearer", - // "refresh_token":"1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" - if (refreshTokenResult.ContainsKey(AccessToken)) - { - settings.AccessToken = (string)refreshTokenResult[AccessToken]; - } - if (refreshTokenResult.ContainsKey(RefreshToken)) - { - settings.RefreshToken = (string)refreshTokenResult[RefreshToken]; - } - if (refreshTokenResult.ContainsKey(ExpiresIn)) - { - object seconds = refreshTokenResult[ExpiresIn]; - if (seconds != null) - { - settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double)seconds); - } - } - settings.Code = null; - } - - /// - /// Used to update the settings with the callback information - /// - /// OAuth2Settings - /// IDictionary - /// true if the access token is already in the callback - private static bool UpdateFromCallback(OAuth2Settings settings, IDictionary callbackParameters) - { - if (!callbackParameters.ContainsKey(AccessToken)) - { - return false; - } - if (callbackParameters.ContainsKey(RefreshToken)) - { - // Refresh the refresh token :) - settings.RefreshToken = callbackParameters[RefreshToken]; - } - if (callbackParameters.ContainsKey(ExpiresIn)) - { - var expiresIn = callbackParameters[ExpiresIn]; - settings.AccessTokenExpires = DateTimeOffset.MaxValue; - if (expiresIn != null) - { - if (double.TryParse(expiresIn, out var seconds)) - { - settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds(seconds); - } - } - } - settings.AccessToken = callbackParameters[AccessToken]; - return true; - } - - /// - /// Go out and retrieve a new access token via refresh-token with the TokenUrl in the settings - /// Will upate the access token, refresh token, expire date - /// - /// - public static void GenerateAccessToken(OAuth2Settings settings) { - IDictionary data = new Dictionary - { - { RefreshToken, settings.RefreshToken }, - { ClientId, settings.ClientId }, - { ClientSecret, settings.ClientSecret }, - { GrantType, RefreshToken } - }; - foreach (string key in settings.AdditionalAttributes.Keys) { - data.Add(key, settings.AdditionalAttributes[key]); - } - - HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(settings.TokenUrl, HTTPMethod.POST); - NetworkHelper.UploadFormUrlEncoded(webRequest, data); - string accessTokenJsonResult = NetworkHelper.GetResponseAsString(webRequest, true); - - // gives as described here: https://developers.google.com/identity/protocols/OAuth2InstalledApp - // "access_token":"1/fFAGRNJru1FTz70BzhT3Zg", - // "expires_in":3920, - // "token_type":"Bearer", - - IDictionary accessTokenResult = JSONHelper.JsonDecode(accessTokenJsonResult); - if (accessTokenResult.ContainsKey("error")) { - if ("invalid_grant" == (string)accessTokenResult["error"]) { - // Refresh token has also expired, we need a new one! - settings.RefreshToken = null; - settings.AccessToken = null; - settings.AccessTokenExpires = DateTimeOffset.MinValue; - settings.Code = null; - return; - } else { - if (accessTokenResult.ContainsKey("error_description")) { - throw new Exception($"{accessTokenResult["error"]} - {accessTokenResult["error_description"]}"); - } else { - throw new Exception((string)accessTokenResult["error"]); - } - } - } - - if (accessTokenResult.ContainsKey(AccessToken)) - { - settings.AccessToken = (string) accessTokenResult[AccessToken]; - settings.AccessTokenExpires = DateTimeOffset.MaxValue; - } - if (accessTokenResult.ContainsKey(RefreshToken)) { - // Refresh the refresh token :) - settings.RefreshToken = (string)accessTokenResult[RefreshToken]; - } - if (accessTokenResult.ContainsKey(ExpiresIn)) - { - object seconds = accessTokenResult[ExpiresIn]; - if (seconds != null) - { - settings.AccessTokenExpires = DateTimeOffset.Now.AddSeconds((double) seconds); - } - } - } - - /// - /// Authenticate by using the mode specified in the settings - /// - /// OAuth2Settings - /// false if it was canceled, true if it worked, exception if not - public static bool Authenticate(OAuth2Settings settings) { - var completed = settings.AuthorizeMode switch - { - OAuth2AuthorizeMode.LocalServer => AuthenticateViaLocalServer(settings), - OAuth2AuthorizeMode.EmbeddedBrowser => AuthenticateViaEmbeddedBrowser(settings), - OAuth2AuthorizeMode.OutOfBoundAuto => AuthenticateViaDefaultBrowser(settings), - _ => throw new NotImplementedException($"Authorize mode '{settings.AuthorizeMode}' is not 'yet' implemented."), - }; - return completed; - } - - /// - /// Authenticate via the default browser - /// If this works, return the code - /// - /// OAuth2Settings with the Auth / Token url etc - /// true if completed, false if canceled - private static bool AuthenticateViaDefaultBrowser(OAuth2Settings settings) - { - var monitor = new WindowsTitleMonitor(); - - string[] code = new string[1]; - monitor.TitleChangeEvent += args => - { - if (args.Title.Contains(settings.State)) - { - code[0] = args.Title; - settings.Code = args.Title; - } - }; - using (var process = Process.Start(settings.FormattedAuthUrl)) - { - while (string.IsNullOrEmpty(code[0])) - { - Application.DoEvents(); - } - }; - - return true; - } - - /// - /// Authenticate via an embedded browser - /// If this works, return the code - /// - /// OAuth2Settings with the Auth / Token url etc - /// true if completed, false if canceled - private static bool AuthenticateViaEmbeddedBrowser(OAuth2Settings settings) { - if (string.IsNullOrEmpty(settings.CloudServiceName)) { - throw new ArgumentNullException(nameof(settings.CloudServiceName)); - } - if (settings.BrowserSize == Size.Empty) { - throw new ArgumentNullException(nameof(settings.BrowserSize)); - } - OAuthLoginForm loginForm = new OAuthLoginForm($"Authorize {settings.CloudServiceName}", settings.BrowserSize, settings.FormattedAuthUrl, settings.RedirectUrl); - loginForm.ShowDialog(); - if (loginForm.IsOk) { - if (loginForm.CallbackParameters.TryGetValue(Code, out var code) && !string.IsNullOrEmpty(code)) { - settings.Code = code; - GenerateRefreshToken(settings); - return true; - } - return UpdateFromCallback(settings, loginForm.CallbackParameters); - } - return false; - } - - /// - /// Authenticate via a local server by using the LocalServerCodeReceiver - /// If this works, return the code - /// - /// OAuth2Settings with the Auth / Token url etc - /// true if completed - private static bool AuthenticateViaLocalServer(OAuth2Settings settings) { - var codeReceiver = new LocalServerCodeReceiver(); - IDictionary result = codeReceiver.ReceiveCode(settings); - - if (result.TryGetValue(Code, out var code) && !string.IsNullOrEmpty(code)) { - settings.Code = code; - GenerateRefreshToken(settings); - return true; - } - - if (result.TryGetValue("error", out var error)) { - if (result.TryGetValue("error_description", out var errorDescription)) { - throw new Exception(errorDescription); - } - if ("access_denied" == error) { - throw new UnauthorizedAccessException("Access denied"); - } - throw new Exception(error); - } - return false; - } - - /// - /// Simple helper to add the Authorization Bearer header - /// - /// WebRequest - /// OAuth2Settings - public static void AddOAuth2Credentials(HttpWebRequest webRequest, OAuth2Settings settings) { - if (!string.IsNullOrEmpty(settings.AccessToken)) { - webRequest.Headers.Add("Authorization", "Bearer " + settings.AccessToken); - } - } - - /// - /// Check and authenticate or refresh tokens - /// - /// OAuth2Settings - public static void CheckAndAuthenticateOrRefresh(OAuth2Settings settings) { - // Get Refresh / Access token - if (string.IsNullOrEmpty(settings.RefreshToken)) { - if (!Authenticate(settings)) { - throw new Exception("Authentication cancelled"); - } - } - if (settings.IsAccessTokenExpired) { - GenerateAccessToken(settings); - // Get Refresh / Access token - if (string.IsNullOrEmpty(settings.RefreshToken)) { - if (!Authenticate(settings)) { - throw new Exception("Authentication cancelled"); - } - GenerateAccessToken(settings); - } - } - if (settings.IsAccessTokenExpired) { - throw new Exception("Authentication failed"); - } - } - - /// - /// CreateWebRequest ready for OAuth 2 access - /// - /// HTTPMethod - /// - /// OAuth2Settings - /// HttpWebRequest - public static HttpWebRequest CreateOAuth2WebRequest(HTTPMethod method, string url, OAuth2Settings settings) { - CheckAndAuthenticateOrRefresh(settings); - - HttpWebRequest webRequest = NetworkHelper.CreateWebRequest(url, method); - AddOAuth2Credentials(webRequest, settings); - return webRequest; - } - } -} diff --git a/GreenshotPlugin/Core/PluginUtils.cs b/GreenshotPlugin/Core/PluginUtils.cs index 0db458a3f..51edfffa8 100644 --- a/GreenshotPlugin/Core/PluginUtils.cs +++ b/GreenshotPlugin/Core/PluginUtils.cs @@ -29,7 +29,6 @@ using System.Drawing; using System.IO; using System.Windows.Forms; using GreenshotPlugin.IniFile; -using GreenshotPlugin.Interfaces.Forms; namespace GreenshotPlugin.Core { /// @@ -52,7 +51,7 @@ namespace GreenshotPlugin.Core { /// private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName != "IconSize") return; - List cachedImages = new List(); + var cachedImages = new List(); lock (ExeIconCache) { foreach (string key in ExeIconCache.Keys) { cachedImages.Add(ExeIconCache[key]); @@ -71,7 +70,7 @@ namespace GreenshotPlugin.Core { /// e.g. cmd.exe /// Path to file public static string GetExePath(string exeName) { - using (RegistryKey key = Registry.LocalMachine.OpenSubKey(PathKey + exeName, false)) { + using (var key = Registry.LocalMachine.OpenSubKey(PathKey + exeName, false)) { if (key != null) { // "" is the default key, which should point to the requested location return (string)key.GetValue(string.Empty); @@ -147,69 +146,7 @@ namespace GreenshotPlugin.Core { return null; } - /// - /// Helper method to add a MenuItem to the File MenuItem of an ImageEditor - /// - /// - /// Image to display in the menu - /// Text to display in the menu - /// The TAG value - /// Keys which can be used as shortcut - /// The onclick handler - public static void AddToFileMenu(IImageEditor imageEditor, Image image, string text, object tag, Keys? shortcutKeys, EventHandler handler) { - var item = new ToolStripMenuItem - { - Image = image, - Text = text, - Tag = tag - }; - if (shortcutKeys.HasValue) { - item.ShortcutKeys = shortcutKeys.Value; - } - item.Click += handler; - AddToFileMenu(imageEditor, item); - } - - /// - /// Helper method to add a MenuItem to the File MenuItem of an ImageEditor - /// - /// - /// - public static void AddToFileMenu(IImageEditor imageEditor, ToolStripMenuItem item) { - ToolStripMenuItem toolStripMenuItem = imageEditor.GetFileMenuItem(); - bool added = false; - for(int i = 0; i< toolStripMenuItem.DropDownItems.Count; i++) { - if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) { - toolStripMenuItem.DropDownItems.Insert(i, item); - added = true; - break; - } - } - if (!added) { - toolStripMenuItem.DropDownItems.Add(item); - } - } - - /// - /// Helper method to add a MenuItem to the Plugin MenuItem of an ImageEditor - /// - /// - /// - public static void AddToPluginMenu(IImageEditor imageEditor, ToolStripMenuItem item) { - ToolStripMenuItem toolStripMenuItem = imageEditor.GetPluginMenuItem(); - bool added = false; - for(int i = 0; i< toolStripMenuItem.DropDownItems.Count; i++) { - if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator)) { - toolStripMenuItem.DropDownItems.Insert(i, item); - added = true; - break; - } - } - if (!added) { - toolStripMenuItem.DropDownItems.Add(item); - } - } - /// + /// /// Helper method to add a plugin MenuItem to the Greenshot context menu /// /// ToolStripMenuItem diff --git a/GreenshotPlugin/Core/StringExtensions.cs b/GreenshotPlugin/Core/StringExtensions.cs index e7ee8cf81..cd957c543 100644 --- a/GreenshotPlugin/Core/StringExtensions.cs +++ b/GreenshotPlugin/Core/StringExtensions.cs @@ -137,19 +137,5 @@ namespace GreenshotPlugin.Core { return returnValue; } - - /// - /// Read "streamextensions" :) - /// - /// Stream - /// Stream - public static void CopyTo(this Stream input, Stream output) { - byte[] buffer = new byte[16 * 1024]; // Fairly arbitrary size - int bytesRead; - - while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) { - output.Write(buffer, 0, bytesRead); - } - } - } + } } diff --git a/GreenshotPlugin/Core/WindowDetails.cs b/GreenshotPlugin/Core/WindowDetails.cs index 0410d79c7..7c9a2b905 100644 --- a/GreenshotPlugin/Core/WindowDetails.cs +++ b/GreenshotPlugin/Core/WindowDetails.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Drawing; +using System.Drawing.Drawing2D; using System.Drawing.Imaging; +using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; @@ -25,11 +27,11 @@ namespace GreenshotPlugin.Core /// /// Provides details about a Window returned by the enumeration /// - public class WindowDetails : IEquatable{ - private const string MetroWindowsClass = "Windows.UI.Core.CoreWindow"; //Used for Windows 8(.1) - private const string FramedAppClass = "ApplicationFrameWindow"; // Windows 10 uses ApplicationFrameWindow - private const string MetroApplauncherClass = "ImmersiveLauncher"; - private const string MetroGutterClass = "ImmersiveGutter"; + public class WindowDetails : IEquatable { + private const string AppWindowClass = "Windows.UI.Core.CoreWindow"; //Used for Windows 8(.1) + private const string AppFrameWindowClass = "ApplicationFrameWindow"; // Windows 10 uses ApplicationFrameWindow + private const string ApplauncherClass = "ImmersiveLauncher"; + private const string GutterClass = "ImmersiveGutter"; private static readonly IList IgnoreClasses = new List(new[] { "Progman", "Button", "Dwm" }); //"MS-SDIa" private static readonly ILog Log = LogManager.GetLogger(typeof(WindowDetails)); @@ -72,23 +74,28 @@ namespace GreenshotPlugin.Core /// This checks if the window is a Windows 8 App /// For Windows 10 most normal code works, as it's hosted inside "ApplicationFrameWindow" /// - public bool IsApp => MetroWindowsClass.Equals(ClassName); + public bool IsApp => AppWindowClass.Equals(ClassName); /// /// This checks if the window is a Windows 10 App /// For Windows 10 apps are hosted inside "ApplicationFrameWindow" /// - public bool IsWin10App => FramedAppClass.Equals(ClassName); + public bool IsWin10App => AppFrameWindowClass.Equals(ClassName); + /// + /// Check if this window belongs to a background app + /// + public bool IsBackgroundWin10App => WindowsVersion.IsWindows10OrLater && AppFrameWindowClass.Equals(ClassName) && !Children.Any(window => string.Equals(window.ClassName, AppWindowClass)); + /// /// Check if the window is the metro gutter (sizeable separator) /// - public bool IsGutter => MetroGutterClass.Equals(ClassName); + public bool IsGutter => GutterClass.Equals(ClassName); /// /// Test if this window is for the App-Launcher /// - public bool IsAppLauncher => MetroApplauncherClass.Equals(ClassName); + public bool IsAppLauncher => ApplauncherClass.Equals(ClassName); /// /// Check if this window is the window of a metro app @@ -259,33 +266,6 @@ namespace GreenshotPlugin.Core } } - /// - /// Retrieve all windows with a certain title or classname - /// - /// IEnumerable - /// The regexp to look for in the title - /// The regexp to look for in the classname - /// IEnumerable WindowDetails with all the found windows - private static IEnumerable FindWindow(IEnumerable windows, string titlePattern, string classnamePattern) { - Regex titleRegexp = null; - Regex classnameRegexp = null; - - if (titlePattern != null && titlePattern.Trim().Length > 0) { - titleRegexp = new Regex(titlePattern); - } - if (classnamePattern != null && classnamePattern.Trim().Length > 0) { - classnameRegexp = new Regex(classnamePattern); - } - - foreach(WindowDetails window in windows) { - if (titleRegexp != null && titleRegexp.IsMatch(window.Text)) { - yield return window; - } else if (classnameRegexp != null && classnameRegexp.IsMatch(window.ClassName)) { - yield return window; - } - } - } - /// /// Retrieve the child with matching classname /// @@ -298,17 +278,6 @@ namespace GreenshotPlugin.Core return null; } - /// - /// Retrieve the children with matching classname - /// - public IEnumerable GetChilden(string childClassname) { - foreach (var child in Children) { - if (childClassname.Equals(child.ClassName)) { - yield return child; - } - } - } - public IntPtr ParentHandle { get { if (_parentHandle == IntPtr.Zero) { @@ -369,102 +338,6 @@ namespace GreenshotPlugin.Core return _childWindows; } - /// - /// Retrieve children with a certain title or classname - /// - /// The regexp to look for in the title - /// The regexp to look for in the classname - /// List WindowDetails with all the found windows, or an empty list - public IEnumerable FindChildren(string titlePattern, string classnamePattern) { - return FindWindow(Children, titlePattern, classnamePattern); - } - - /// - /// Recurse-ing helper method for the FindPath - /// - /// List string with classNames - /// The index in the list to look for - /// WindowDetails if a match was found - private WindowDetails FindPath(IList classNames, int index) { - if (index == classNames.Count - 1) { - foreach (var foundWindow in FindChildren(null, classNames[index])) - { - return foundWindow; - } - } else { - foreach(var foundWindow in FindChildren(null, classNames[index])) - { - var resultWindow = foundWindow.FindPath(classNames, index+1); - if (resultWindow != null) - { - return resultWindow; - } - } - } - return null; - } - - /// - /// This method will find the child window according to a path of classNames. - /// Usually used for finding a certain "content" window like for the IE Browser - /// - /// List of string with classname "path" - /// true allows the search to skip a classname of the path - /// WindowDetails if found - public WindowDetails FindPath(IList classNames, bool allowSkip) { - int index = 0; - var resultWindow = FindPath(classNames, index++); - if (resultWindow == null && allowSkip) { - while(resultWindow == null && index < classNames.Count) { - resultWindow = FindPath(classNames, index); - } - } - return resultWindow; - } - - /// - /// Deep scan for a certain classname pattern - /// - /// Window to scan into - /// Classname regexp pattern - /// The first WindowDetails found - public static WindowDetails DeepScan(WindowDetails windowDetails, Regex classnamePattern) { - if (classnamePattern.IsMatch(windowDetails.ClassName)) { - return windowDetails; - } - // First loop through this level - foreach(var child in windowDetails.Children) { - if (classnamePattern.IsMatch(child.ClassName)) { - return child; - } - } - // Go into all children - foreach(var child in windowDetails.Children) { - var deepWindow = DeepScan(child, classnamePattern); - if (deepWindow != null) { - return deepWindow; - } - } - return null; - } - - /// - /// GetWindow - /// - /// The GetWindowCommand to use - /// null if nothing found, otherwise the WindowDetails instance of the "child" - public WindowDetails GetWindow(GetWindowCommand gwCommand) { - var tmphWnd = User32.GetWindow(Handle, gwCommand); - if (IntPtr.Zero == tmphWnd) { - return null; - } - var windowDetails = new WindowDetails(tmphWnd) - { - _parent = this - }; - return windowDetails; - } - /// /// Gets the window's handle /// @@ -512,7 +385,7 @@ namespace GreenshotPlugin.Core } /// - /// Gets/Sets whether the window is maximised or not. + /// Gets/Sets whether the window is maximized or not. /// public bool Maximised { get { @@ -541,13 +414,6 @@ namespace GreenshotPlugin.Core } } - /// - /// This doesn't work as good as is should, but does move the App out of the way... - /// - public void HideApp() { - User32.ShowWindow(Handle, ShowWindowCommand.Hide); - } - /// /// Returns if this window is cloaked /// @@ -561,7 +427,7 @@ namespace GreenshotPlugin.Core /// public bool Visible { get { - // Tip from Raymond Chen + // Tip from Raymond Chen https://devblogs.microsoft.com/oldnewthing/20200302-00/?p=103507 if (IsCloaked) { return false; @@ -627,13 +493,6 @@ namespace GreenshotPlugin.Core } } - /// - /// Make sure the next call of a cached value is guaranteed the real value - /// - public void Reset() { - _previousWindowRectangle = Rectangle.Empty; - } - private Rectangle _previousWindowRectangle = Rectangle.Empty; private long _lastWindowRectangleRetrieveTime; private const long CacheTime = TimeSpan.TicksPerSecond * 2; @@ -1354,24 +1213,6 @@ namespace GreenshotPlugin.Core return null; } - /// - /// Check if this window is Greenshot - /// - public bool IsGreenshot { - get { - try { - if (!IsMetroApp) - { - using Process thisWindowProcess = Process; - return "Greenshot".Equals(thisWindowProcess.MainModule.FileVersionInfo.ProductName); - } - } catch (Exception ex) { - Log.Warn(ex); - } - return false; - } - } - /// /// Gets the Desktop window /// @@ -1476,7 +1317,7 @@ namespace GreenshotPlugin.Core /// List WindowDetails with all the visible top level windows public static IEnumerable GetVisibleWindows() { Rectangle screenBounds = WindowCapture.GetScreenBounds(); - foreach(var window in GetMetroApps()) { + foreach(var window in GetAppWindows()) { if (IsVisible(window, screenBounds)) { yield return window; @@ -1496,37 +1337,24 @@ namespace GreenshotPlugin.Core /// These are all Windows with Classname "Windows.UI.Core.CoreWindow" /// /// List WindowDetails with visible metro apps - public static IEnumerable GetMetroApps() { + public static IEnumerable GetAppWindows() { // if the appVisibility != null we have Windows 8. if (AppVisibility == null) { yield break; } - //string[] wcs = {"ImmersiveGutter", "Snapped Desktop", "ImmersiveBackgroundWindow","ImmersiveLauncher","Windows.UI.Core.CoreWindow","ApplicationManager_ImmersiveShellWindow","SearchPane","MetroGhostWindow","EdgeUiInputWndClass", "NativeHWNDHost", "Shell_CharmWindow"}; - //List specials = new List(); - //foreach(string wc in wcs) { - // IntPtr wcHandle = User32.FindWindow(null, null); - // while (wcHandle != IntPtr.Zero) { - // WindowDetails special = new WindowDetails(wcHandle); - // if (special.WindowRectangle.Left >= 1920 && special.WindowRectangle.Size != Size.Empty) { - // specials.Add(special); - // LOG.DebugFormat("Found special {0} : {1} at {2} visible: {3} {4} {5}", special.ClassName, special.Text, special.WindowRectangle, special.Visible, special.ExtendedWindowStyle, special.WindowStyle); - // } - // wcHandle = User32.FindWindowEx(IntPtr.Zero, wcHandle, null, null); - // }; - //} - IntPtr nextHandle = User32.FindWindow(MetroWindowsClass, null); + var nextHandle = User32.FindWindow(AppWindowClass, null); while (nextHandle != IntPtr.Zero) { var metroApp = new WindowDetails(nextHandle); yield return metroApp; // Check if we have a gutter! if (metroApp.Visible && !metroApp.Maximised) { - var gutterHandle = User32.FindWindow(MetroGutterClass, null); + var gutterHandle = User32.FindWindow(GutterClass, null); if (gutterHandle != IntPtr.Zero) { yield return new WindowDetails(gutterHandle); } } - nextHandle = User32.FindWindowEx(IntPtr.Zero, nextHandle, MetroWindowsClass, null); + nextHandle = User32.FindWindowEx(IntPtr.Zero, nextHandle, AppWindowClass, null); } } @@ -1537,21 +1365,10 @@ namespace GreenshotPlugin.Core /// bool private static bool IsTopLevel(WindowDetails window) { - // Window is not on this desktop if (window.IsCloaked) { return false; } - - // Ignore windows without title - if (window.Text.Length == 0) - { - return false; - } - if (IgnoreClasses.Contains(window.ClassName)) - { - return false; - } // Windows without size if (window.WindowRectangle.Size.Width * window.WindowRectangle.Size.Height == 0) { @@ -1576,7 +1393,21 @@ namespace GreenshotPlugin.Core { return false; } - return window.Visible || window.Iconic; + // Ignore windows without title + if (window.Text.Length == 0) + { + return false; + } + if (IgnoreClasses.Contains(window.ClassName)) + { + return false; + } + if (!(window.Visible || window.Iconic)) + { + return false; + } + + return !window.IsBackgroundWin10App; } /// @@ -1584,7 +1415,7 @@ namespace GreenshotPlugin.Core /// /// List WindowDetails with all the top level windows public static IEnumerable GetTopLevelWindows() { - foreach (var possibleTopLevel in GetMetroApps()) + foreach (var possibleTopLevel in GetAppWindows()) { if (IsTopLevel(possibleTopLevel)) { @@ -1662,7 +1493,7 @@ namespace GreenshotPlugin.Core if (AppVisibility == null) { return null; } - IntPtr appLauncher = User32.FindWindow(MetroApplauncherClass, null); + IntPtr appLauncher = User32.FindWindow(ApplauncherClass, null); if (appLauncher != IntPtr.Zero) { return new WindowDetails (appLauncher); } @@ -1681,5 +1512,32 @@ namespace GreenshotPlugin.Core return false; } } + + /// + /// Make a string representation of the window details + /// + /// string + public override string ToString() + { + var result = new StringBuilder(); + result.AppendLine($"Text: {Text}"); + result.AppendLine($"ClassName: {ClassName}"); + result.AppendLine($"ExtendedWindowStyle: {ExtendedWindowStyle}"); + result.AppendLine($"WindowStyle: {WindowStyle}"); + result.AppendLine($"Size: {WindowRectangle.Size}"); + result.AppendLine($"HasParent: {HasParent}"); + result.AppendLine($"IsWin10App: {IsWin10App}"); + result.AppendLine($"IsApp: {IsApp}"); + result.AppendLine($"Visible: {Visible}"); + result.AppendLine($"IsWindowVisible: {User32.IsWindowVisible(Handle)}"); + result.AppendLine($"IsCloaked: {IsCloaked}"); + result.AppendLine($"Iconic: {Iconic}"); + result.AppendLine($"IsBackgroundWin10App: {IsBackgroundWin10App}"); + if (HasChildren) + { + result.AppendLine($"Children classes: {string.Join(",", Children.Select(c => c.ClassName))}"); + } + return result.ToString(); + } } } \ No newline at end of file diff --git a/GreenshotPlugin/Core/WindowsEnumerator.cs b/GreenshotPlugin/Core/WindowsEnumerator.cs index 3bc1095a5..9025cd7b8 100644 --- a/GreenshotPlugin/Core/WindowsEnumerator.cs +++ b/GreenshotPlugin/Core/WindowsEnumerator.cs @@ -34,25 +34,7 @@ namespace GreenshotPlugin.Core { /// public IList Items { get; private set; } - /// - /// Gets all top level windows on the system. - /// - public WindowsEnumerator GetWindows() { - GetWindows(IntPtr.Zero, null); - return this; - } - - /// - /// Gets all child windows of the specified window - /// - /// Window Handle to get children for - public WindowsEnumerator GetWindows(WindowDetails parent) - { - GetWindows(parent?.Handle ?? IntPtr.Zero, null); - return this; - } - - /// + /// /// Gets all child windows of the specified window /// /// Window Handle to get children for @@ -69,7 +51,7 @@ namespace GreenshotPlugin.Core { parentText = title.ToString(); } - List windows = new List(); + var windows = new List(); foreach (var window in Items) { if (hasParent) { window.Text = parentText; diff --git a/GreenshotPlugin/Core/WindowsVersion.cs b/GreenshotPlugin/Core/WindowsVersion.cs index cd263d518..703fcd206 100644 --- a/GreenshotPlugin/Core/WindowsVersion.cs +++ b/GreenshotPlugin/Core/WindowsVersion.cs @@ -15,51 +15,18 @@ namespace GreenshotPlugin.Core /// public static Version WinVersion { get; } = Environment.OSVersion.Version; - public static double WinVersionTotal = WinVersion.Major + (double)WinVersion.Minor / 10; /// /// Test if the current OS is Windows 10 /// /// true if we are running on Windows 10 public static bool IsWindows10 { get; } = WinVersion.Major == 10; - /// - /// Test if the current OS is before Windows 10 - /// - /// true if we are running on Windows before 10 - public static bool IsBeforeWindows10 { get; } = WinVersion.Major < 10; - /// /// Test if the current OS is Windows 10 or later /// /// true if we are running on Windows 10 or later public static bool IsWindows10OrLater { get; } = WinVersion.Major >= 10; - /// - /// Test if the current OS is Windows 7 or later - /// - /// true if we are running on Windows 7 or later - public static bool IsWindows7OrLater { get; } = WinVersion.Major == 6 && WinVersion.Minor >= 1 || WinVersion.Major > 6; - - public static bool IsWindows7OrLower { get; } = WinVersionTotal <= 6.1; - - /// - /// Test if the current OS is Windows 8.0 - /// - /// true if we are running on Windows 8.0 - public static bool IsWindows8 { get; } = WinVersion.Major == 6 && WinVersion.Minor == 2; - - /// - /// Test if the current OS is Windows 8(.1) - /// - /// true if we are running on Windows 8(.1) - public static bool IsWindows81 { get; } = WinVersion.Major == 6 && WinVersion.Minor == 3; - - /// - /// Test if the current OS is Windows 8.0 or 8.1 - /// - /// true if we are running on Windows 8.1 or 8.0 - public static bool IsWindows8X { get; } = IsWindows8 || IsWindows81; - /// /// Test if the current OS is Windows 8.1 or later /// @@ -72,36 +39,12 @@ namespace GreenshotPlugin.Core /// true if we are running on Windows 8 or later public static bool IsWindows8OrLater { get; } = WinVersion.Major == 6 && WinVersion.Minor >= 2 || WinVersion.Major > 6; - /// - /// Test if the current OS is Windows Vista - /// - /// true if we are running on Windows Vista or later - public static bool IsWindowsVista { get; } = WinVersion.Major >= 6 && WinVersion.Minor == 0; - /// /// Test if the current OS is Windows Vista or later /// /// true if we are running on Windows Vista or later public static bool IsWindowsVistaOrLater { get; } = WinVersion.Major >= 6; - /// - /// Test if the current OS is from before Windows Vista (e.g. Windows XP) - /// - /// true if we are running on Windows from before Vista - public static bool IsWindowsBeforeVista { get; } = WinVersion.Major < 6; - - /// - /// Test if the current OS is Windows XP - /// - /// true if we are running on Windows XP or later - public static bool IsWindowsXp { get; } = WinVersion.Major == 5 && WinVersion.Minor >= 1; - - /// - /// Test if the current OS is Windows XP or later - /// - /// true if we are running on Windows XP or later - public static bool IsWindowsXpOrLater { get; } = WinVersion.Major >= 5 || WinVersion.Major == 5 && WinVersion.Minor >= 1; - /// /// Returns the windows build number /// diff --git a/GreenshotPlugin/FileDescriptorReader.cs b/GreenshotPlugin/FileDescriptorReader.cs new file mode 100644 index 000000000..93b94f834 --- /dev/null +++ b/GreenshotPlugin/FileDescriptorReader.cs @@ -0,0 +1,182 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Text; +using GreenshotPlugin.UnmanagedHelpers.Structs; + +namespace GreenshotPlugin.Interop +{ + + /// + /// Specifies which fields are valid in a FileDescriptor Structure + /// + [Flags] + internal enum FileDescriptorFlags : uint + { + } + + internal static class FileDescriptorReader + { + internal sealed class FileDescriptor + { + public FileDescriptorFlags Flags { get; set; } + public Guid ClassId { get; set; } + public SIZE Size { get; set; } + public POINT Point { get; set; } + public FileAttributes FileAttributes { get; set; } + public DateTime CreationTime { get; set; } + public DateTime LastAccessTime { get; set; } + public DateTime LastWriteTime { get; set; } + public Int64 FileSize { get; set; } + public string FileName { get; set; } + + public FileDescriptor(BinaryReader reader) + { + //Flags + Flags = (FileDescriptorFlags) reader.ReadUInt32(); + //ClassID + ClassId = new Guid(reader.ReadBytes(16)); + //Size + Size = new SIZE(reader.ReadInt32(), reader.ReadInt32()); + //Point + Point = new POINT(reader.ReadInt32(), reader.ReadInt32()); + //FileAttributes + FileAttributes = (FileAttributes) reader.ReadUInt32(); + //CreationTime + CreationTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64()); + //LastAccessTime + LastAccessTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64()); + //LastWriteTime + LastWriteTime = new DateTime(1601, 1, 1).AddTicks(reader.ReadInt64()); + //FileSize + FileSize = reader.ReadInt64(); + //FileName + byte[] nameBytes = reader.ReadBytes(520); + int i = 0; + while (i < nameBytes.Length) + { + if (nameBytes[i] == 0 && nameBytes[i + 1] == 0) + break; + i++; + i++; + } + + FileName = Encoding.Unicode.GetString(nameBytes, 0, i); + } + } + + public static IEnumerable Read(Stream fileDescriptorStream) + { + if (fileDescriptorStream == null) + { + yield break; + } + + var reader = new BinaryReader(fileDescriptorStream); + var count = reader.ReadUInt32(); + while (count > 0) + { + var descriptor = new FileDescriptor(reader); + + yield return descriptor; + + count--; + } + } + + public static IEnumerable ReadFileNames(Stream fileDescriptorStream) + { + if (fileDescriptorStream == null) + { + yield break; + } + var reader = new BinaryReader(fileDescriptorStream); + var count = reader.ReadUInt32(); + while (count > 0) + { + FileDescriptor descriptor = new FileDescriptor(reader); + + yield return descriptor.FileName; + + count--; + } + } + + internal static MemoryStream GetFileContents(System.Windows.Forms.IDataObject dataObject, int index) + { + //cast the default IDataObject to a com IDataObject + var comDataObject = (IDataObject)dataObject; + + var format = System.Windows.DataFormats.GetDataFormat("FileContents"); + if (format == null) + { + return null; + } + + //create STGMEDIUM to output request results into + var medium = new STGMEDIUM(); + + unchecked + { + var formatetc = new FORMATETC + { + cfFormat = (short)format.Id, + dwAspect = DVASPECT.DVASPECT_CONTENT, + lindex = index, + tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_HGLOBAL + }; + + //using the com IDataObject interface get the data using the defined FORMATETC + comDataObject.GetData(ref formatetc, out medium); + } + + return medium.tymed switch + { + TYMED.TYMED_ISTREAM => GetIStream(medium), + _ => null + }; + } + + private static MemoryStream GetIStream(STGMEDIUM medium) + { + //marshal the returned pointer to a IStream object + IStream iStream = (IStream)Marshal.GetObjectForIUnknown(medium.unionmember); + Marshal.Release(medium.unionmember); + + //get the STATSTG of the IStream to determine how many bytes are in it + var iStreamStat = new System.Runtime.InteropServices.ComTypes.STATSTG(); + iStream.Stat(out iStreamStat, 0); + int iStreamSize = (int)iStreamStat.cbSize; + + //read the data from the IStream into a managed byte array + byte[] iStreamContent = new byte[iStreamSize]; + iStream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero); + + //wrapped the managed byte array into a memory stream + return new MemoryStream(iStreamContent); + } + } +} \ No newline at end of file diff --git a/GreenshotPlugin/GreenshotPlugin.csproj b/GreenshotPlugin/GreenshotPlugin.csproj index 29371bcfd..db8b82b57 100644 --- a/GreenshotPlugin/GreenshotPlugin.csproj +++ b/GreenshotPlugin/GreenshotPlugin.csproj @@ -14,6 +14,7 @@ + diff --git a/GreenshotPlugin/Interfaces/Drawing/Container.cs b/GreenshotPlugin/Interfaces/Drawing/Container.cs index a97ff5ffc..7b999565a 100644 --- a/GreenshotPlugin/Interfaces/Drawing/Container.cs +++ b/GreenshotPlugin/Interfaces/Drawing/Container.cs @@ -24,7 +24,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; -using System.Drawing.Imaging; using System.Windows.Forms; using GreenshotPlugin.Interfaces.Drawing.Adorners; @@ -213,14 +212,4 @@ namespace GreenshotPlugin.Interfaces.Drawing } void Load(string filename); } - - public interface IMetafileContainer : IDrawableContainer - { - Metafile Metafile - { - get; - set; - } - void Load(string filename); - } } diff --git a/GreenshotPlugin/Interfaces/Drawing/IFieldholder.cs b/GreenshotPlugin/Interfaces/Drawing/IFieldholder.cs index c67303ffb..df0f779d5 100644 --- a/GreenshotPlugin/Interfaces/Drawing/IFieldholder.cs +++ b/GreenshotPlugin/Interfaces/Drawing/IFieldholder.cs @@ -31,26 +31,9 @@ namespace GreenshotPlugin.Interfaces.Drawing /// public interface IFieldHolder { - event FieldChangedEventHandler FieldChanged; - - void AddField(IField field); - void RemoveField(IField field); IList GetFields(); IField GetField(IFieldType fieldType); bool HasField(IFieldType fieldType); - void SetFieldValue(IFieldType fieldType, object value); - } - - /// - /// Extended fieldHolder which has fieldHolder children. - /// Implementations should pass field values to and from - /// their children. - /// AbstractFieldHolderWithChildren is the basic implementation. - /// - public interface IFieldHolderWithChildren : IFieldHolder - { - void AddChild(IFieldHolder fieldHolder); - void RemoveChild(IFieldHolder fieldHolder); } } diff --git a/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs b/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs index bd42b9aca..808951234 100644 --- a/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs +++ b/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs @@ -20,41 +20,21 @@ */ using System.Drawing; -using System.Windows.Forms; namespace GreenshotPlugin.Interfaces.Forms { /// /// The IImageEditor is the Interface that the Greenshot ImageEditor has to implement /// public interface IImageEditor { - /// - /// Return the IWin32Window, this way Plugins have access to the HWND handles wich can be used with Win32 API calls. - /// - IWin32Window WindowHandle { - get; - } - - /// + /// /// Get the current Image from the Editor for Exporting (save/upload etc) /// This is actually a wrapper which calls Surface.GetImageForExport(). /// Don't forget to call image.Dispose() when finished!!! /// /// Bitmap Image GetImageForExport(); - - /// - /// Get the ToolStripMenuItem where plugins can place their Menu entrys - /// - /// ToolStripMenuItem - ToolStripMenuItem GetPluginMenuItem(); - /// - /// Get the File ToolStripMenuItem - /// - /// ToolStripMenuItem - ToolStripMenuItem GetFileMenuItem(); - - /// + /// /// Make the ICaptureDetails from the current Surface in the EditorForm available. /// ICaptureDetails CaptureDetails { diff --git a/GreenshotPlugin/Interop/COMWrapper.cs b/GreenshotPlugin/Interop/COMWrapper.cs index f31392124..c96033de3 100644 --- a/GreenshotPlugin/Interop/COMWrapper.cs +++ b/GreenshotPlugin/Interop/COMWrapper.cs @@ -35,8 +35,6 @@ namespace GreenshotPlugin.Interop { /// public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo { private static readonly ILog Log = LogManager.GetLogger(typeof(COMWrapper)); - private const int MK_E_UNAVAILABLE = -2147221021; - private const int CO_E_CLASSSTRING = -2147221005; public const int RPC_E_CALL_REJECTED = unchecked((int)0x80010001); public const int RPC_E_FAIL = unchecked((int)0x80004005); @@ -60,84 +58,7 @@ namespace GreenshotPlugin.Interop { /// private readonly string _targetName; - [DllImport("ole32.dll")] - private static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgId); - // Converts failure HRESULTs to exceptions: - [DllImport("oleaut32", PreserveSig=false)] - private static extern void GetActiveObject(ref Guid rclsid, IntPtr pvReserved, [MarshalAs(UnmanagedType.IUnknown)] out object ppunk); - /// - /// Gets a COM object and returns the transparent proxy which intercepts all calls to the object - /// - /// Interface which defines the method and properties to intercept - /// Transparent proxy to the real proxy for the object - /// T must be an interface decorated with the attribute. - public static T GetInstance() { - Type type = typeof(T); - if (null == type) { - throw new ArgumentNullException(nameof(T)); - } - if (!type.IsInterface) { - throw new ArgumentException("The specified type must be an interface.", nameof(T)); - } - - var progIdAttribute = ComProgIdAttribute.GetAttribute(type); - if (string.IsNullOrEmpty(progIdAttribute?.Value)) { - throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T)); - } - string progId = progIdAttribute.Value; - - object comObject = null; - - // Convert from clsid to Prog ID, if needed - if (progId.StartsWith("clsid:")) { - Guid guid = new Guid(progId.Substring(6)); - int result = ProgIDFromCLSID(ref guid, out progId); - if (result != 0) { - // Restore progId, as it's overwritten - progId = progIdAttribute.Value; - - try { - GetActiveObject(ref guid, IntPtr.Zero, out comObject); - } catch (Exception) { - Log.WarnFormat("Error {0} getting instance for class id {1}", result, progIdAttribute.Value); - } - if (comObject == null) { - Log.WarnFormat("Error {0} getting progId {1}", result, progIdAttribute.Value); - } - } else { - Log.InfoFormat("Mapped {0} to progId {1}", progIdAttribute.Value, progId); - } - } - - if (comObject == null) { - try { - comObject = Marshal.GetActiveObject(progId); - } catch (COMException comE) { - if (comE.ErrorCode == MK_E_UNAVAILABLE) { - Log.DebugFormat("No current instance of {0} object available.", progId); - } else if (comE.ErrorCode == CO_E_CLASSSTRING) { - Log.WarnFormat("Unknown progId {0}", progId); - } else { - Log.Warn("Error getting active object for " + progIdAttribute.Value, comE); - } - } catch (Exception e) { - Log.Warn("Error getting active object for " + progIdAttribute.Value, e); - } - } - - if (comObject != null) { - if (comObject is IDispatch) { - COMWrapper wrapper = new COMWrapper(comObject, type, progIdAttribute.Value); - return (T)wrapper.GetTransparentProxy(); - } else { - return (T)comObject; - } - } - return default; - } - - /// /// A simple create instance, doesn't create a wrapper!! /// /// T @@ -188,125 +109,7 @@ namespace GreenshotPlugin.Interop { return default; } - /// - /// Gets or creates a COM object and returns the transparent proxy which intercepts all calls to the object - /// The ComProgId can be a normal ComProgId or a GUID prefixed with "clsid:" - /// - /// Interface which defines the method and properties to intercept - /// Transparent proxy to the real proxy for the object - /// T must be an interface decorated with the attribute. - public static T GetOrCreateInstance() { - Type type = typeof(T); - if (null == type) { - throw new ArgumentNullException(nameof(T)); - } - if (!type.IsInterface) { - throw new ArgumentException("The specified type must be an interface.", nameof(T)); - } - - var progIdAttribute = ComProgIdAttribute.GetAttribute(type); - if (string.IsNullOrEmpty(progIdAttribute?.Value)) { - throw new ArgumentException("The specified type must define a ComProgId attribute.", nameof(T)); - } - - object comObject = null; - Type comType = null; - string progId = progIdAttribute.Value; - Guid guid = Guid.Empty; - - // Convert from clsid to Prog ID, if needed - if (progId.StartsWith("clsid:")) { - guid = new Guid(progId.Substring(6)); - int result = ProgIDFromCLSID(ref guid, out progId); - if (result != 0) { - // Restore progId, as it's overwritten - progId = progIdAttribute.Value; - try { - GetActiveObject(ref guid, IntPtr.Zero, out comObject); - } catch (Exception) { - Log.WarnFormat("Error {0} getting instance for class id {1}", result, progIdAttribute.Value); - } - if (comObject == null) { - Log.WarnFormat("Error {0} getting progId {1}", result, progIdAttribute.Value); - } - } else { - Log.InfoFormat("Mapped {0} to progId {1}", progIdAttribute.Value, progId); - } - } - - if (comObject == null) { - if (!progId.StartsWith("clsid:")) { - try { - comObject = Marshal.GetActiveObject(progId); - } catch (COMException comE) { - if (comE.ErrorCode == MK_E_UNAVAILABLE) { - Log.DebugFormat("No current instance of {0} object available.", progId); - } else if (comE.ErrorCode == CO_E_CLASSSTRING) { - Log.WarnFormat("Unknown progId {0} (application not installed)", progId); - return default; - } else { - Log.Warn("Error getting active object for " + progId, comE); - } - } catch (Exception e) { - Log.Warn("Error getting active object for " + progId, e); - } - } - } - - // Did we get the current instance? If not, try to create a new - if (comObject == null) { - try { - comType = Type.GetTypeFromProgID(progId, true); - } catch (Exception ex) { - if (Guid.Empty != guid) { - comType = Type.GetTypeFromCLSID(guid); - } else { - Log.Warn("Error type for " + progId, ex); - } - } - - if (comType != null) { - try { - comObject = Activator.CreateInstance(comType); - if (comObject != null) { - Log.DebugFormat("Created new instance of {0} object.", progId); - } - } catch (Exception e) { - Log.Warn("Error creating object for " + progId, e); - } - } - } - if (comObject != null) { - if (comObject is IDispatch) { - COMWrapper wrapper = new COMWrapper(comObject, type, progIdAttribute.Value); - return (T)wrapper.GetTransparentProxy(); - } else { - return (T)comObject; - } - } - return default; - } - - /// - /// Wrap a com object as COMWrapper - /// - /// Interface which defines the method and properties to intercept - /// An object to intercept - /// Transparent proxy to the real proxy for the object - public static T Wrap(object comObject) { - Type type = typeof (T); - if (null == comObject) { - throw new ArgumentNullException(nameof(comObject)); - } - if (null == type) { - throw new ArgumentNullException(nameof(T)); - } - - COMWrapper wrapper = new COMWrapper(comObject, type, type.FullName); - return (T)wrapper.GetTransparentProxy(); - } - - /// + /// /// Wrap an object and return the transparent proxy which intercepts all calls to the object /// /// An object to intercept diff --git a/GreenshotPlugin/Interop/IAppVisibility.cs b/GreenshotPlugin/Interop/IAppVisibility.cs index 2feb78b76..58fddc8b8 100644 --- a/GreenshotPlugin/Interop/IAppVisibility.cs +++ b/GreenshotPlugin/Interop/IAppVisibility.cs @@ -35,8 +35,6 @@ namespace GreenshotPlugin.Interop { } public enum MONITOR_APP_VISIBILITY { - MAV_UNKNOWN = 0, // The mode for the monitor is unknown - MAV_NO_APP_VISIBLE = 1, MAV_APP_VISIBLE = 2 } } diff --git a/GreenshotPlugin/UnmanagedHelpers/DWM.cs b/GreenshotPlugin/UnmanagedHelpers/DWM.cs index bc17f3ab2..eed7c71e5 100644 --- a/GreenshotPlugin/UnmanagedHelpers/DWM.cs +++ b/GreenshotPlugin/UnmanagedHelpers/DWM.cs @@ -23,6 +23,7 @@ using System; using System.Drawing; using System.Runtime.InteropServices; using GreenshotPlugin.Core; +using GreenshotPlugin.Core.Enums; using GreenshotPlugin.UnmanagedHelpers.Enums; using GreenshotPlugin.UnmanagedHelpers.Structs; using Microsoft.Win32; @@ -33,8 +34,6 @@ namespace GreenshotPlugin.UnmanagedHelpers { /// Desktop Window Manager helper code /// public static class DWM { - public static readonly uint DWM_EC_DISABLECOMPOSITION = 0; - public static readonly uint DWM_EC_ENABLECOMPOSITION = 1; // DWM [DllImport("dwmapi", SetLastError = true)] @@ -42,9 +41,9 @@ namespace GreenshotPlugin.UnmanagedHelpers { [DllImport("dwmapi", SetLastError = true)] public static extern int DwmUnregisterThumbnail(IntPtr thumb); [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmQueryThumbnailSourceSize(IntPtr thumb, out SIZE size); + public static extern HResult DwmQueryThumbnailSourceSize(IntPtr thumb, out SIZE size); [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmUpdateThumbnailProperties(IntPtr hThumb, ref DWM_THUMBNAIL_PROPERTIES props); + public static extern HResult DwmUpdateThumbnailProperties(IntPtr hThumb, ref DWM_THUMBNAIL_PROPERTIES props); // Deprecated as of Windows 8 Release Preview [DllImport("dwmapi", SetLastError = true)] @@ -53,19 +52,8 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out RECT lpRect, int size); [DllImport("dwmapi", SetLastError = true)] public static extern int DwmGetWindowAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE dwAttribute, out bool pvAttribute, int cbAttribute); - [DllImport("dwmapi", SetLastError = true)] - public static extern int DwmEnableBlurBehindWindow(IntPtr hWnd, ref DWM_BLURBEHIND blurBehind); - [DllImport("dwmapi", SetLastError = true)] - public static extern uint DwmEnableComposition(uint uCompositionAction); - public static void EnableComposition() { - DwmEnableComposition(DWM_EC_ENABLECOMPOSITION); - } - public static void DisableComposition() { - DwmEnableComposition(DWM_EC_DISABLECOMPOSITION); - } - - // Key to ColorizationColor for DWM + // Key to ColorizationColor for DWM private const string COLORIZATION_COLOR_KEY = @"SOFTWARE\Microsoft\Windows\DWM"; /// diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ClassLongIndex.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ClassLongIndex.cs index 23c1d0b6f..d862d0ee8 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ClassLongIndex.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/ClassLongIndex.cs @@ -1,19 +1,32 @@ -using System.Diagnostics.CodeAnalysis; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums { [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ClassLongIndex { - GCL_CBCLSEXTRA = -20, // the size, in bytes, of the extra memory associated with the class. Setting this value does not change the number of extra bytes already allocated. - GCL_CBWNDEXTRA = -18, // the size, in bytes, of the extra window memory associated with each window in the class. Setting this value does not change the number of extra bytes already allocated. For information on how to access this memory, see SetWindowLong. - GCL_HBRBACKGROUND = -10, // a handle to the background brush associated with the class. - GCL_HCURSOR = -12, // a handle to the cursor associated with the class. GCL_HICON = -14, // a handle to the icon associated with the class. GCL_HICONSM = -34, // a handle to the small icon associated with the class. - GCL_HMODULE = -16, // a handle to the module that registered the class. - GCL_MENUNAME = -8, // the address of the menu name string. The string identifies the menu resource associated with the class. - GCL_STYLE = -26, // the window-class style bits. - GCL_WNDPROC = -24, // the address of the window procedure, or a handle representing the address of the window procedure. You must use the CallWindowProc function to call the window procedure. } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_BB.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_BB.cs deleted file mode 100644 index 1541e9143..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_BB.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [Flags] - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum DWM_BB { - Enable = 1, - BlurRegion = 2, - TransitionMaximized = 4 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_BLURBEHIND.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_BLURBEHIND.cs deleted file mode 100644 index 29180d445..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/DWM_BLURBEHIND.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System; -using System.Runtime.InteropServices; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [StructLayout(LayoutKind.Sequential)] - public struct DWM_BLURBEHIND { - public DWM_BB dwFlags; - public bool fEnable; - public IntPtr hRgnBlur; - public bool fTransitionOnMaximized; - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/DesktopAccessRight.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/DesktopAccessRight.cs index abd70937b..a52871fa4 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/DesktopAccessRight.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/DesktopAccessRight.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/DeviceCaps.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/DeviceCaps.cs index 7e40cf277..d83bf89a0 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/DeviceCaps.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/DeviceCaps.cs @@ -1,4 +1,25 @@ -using System.Diagnostics.CodeAnalysis; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums { @@ -8,166 +29,15 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums /// [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DeviceCaps { - /// - /// Device driver version - /// - DRIVERVERSION = 0, - /// - /// Device classification - /// - TECHNOLOGY = 2, - /// - /// Horizontal size in millimeters - /// - HORZSIZE = 4, - /// - /// Vertical size in millimeters - /// - VERTSIZE = 6, - /// - /// Horizontal width in pixels - /// - HORZRES = 8, - /// - /// Vertical height in pixels - /// - VERTRES = 10, - /// - /// Number of bits per pixel - /// - BITSPIXEL = 12, - /// - /// Number of planes - /// - PLANES = 14, - /// - /// Number of brushes the device has - /// - NUMBRUSHES = 16, - /// - /// Number of pens the device has - /// - NUMPENS = 18, - /// - /// Number of markers the device has - /// - NUMMARKERS = 20, - /// - /// Number of fonts the device has - /// - NUMFONTS = 22, - /// - /// Number of colors the device supports - /// - NUMCOLORS = 24, - /// - /// Size required for device descriptor - /// - PDEVICESIZE = 26, - /// - /// Curve capabilities - /// - CURVECAPS = 28, - /// - /// Line capabilities - /// - LINECAPS = 30, - /// - /// Polygonal capabilities - /// - POLYGONALCAPS = 32, - /// - /// Text capabilities - /// - TEXTCAPS = 34, - /// - /// Clipping capabilities - /// - CLIPCAPS = 36, - /// - /// Bitblt capabilities - /// - RASTERCAPS = 38, - /// - /// Length of the X leg - /// - ASPECTX = 40, - /// - /// Length of the Y leg - /// - ASPECTY = 42, - /// - /// Length of the hypotenuse - /// - ASPECTXY = 44, - /// - /// Shading and Blending caps - /// - SHADEBLENDCAPS = 45, - + /// /// Logical pixels inch in X /// LOGPIXELSX = 88, - /// - /// Logical pixels inch in Y - /// - LOGPIXELSY = 90, - - /// - /// Number of entries in physical palette - /// - SIZEPALETTE = 104, - /// - /// Number of reserved entries in palette - /// - NUMRESERVED = 106, - /// - /// Actual color resolution - /// - COLORRES = 108, - - // Printing related DeviceCaps. These replace the appropriate Escapes - /// - /// Physical Width in device units - /// - PHYSICALWIDTH = 110, - /// - /// Physical Height in device units - /// - PHYSICALHEIGHT = 111, - /// - /// Physical Printable Area x margin - /// - PHYSICALOFFSETX = 112, - /// - /// Physical Printable Area y margin - /// - PHYSICALOFFSETY = 113, - /// - /// Scaling factor x - /// - SCALINGFACTORX = 114, - /// - /// Scaling factor y - /// - SCALINGFACTORY = 115, /// /// Current vertical refresh rate of the display device (for displays only) in Hz /// - VREFRESH = 116, - /// - /// Horizontal width of entire desktop in pixels - /// - DESKTOPVERTRES = 117, - /// - /// Vertical height of entire desktop in pixels - /// - DESKTOPHORZRES = 118, - /// - /// Preferred blt alignment - /// - BLTALIGNMENT = 119 + VREFRESH = 116 } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/EventObjects.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/EventObjects.cs index 61d890354..a1981e644 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/EventObjects.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/EventObjects.cs @@ -1,4 +1,25 @@ -using System.Diagnostics.CodeAnalysis; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums { @@ -9,17 +30,6 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums [SuppressMessage("ReSharper", "InconsistentNaming")] public enum EventObjects { - OBJID_ALERT = -10, - OBJID_CARET = -8, - OBJID_CLIENT = -4, - OBJID_CURSOR = -9, - OBJID_HSCROLL = -6, - OBJID_MENU = -3, - OBJID_SIZEGRIP = -7, - OBJID_SOUND = -11, - OBJID_SYSMENU = -1, - OBJID_TITLEBAR = -2, - OBJID_VSCROLL = -5, OBJID_WINDOW = 0 } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs index a8897d5bc..6bc87e3f7 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/ExtendedWindowStyleFlags.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums @@ -6,38 +27,7 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums [Flags] [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ExtendedWindowStyleFlags : uint { - WS_EX_DLGMODALFRAME = 0x00000001, - WS_EX_NOPARENTNOTIFY = 0x00000004, - WS_EX_TOPMOST = 0x00000008, - WS_EX_ACCEPTFILES = 0x00000010, - WS_EX_TRANSPARENT = 0x00000020, - - //#if(WINVER >= 0x0400) - WS_EX_MDICHILD = 0x00000040, WS_EX_TOOLWINDOW = 0x00000080, - WS_EX_WINDOWEDGE = 0x00000100, - WS_EX_CLIENTEDGE = 0x00000200, - WS_EX_CONTEXTHELP = 0x00000400, - - WS_EX_RIGHT = 0x00001000, - WS_EX_LEFT = 0x00000000, - WS_EX_RTLREADING = 0x00002000, - WS_EX_LTRREADING = 0x00000000, - WS_EX_LEFTSCROLLBAR = 0x00004000, - WS_EX_RIGHTSCROLLBAR = 0x00000000, - - WS_EX_CONTROLPARENT = 0x00010000, - WS_EX_STATICEDGE = 0x00020000, - WS_EX_APPWINDOW = 0x00040000, - - //WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE), - //WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST), - - WS_EX_LAYERED = 0x00080000, - WS_EX_NOINHERITLAYOUT = 0x00100000, // Disable inheritence of mirroring by children WS_EX_NOREDIRECTIONBITMAP = 0x00200000, //The window does not render to a redirection surface. This is for windows that do not have visible content or that use mechanisms other than surfaces to provide their visual. - WS_EX_LAYOUTRTL = 0x00400000, // Right to left mirroring - WS_EX_COMPOSITED = 0x02000000, - WS_EX_NOACTIVATE = 0x08000000 // A top-level window created with this style does not become the foreground window when the user clicks it. The system does not bring this window to the foreground when the user minimizes or closes the foreground window. } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/GetWindowCommand.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/GetWindowCommand.cs deleted file mode 100644 index 51ce444ca..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/GetWindowCommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum GetWindowCommand : uint { - GW_HWNDFIRST = 0, - GW_HWNDLAST = 1, - GW_HWNDNEXT = 2, - GW_HWNDPREV = 3, - GW_OWNER = 4, - GW_CHILD = 5, - GW_ENABLEDPOPUP = 6 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ProcessAccessFlags.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ProcessAccessFlags.cs index 79623ec8e..063623e25 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ProcessAccessFlags.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/ProcessAccessFlags.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums @@ -6,15 +27,7 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums [Flags] [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ProcessAccessFlags : uint { - All = 0x001F0FFF, - Terminate = 0x00000001, - CreateThread = 0x00000002, - VMOperation = 0x00000008, VMRead = 0x00000010, - VMWrite = 0x00000020, - DupHandle = 0x00000040, - SetInformation = 0x00000200, QueryInformation = 0x00000400, - Synchronize = 0x00100000 } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/RegionResult.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/RegionResult.cs index fd07afb1d..b9ef9536f 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/RegionResult.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/RegionResult.cs @@ -1,4 +1,25 @@ -using System.Diagnostics.CodeAnalysis; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums { @@ -6,7 +27,5 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums public enum RegionResult { REGION_ERROR = 0, REGION_NULLREGION = 1, - REGION_SIMPLEREGION = 2, - REGION_COMPLEXREGION = 3 } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/SYSCOLOR.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/SYSCOLOR.cs deleted file mode 100644 index 7d6802081..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/SYSCOLOR.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum SYSCOLOR - { - SCROLLBAR = 0, - BACKGROUND = 1, - DESKTOP = 1, - ACTIVECAPTION = 2, - INACTIVECAPTION = 3, - MENU = 4, - WINDOW = 5, - WINDOWFRAME = 6, - MENUTEXT = 7, - WINDOWTEXT = 8, - CAPTIONTEXT = 9, - ACTIVEBORDER = 10, - INACTIVEBORDER = 11, - APPWORKSPACE = 12, - HIGHLIGHT = 13, - HIGHLIGHTTEXT = 14, - BTNFACE = 15, - THREEDFACE = 15, - BTNSHADOW = 16, - THREEDSHADOW = 16, - GRAYTEXT = 17, - BTNTEXT = 18, - INACTIVECAPTIONTEXT = 19, - BTNHIGHLIGHT = 20, - TREEDHIGHLIGHT = 20, - THREEDHILIGHT = 20, - BTNHILIGHT = 20, - THREEDDKSHADOW = 21, - THREEDLIGHT = 22, - INFOTEXT = 23, - INFOBK = 24 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollBarDirection.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollBarDirection.cs deleted file mode 100644 index 3a76ae2ae..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollBarDirection.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum ScrollBarDirection - { - SB_HORZ = 0, - SB_VERT = 1, - SB_CTL = 2, - SB_BOTH = 3 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollInfoMask.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollInfoMask.cs deleted file mode 100644 index e7b0d32b2..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollInfoMask.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum ScrollInfoMask { - SIF_RANGE = 0x1, - SIF_PAGE = 0x2, - SIF_POS = 0x4, - SIF_DISABLENOSCROLL = 0x8, - SIF_TRACKPOS = 0x10, - SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollbarCommand.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollbarCommand.cs deleted file mode 100644 index 66e1392f2..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ScrollbarCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum ScrollbarCommand - { - SB_LINEUP = 0, // Scrolls one line up. - SB_LINEDOWN = 1, // Scrolls one line down. - SB_PAGEUP = 2, // Scrolls one page up. - SB_PAGEDOWN = 3, // Scrolls one page down. - SB_THUMBPOSITION = 4, // The user has dragged the scroll box (thumb) and released the mouse button. The high-order word indicates the position of the scroll box at the end of the drag operation. - SB_THUMBTRACK = 5, // The user is dragging the scroll box. This message is sent repeatedly until the user releases the mouse button. The high-order word indicates the position that the scroll box has been dragged to. - SB_TOP = 6, // Scrolls to the upper left. - SB_BOTTOM = 7, // Scrolls to the lower right. - SB_ENDSCROLL = 8 // Ends scroll. - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs index 0b9cc24ca..e8cbd4390 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/SendMessageTimeoutFlags.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums @@ -9,9 +30,6 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums [Flags] [SuppressMessage("ReSharper", "InconsistentNaming")] public enum SendMessageTimeoutFlags : uint { - SMTO_NORMAL = 0x0, - SMTO_BLOCK = 0x1, - SMTO_ABORTIFHUNG = 0x2, - SMTO_NOTIMEOUTIFNOTHUNG = 0x8 + SMTO_NORMAL = 0x0 } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ShowWindowCommand.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ShowWindowCommand.cs index 0c69e7ea3..7962650d3 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ShowWindowCommand.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/ShowWindowCommand.cs @@ -1,4 +1,25 @@ -using System.Diagnostics.CodeAnalysis; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums { diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/SoundFlags.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/SoundFlags.cs index 67c961381..8104a5dea 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/SoundFlags.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/SoundFlags.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums @@ -10,15 +31,9 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums [SuppressMessage("ReSharper", "InconsistentNaming")] public enum SoundFlags { - SND_SYNC = 0x0000, // play synchronously (default) SND_ASYNC = 0x0001, // play asynchronously - SND_NODEFAULT = 0x0002, // silence (!default) if sound not found SND_MEMORY = 0x0004, // pszSound points to a memory file - SND_LOOP = 0x0008, // loop the sound until next sndPlaySound SND_NOSTOP = 0x0010, // don't stop any currently playing sound SND_NOWAIT = 0x00002000, // don't wait if the driver is busy - SND_ALIAS = 0x00010000, // name is a registry alias - SND_ALIAS_ID = 0x00110000, // alias is a predefined id - SND_FILENAME = 0x00020000, // name is file name } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/SystemMetric.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/SystemMetric.cs deleted file mode 100644 index 371cf90a3..000000000 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/SystemMetric.cs +++ /dev/null @@ -1,392 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace GreenshotPlugin.UnmanagedHelpers.Enums -{ - /// - /// Flags used with the Windows API (User32.dll):GetSystemMetrics(SystemMetric smIndex) - /// - /// This Enum and declaration signature was written by Gabriel T. Sharp - /// ai_productions@verizon.net or osirisgothra@hotmail.com - /// Obtained on pinvoke.net, please contribute your code to support the wiki! - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum SystemMetric - { - /// - /// Width of the screen of the primary display monitor, in pixels. This is the same values obtained by calling GetDeviceCaps as follows: GetDeviceCaps( hdcPrimaryMonitor, HORZRES). - /// - SM_CXSCREEN=0, - /// - /// Height of the screen of the primary display monitor, in pixels. This is the same values obtained by calling GetDeviceCaps as follows: GetDeviceCaps( hdcPrimaryMonitor, VERTRES). - /// - SM_CYSCREEN=1, - /// - /// Width of a horizontal scroll bar, in pixels. - /// - SM_CYVSCROLL=2, - /// - /// Height of a horizontal scroll bar, in pixels. - /// - SM_CXVSCROLL=3, - /// - /// Height of a caption area, in pixels. - /// - SM_CYCAPTION=4, - /// - /// Width of a window border, in pixels. This is equivalent to the SM_CXEDGE value for windows with the 3-D look. - /// - SM_CXBORDER=5, - /// - /// Height of a window border, in pixels. This is equivalent to the SM_CYEDGE value for windows with the 3-D look. - /// - SM_CYBORDER=6, - /// - /// Thickness of the frame around the perimeter of a window that has a caption but is not sizable, in pixels. SM_CXFIXEDFRAME is the height of the horizontal border and SM_CYFIXEDFRAME is the width of the vertical border. - /// - SM_CXDLGFRAME=7, - /// - /// Thickness of the frame around the perimeter of a window that has a caption but is not sizable, in pixels. SM_CXFIXEDFRAME is the height of the horizontal border and SM_CYFIXEDFRAME is the width of the vertical border. - /// - SM_CYDLGFRAME=8, - /// - /// Height of the thumb box in a vertical scroll bar, in pixels - /// - SM_CYVTHUMB=9, - /// - /// Width of the thumb box in a horizontal scroll bar, in pixels. - /// - SM_CXHTHUMB=10, - /// - /// Default width of an icon, in pixels. The LoadIcon function can load only icons with the dimensions specified by SM_CXICON and SM_CYICON - /// - SM_CXICON=11, - /// - /// Default height of an icon, in pixels. The LoadIcon function can load only icons with the dimensions SM_CXICON and SM_CYICON. - /// - SM_CYICON=12, - /// - /// Width of a cursor, in pixels. The system cannot create cursors of other sizes. - /// - SM_CXCURSOR=13, - /// - /// Height of a cursor, in pixels. The system cannot create cursors of other sizes. - /// - SM_CYCURSOR=14, - /// - /// Height of a single-line menu bar, in pixels. - /// - SM_CYMENU=15, - /// - /// Width of the client area for a full-screen window on the primary display monitor, in pixels. To get the coordinates of the portion of the screen not obscured by the system taskbar or by application desktop toolbars, call the SystemParametersInfo function with the SPI_GETWORKAREA value. - /// - SM_CXFULLSCREEN=16, - /// - /// Height of the client area for a full-screen window on the primary display monitor, in pixels. To get the coordinates of the portion of the screen not obscured by the system taskbar or by application desktop toolbars, call the SystemParametersInfo function with the SPI_GETWORKAREA value. - /// - SM_CYFULLSCREEN=17, - /// - /// For double byte character set versions of the system, this is the height of the Kanji window at the bottom of the screen, in pixels - /// - SM_CYKANJIWINDOW=18, - /// - /// Nonzero if a mouse with a wheel is installed; zero otherwise - /// - SM_MOUSEWHEELPRESENT=75, - /// - /// Height of the arrow bitmap on a vertical scroll bar, in pixels. - /// - SM_CYHSCROLL=20, - /// - /// Width of the arrow bitmap on a horizontal scroll bar, in pixels. - /// - SM_CXHSCROLL=21, - /// - /// Nonzero if the debug version of User.exe is installed; zero otherwise. - /// - SM_DEBUG=22, - /// - /// Nonzero if the left and right mouse buttons are reversed; zero otherwise. - /// - SM_SWAPBUTTON=23, - /// - /// Reserved for future use - /// - SM_RESERVED1=24, - /// - /// Reserved for future use - /// - SM_RESERVED2=25, - /// - /// Reserved for future use - /// - SM_RESERVED3=26, - /// - /// Reserved for future use - /// - SM_RESERVED4=27, - /// - /// Minimum width of a window, in pixels. - /// - SM_CXMIN=28, - /// - /// Minimum height of a window, in pixels. - /// - SM_CYMIN=29, - /// - /// Width of a button in a window's caption or title bar, in pixels. - /// - SM_CXSIZE=30, - /// - /// Height of a button in a window's caption or title bar, in pixels. - /// - SM_CYSIZE=31, - /// - /// Thickness of the sizing border around the perimeter of a window that can be resized, in pixels. SM_CXSIZEFRAME is the width of the horizontal border, and SM_CYSIZEFRAME is the height of the vertical border. - /// - SM_CXFRAME=32, - /// - /// Thickness of the sizing border around the perimeter of a window that can be resized, in pixels. SM_CXSIZEFRAME is the width of the horizontal border, and SM_CYSIZEFRAME is the height of the vertical border. - /// - SM_CYFRAME=33, - /// - /// Minimum tracking width of a window, in pixels. The user cannot drag the window frame to a size smaller than these dimensions. A window can override this value by processing the WM_GETMINMAXINFO message. - /// - SM_CXMINTRACK=34, - /// - /// Minimum tracking height of a window, in pixels. The user cannot drag the window frame to a size smaller than these dimensions. A window can override this value by processing the WM_GETMINMAXINFO message - /// - SM_CYMINTRACK=35, - /// - /// Width of the rectangle around the location of a first click in a double-click sequence, in pixels. The second click must occur within the rectangle defined by SM_CXDOUBLECLK and SM_CYDOUBLECLK for the system to consider the two clicks a double-click - /// - SM_CXDOUBLECLK=36, - /// - /// Height of the rectangle around the location of a first click in a double-click sequence, in pixels. The second click must occur within the rectangle defined by SM_CXDOUBLECLK and SM_CYDOUBLECLK for the system to consider the two clicks a double-click. (The two clicks must also occur within a specified time.) - /// - SM_CYDOUBLECLK=37, - /// - /// Width of a grid cell for items in large icon view, in pixels. Each item fits into a rectangle of size SM_CXICONSPACING by SM_CYICONSPACING when arranged. This value is always greater than or equal to SM_CXICON - /// - SM_CXICONSPACING=38, - /// - /// Height of a grid cell for items in large icon view, in pixels. Each item fits into a rectangle of size SM_CXICONSPACING by SM_CYICONSPACING when arranged. This value is always greater than or equal to SM_CYICON. - /// - SM_CYICONSPACING=39, - /// - /// Nonzero if drop-down menus are right-aligned with the corresponding menu-bar item; zero if the menus are left-aligned. - /// - SM_MENUDROPALIGNMENT=40, - /// - /// Nonzero if the Microsoft Windows for Pen computing extensions are installed; zero otherwise. - /// - SM_PENWINDOWS=41, - /// - /// Nonzero if User32.dll supports DBCS; zero otherwise. (WinMe/95/98): Unicode - /// - SM_DBCSENABLED=42, - /// - /// Number of buttons on mouse, or zero if no mouse is installed. - /// - SM_CMOUSEBUTTONS=43, - /// - /// Identical Values Changed After Windows NT 4.0 - /// - SM_CXFIXEDFRAME=SM_CXDLGFRAME, - /// - /// Identical Values Changed After Windows NT 4.0 - /// - SM_CYFIXEDFRAME=SM_CYDLGFRAME, - /// - /// Identical Values Changed After Windows NT 4.0 - /// - SM_CXSIZEFRAME=SM_CXFRAME, - /// - /// Identical Values Changed After Windows NT 4.0 - /// - SM_CYSIZEFRAME=SM_CYFRAME, - /// - /// Nonzero if security is present; zero otherwise. - /// - SM_SECURE=44, - /// - /// Width of a 3-D border, in pixels. This is the 3-D counterpart of SM_CXBORDER - /// - SM_CXEDGE=45, - /// - /// Height of a 3-D border, in pixels. This is the 3-D counterpart of SM_CYBORDER - /// - SM_CYEDGE=46, - /// - /// Width of a grid cell for a minimized window, in pixels. Each minimized window fits into a rectangle this size when arranged. This value is always greater than or equal to SM_CXMINIMIZED. - /// - SM_CXMINSPACING=47, - /// - /// Height of a grid cell for a minimized window, in pixels. Each minimized window fits into a rectangle this size when arranged. This value is always greater than or equal to SM_CYMINIMIZED. - /// - SM_CYMINSPACING=48, - /// - /// Recommended width of a small icon, in pixels. Small icons typically appear in window captions and in small icon view - /// - SM_CXSMICON=49, - /// - /// Recommended height of a small icon, in pixels. Small icons typically appear in window captions and in small icon view. - /// - SM_CYSMICON=50, - /// - /// Height of a small caption, in pixels - /// - SM_CYSMCAPTION=51, - /// - /// Width of small caption buttons, in pixels. - /// - SM_CXSMSIZE=52, - /// - /// Height of small caption buttons, in pixels. - /// - SM_CYSMSIZE=53, - /// - /// Width of menu bar buttons, such as the child window close button used in the multiple document interface, in pixels. - /// - SM_CXMENUSIZE=54, - /// - /// Height of menu bar buttons, such as the child window close button used in the multiple document interface, in pixels. - /// - SM_CYMENUSIZE=55, - /// - /// Flags specifying how the system arranged minimized windows - /// - SM_ARRANGE=56, - /// - /// Width of a minimized window, in pixels. - /// - SM_CXMINIMIZED=57, - /// - /// Height of a minimized window, in pixels. - /// - SM_CYMINIMIZED=58, - /// - /// Default maximum width of a window that has a caption and sizing borders, in pixels. This metric refers to the entire desktop. The user cannot drag the window frame to a size larger than these dimensions. A window can override this value by processing the WM_GETMINMAXINFO message. - /// - SM_CXMAXTRACK=59, - /// - /// Default maximum height of a window that has a caption and sizing borders, in pixels. This metric refers to the entire desktop. The user cannot drag the window frame to a size larger than these dimensions. A window can override this value by processing the WM_GETMINMAXINFO message. - /// - SM_CYMAXTRACK=60, - /// - /// Default width, in pixels, of a maximized top-level window on the primary display monitor. - /// - SM_CXMAXIMIZED=61, - /// - /// Default height, in pixels, of a maximized top-level window on the primary display monitor. - /// - SM_CYMAXIMIZED=62, - /// - /// Least significant bit is set if a network is present; otherwise, it is cleared. The other bits are reserved for future use - /// - SM_NETWORK=63, - /// - /// Value that specifies how the system was started: 0-normal, 1-failsafe, 2-failsafe /w net - /// - SM_CLEANBOOT=67, - /// - /// Width of a rectangle centered on a drag point to allow for limited movement of the mouse pointer before a drag operation begins, in pixels. - /// - SM_CXDRAG=68, - /// - /// Height of a rectangle centered on a drag point to allow for limited movement of the mouse pointer before a drag operation begins. This value is in pixels. It allows the user to click and release the mouse button easily without unintentionally starting a drag operation. - /// - SM_CYDRAG=69, - /// - /// Nonzero if the user requires an application to present information visually in situations where it would otherwise present the information only in audible form; zero otherwise. - /// - SM_SHOWSOUNDS=70, - /// - /// Width of the default menu check-mark bitmap, in pixels. - /// - SM_CXMENUCHECK=71, - /// - /// Height of the default menu check-mark bitmap, in pixels. - /// - SM_CYMENUCHECK=72, - /// - /// Nonzero if the computer has a low-end (slow) processor; zero otherwise - /// - SM_SLOWMACHINE=73, - /// - /// Nonzero if the system is enabled for Hebrew and Arabic languages, zero if not. - /// - SM_MIDEASTENABLED=74, - /// - /// Nonzero if a mouse is installed; zero otherwise. This value is rarely zero, because of support for virtual mice and because some systems detect the presence of the port instead of the presence of a mouse. - /// - SM_MOUSEPRESENT=19, - /// - /// Windows 2000 (v5.0+) Coordinate of the top of the virtual screen - /// - SM_XVIRTUALSCREEN=76, - /// - /// Windows 2000 (v5.0+) Coordinate of the left of the virtual screen - /// - SM_YVIRTUALSCREEN=77, - /// - /// Windows 2000 (v5.0+) Width of the virtual screen - /// - SM_CXVIRTUALSCREEN=78, - /// - /// Windows 2000 (v5.0+) Height of the virtual screen - /// - SM_CYVIRTUALSCREEN=79, - /// - /// Number of display monitors on the desktop - /// - SM_CMONITORS=80, - /// - /// Windows XP (v5.1+) Nonzero if all the display monitors have the same color format, zero otherwise. Note that two displays can have the same bit depth, but different color formats. For example, the red, green, and blue pixels can be encoded with different numbers of bits, or those bits can be located in different places in a pixel's color value. - /// - SM_SAMEDISPLAYFORMAT=81, - /// - /// Windows XP (v5.1+) Nonzero if Input Method Manager/Input Method Editor features are enabled; zero otherwise - /// - SM_IMMENABLED=82, - /// - /// Windows XP (v5.1+) Width of the left and right edges of the focus rectangle drawn by DrawFocusRect. This value is in pixels. - /// - SM_CXFOCUSBORDER=83, - /// - /// Windows XP (v5.1+) Height of the top and bottom edges of the focus rectangle drawn by DrawFocusRect. This value is in pixels. - /// - SM_CYFOCUSBORDER=84, - /// - /// Nonzero if the current operating system is the Windows XP Tablet PC edition, zero if not. - /// - SM_TABLETPC=86, - /// - /// Nonzero if the current operating system is the Windows XP, Media Center Edition, zero if not. - /// - SM_MEDIACENTER=87, - /// - /// Metrics Other - /// - SM_CMETRICS_OTHER=76, - /// - /// Metrics Windows 2000 - /// - SM_CMETRICS_2000=83, - /// - /// Metrics Windows NT - /// - SM_CMETRICS_NT=88, - /// - /// Windows XP (v5.1+) This system metric is used in a Terminal Services environment. If the calling process is associated with a Terminal Services client session, the return value is nonzero. If the calling process is associated with the Terminal Server console session, the return value is zero. The console session is not necessarily the physical console - see WTSGetActiveConsoleSessionId for more information. - /// - SM_REMOTESESSION=0x1000, - /// - /// Windows XP (v5.1+) Nonzero if the current session is shutting down; zero otherwise - /// - SM_SHUTTINGDOWN=0x2000, - /// - /// Windows XP (v5.1+) This system metric is used in a Terminal Services environment. Its value is nonzero if the current session is remotely controlled; zero otherwise - /// - SM_REMOTECONTROL=0x2001 - } -} \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/ThreadAccess.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/ThreadAccess.cs index 14256ad13..fc5495304 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/ThreadAccess.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/ThreadAccess.cs @@ -1,17 +1,30 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; namespace GreenshotPlugin.UnmanagedHelpers.Enums { [Flags] public enum ThreadAccess : int { - TERMINATE = (0x0001), SUSPEND_RESUME = (0x0002), - GET_CONTEXT = (0x0008), - SET_CONTEXT = (0x0010), - SET_INFORMATION = (0x0020), - QUERY_INFORMATION = (0x0040), - SET_THREAD_TOKEN = (0x0080), - IMPERSONATE = (0x0100), - DIRECT_IMPERSONATION = (0x0200) } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/Win32Error.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/Win32Error.cs index cf5d43850..987bc5654 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/Win32Error.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/Win32Error.cs @@ -1,4 +1,25 @@ -namespace GreenshotPlugin.UnmanagedHelpers.Enums +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +namespace GreenshotPlugin.UnmanagedHelpers.Enums { /// /// A Win32 error code. diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/WinEvent.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/WinEvent.cs index 882796a8b..a170af781 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/WinEvent.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/WinEvent.cs @@ -1,4 +1,24 @@ -using System.Diagnostics.CodeAnalysis; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums { @@ -8,47 +28,8 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums /// [SuppressMessage("ReSharper", "InconsistentNaming")] public enum WinEvent : uint { - EVENT_OBJECT_ACCELERATORCHANGE = 32786, EVENT_OBJECT_CREATE = 32768, EVENT_OBJECT_DESTROY = 32769, - EVENT_OBJECT_DEFACTIONCHANGE = 32785, - EVENT_OBJECT_DESCRIPTIONCHANGE = 32781, - EVENT_OBJECT_FOCUS = 32773, - EVENT_OBJECT_HELPCHANGE = 32784, - EVENT_OBJECT_SHOW = 32770, - EVENT_OBJECT_HIDE = 32771, - EVENT_OBJECT_LOCATIONCHANGE = 32779, EVENT_OBJECT_NAMECHANGE = 32780, - EVENT_OBJECT_PARENTCHANGE = 32783, - EVENT_OBJECT_REORDER = 32772, - EVENT_OBJECT_SELECTION = 32774, - EVENT_OBJECT_SELECTIONADD = 32775, - EVENT_OBJECT_SELECTIONREMOVE = 32776, - EVENT_OBJECT_SELECTIONWITHIN = 32777, - EVENT_OBJECT_STATECHANGE = 32778, - EVENT_OBJECT_VALUECHANGE = 32782, - EVENT_SYSTEM_ALERT = 2, - EVENT_SYSTEM_CAPTUREEND = 9, - EVENT_SYSTEM_CAPTURESTART = 8, - EVENT_SYSTEM_CONTEXTHELPEND = 13, - EVENT_SYSTEM_CONTEXTHELPSTART = 12, - EVENT_SYSTEM_DIALOGEND = 17, - EVENT_SYSTEM_DIALOGSTART = 16, - EVENT_SYSTEM_DRAGDROPEND = 15, - EVENT_SYSTEM_DRAGDROPSTART = 14, - EVENT_SYSTEM_FOREGROUND = 3, - EVENT_SYSTEM_MENUEND = 5, - EVENT_SYSTEM_MENUPOPUPEND = 7, - EVENT_SYSTEM_MENUPOPUPSTART = 6, - EVENT_SYSTEM_MENUSTART = 4, - EVENT_SYSTEM_MINIMIZEEND = 23, - EVENT_SYSTEM_MINIMIZESTART = 22, - EVENT_SYSTEM_MOVESIZEEND = 11, - EVENT_SYSTEM_MOVESIZESTART = 10, - EVENT_SYSTEM_SCROLLINGEND = 19, - EVENT_SYSTEM_SCROLLINGSTART = 18, - EVENT_SYSTEM_SOUND = 1, - EVENT_SYSTEM_SWITCHEND = 21, - EVENT_SYSTEM_SWITCHSTART = 20 } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowLongIndex.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowLongIndex.cs index 55622990e..d71a3803e 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowLongIndex.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowLongIndex.cs @@ -1,4 +1,25 @@ -using System.Diagnostics.CodeAnalysis; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums { @@ -6,10 +27,6 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums public enum WindowLongIndex { GWL_EXSTYLE = -20, // Sets a new extended window style. - GWL_HINSTANCE = -6, // Sets a new application instance handle. - GWL_ID = -12, // Sets a new identifier of the child window. The window cannot be a top-level window. GWL_STYLE = -16, // Sets a new window style. - GWL_USERDATA = -21, // Sets the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero. - GWL_WNDPROC = -4 // Sets a new address for the window procedure. You cannot change this attribute if the window does not belong to the same process as the calling thread. } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPlacementFlags.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPlacementFlags.cs index 7c39ab336..ecdc92fe4 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPlacementFlags.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPlacementFlags.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPos.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPos.cs index 2ae2d248d..d343962ae 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPos.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowPos.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.CodeAnalysis; namespace GreenshotPlugin.UnmanagedHelpers.Enums @@ -7,20 +28,8 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums [SuppressMessage("ReSharper", "InconsistentNaming")] public enum WindowPos { - SWP_ASYNCWINDOWPOS = 0x4000, // If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request. - SWP_DEFERERASE = 0x2000, // Prevents generation of the WM_SYNCPAINT message. - SWP_DRAWFRAME = 0x0020, // Draws a frame (defined in the window's class description) around the window. - SWP_FRAMECHANGED = 0x0020, //Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed. - SWP_HIDEWINDOW = 0x0080, // Hides the window. SWP_NOACTIVATE = 0x0010, // Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter). - SWP_NOCOPYBITS = 0x0100, // Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned. SWP_NOMOVE = 0x0002, //Retains the current position (ignores X and Y parameters). - SWP_NOOWNERZORDER = 0x0200, //Does not change the owner window's position in the Z order. - SWP_NOREDRAW = 0x0008, //Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing. - SWP_NOREPOSITION = 0x0200, // Same as the SWP_NOOWNERZORDER flag. - SWP_NOSENDCHANGING = 0x0400, //Prevents the window from receiving the WM_WINDOWPOSCHANGING message. SWP_NOSIZE = 0x0001, // Retains the current size (ignores the cx and cy parameters). - SWP_NOZORDER = 0x0004, // Retains the current Z order (ignores the hWndInsertAfter parameter). - SWP_SHOWWINDOW = 0x0040 //Displays the window. } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowStyleFlags.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowStyleFlags.cs index b0045e3e5..48988c643 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowStyleFlags.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowStyleFlags.cs @@ -29,58 +29,6 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums { [Flags] [SuppressMessage("ReSharper", "InconsistentNaming")] public enum WindowStyleFlags : long { - //WS_OVERLAPPED = 0x00000000, - WS_POPUP = 0x80000000, - WS_CHILD = 0x40000000, - WS_MINIMIZE = 0x20000000, WS_VISIBLE = 0x10000000, - WS_DISABLED = 0x08000000, - WS_CLIPSIBLINGS = 0x04000000, - WS_CLIPCHILDREN = 0x02000000, - WS_MAXIMIZE = 0x01000000, - WS_BORDER = 0x00800000, - WS_DLGFRAME = 0x00400000, - WS_VSCROLL = 0x00200000, - WS_HSCROLL = 0x00100000, - WS_SYSMENU = 0x00080000, - WS_THICKFRAME = 0x00040000, - WS_GROUP = 0x00020000, - WS_TABSTOP = 0x00010000, - - WS_UNK8000 = 0x00008000, - WS_UNK4000 = 0x00004000, - WS_UNK2000 = 0x00002000, - WS_UNK1000 = 0x00001000, - WS_UNK800 = 0x00000800, - WS_UNK400 = 0x00000400, - WS_UNK200 = 0x00000200, - WS_UNK100 = 0x00000100, - WS_UNK80 = 0x00000080, - WS_UNK40 = 0x00000040, - WS_UNK20 = 0x00000020, - WS_UNK10 = 0x00000010, - WS_UNK8 = 0x00000008, - WS_UNK4 = 0x00000004, - WS_UNK2 = 0x00000002, - WS_UNK1 = 0x00000001, - - //WS_MINIMIZEBOX = 0x00020000, - //WS_MAXIMIZEBOX = 0x00010000, - - //WS_CAPTION = WS_BORDER | WS_DLGFRAME, - //WS_TILED = WS_OVERLAPPED, - //WS_ICONIC = WS_MINIMIZE, - //WS_SIZEBOX = WS_THICKFRAME, - //WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW, - - //WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, - //WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU - //WS_CHILDWINDOW = WS_CHILD } - - // See http://msdn.microsoft.com/en-us/library/aa969530(v=vs.85).aspx - - // Get/Set WindowLong Enum See: http://msdn.microsoft.com/en-us/library/ms633591.aspx - - // See: http://msdn.microsoft.com/en-us/library/ms633545.aspx } diff --git a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowsMessages.cs b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowsMessages.cs index c7c4d98b4..8029ccd30 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Enums/WindowsMessages.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Enums/WindowsMessages.cs @@ -9,934 +9,18 @@ namespace GreenshotPlugin.UnmanagedHelpers.Enums [SuppressMessage("ReSharper", "InconsistentNaming")] public enum WindowsMessages : uint { - WM_NULL = 0x0000, - /// - /// Sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. (The message is sent before the function returns.) The window procedure of the new window receives this message after the window is created, but before the window becomes visible. - /// A window receives this message through its WindowProc function. - /// WM_CREATE message - /// - WM_CREATE = 0x0001, - - /// - /// Sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen. - /// This message is sent first to the window being destroyed and then to the child windows (if any) as they are destroyed. During the processing of the message, it can be assumed that all child windows still exist. - /// A window receives this message through its WindowProc function. - /// WM_DESTROY message - /// - WM_DESTROY = 0x0002, - WM_MOVE = 0x0003, - WM_SIZE = 0x0005, - WM_ACTIVATE = 0x0006, - WM_SETFOCUS = 0x0007, - WM_KILLFOCUS = 0x0008, - - /// - /// Sent when an application changes the enabled state of a window. It is sent to the window whose enabled state is changing. This message is sent before the EnableWindow function returns, but after the enabled state (WS_DISABLED style bit) of the window has changed. - /// A window receives this message through its WindowProc function. - /// WM_ENABLE message - /// - WM_ENABLE = 0x000A, - WM_SETREDRAW = 0x000B, - WM_SETTEXT = 0x000C, - WM_GETTEXT = 0x000D, - WM_GETTEXTLENGTH = 0x000E, - - /// - /// The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. The message is sent when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage function when the application obtains a WM_PAINT message by using the GetMessage or PeekMessage function. - /// A window receives this message through its WindowProc function. - /// WM_PAINT message - /// - WM_PAINT = 0x000F, - - WM_CLOSE = 0x0010, - WM_QUERYENDSESSION = 0x0011, - WM_QUIT = 0x0012, - WM_QUERYOPEN = 0x0013, - WM_ERASEBKGND = 0x0014, - WM_SYSCOLORCHANGE = 0x0015, - WM_ENDSESSION = 0x0016, - WM_SHOWWINDOW = 0x0018, - - /// - /// An application sends the WM_WININICHANGE message to all top-level windows after making a change to the WIN.INI file. The SystemParametersInfo function sends this message after an application uses the function to change a setting in WIN.INI. - /// Note: The WM_WININICHANGE message is provided only for compatibility with earlier versions of the system. Applications should use the WM_SETTINGCHANGE message. - /// M_WININICHANGE message - /// - WM_WININICHANGE = 0x001A, - - /// - /// A message that is sent to all top-level windows when the SystemParametersInfo function changes a system-wide setting or when policy settings have changed. - /// Applications should send WM_SETTINGCHANGE to all top-level windows when they make changes to system parameters. (This message cannot be sent directly to a window.) To send the WM_SETTINGCHANGE message to all top-level windows, use the SendMessageTimeout function with the hWnd parameter set to HWND_BROADCAST. - /// A window receives this message through its WindowProc function. - /// WM_SETTINGCHANGE message - /// - WM_SETTINGCHANGE = WM_WININICHANGE, - WM_DEVMODECHANGE = 0x001B, - WM_ACTIVATEAPP = 0x001C, - WM_FONTCHANGE = 0x001D, - WM_TIMECHANGE = 0x001E, - WM_CANCELMODE = 0x001F, - WM_SETCURSOR = 0x0020, WM_MOUSEACTIVATE = 0x0021, - WM_CHILDACTIVATE = 0x0022, - WM_QUEUESYNC = 0x0023, - WM_GETMINMAXINFO = 0x0024, - WM_PAINTICON = 0x0026, - WM_ICONERASEBKGND = 0x0027, - WM_NEXTDLGCTL = 0x0028, - WM_SPOOLERSTATUS = 0x002A, - WM_DRAWITEM = 0x002B, - WM_MEASUREITEM = 0x002C, - WM_DELETEITEM = 0x002D, - WM_VKEYTOITEM = 0x002E, - WM_CHARTOITEM = 0x002F, - WM_SETFONT = 0x0030, - WM_GETFONT = 0x0031, - WM_SETHOTKEY = 0x0032, - WM_GETHOTKEY = 0x0033, - WM_QUERYDRAGICON = 0x0037, - WM_COMPAREITEM = 0x0039, - WM_GETOBJECT = 0x003D, - WM_COMPACTING = 0x0041, - WM_COMMNOTIFY = 0x0044, - WM_WINDOWPOSCHANGING = 0x0046, - WM_WINDOWPOSCHANGED = 0x0047, - WM_POWER = 0x0048, - WM_COPYDATA = 0x004A, - WM_CANCELJOURNAL = 0x004B, - WM_NOTIFY = 0x004E, WM_INPUTLANGCHANGEREQUEST = 0x0050, WM_INPUTLANGCHANGE = 0x0051, - WM_TCARD = 0x0052, - WM_HELP = 0x0053, - WM_USERCHANGED = 0x0054, - WM_NOTIFYFORMAT = 0x0055, - - /// - /// Notifies a window that the user clicked the right mouse button (right-clicked) in the window. - /// See WM_CONTEXTMENU message - /// - /// In case of a notify icon: - /// If a user selects a notify icon's shortcut menu with the keyboard, the Shell now sends the associated application a WM_CONTEXTMENU message. Earlier versions send WM_RBUTTONDOWN and WM_RBUTTONUP messages. - /// See Shell_NotifyIcon function - /// - WM_CONTEXTMENU = 0x007B, - - WM_STYLECHANGING = 0x007C, - WM_STYLECHANGED = 0x007D, - - /// - /// See - /// WM_DISPLAYCHANGE message - /// - WM_DISPLAYCHANGE = 0x007E, + /// /// Sent to a window to retrieve a handle to the large or small icon associated with a window. The system displays the large icon in the ALT+TAB dialog, and the small icon in the window caption. /// A window receives this message through its WindowProc function. /// WM_GETICON message /// WM_GETICON = 0x007F, - WM_SETICON = 0x0080, - - /// - /// Sent prior to the WM_CREATE message when a window is first created. - /// A window receives this message through its WindowProc function. - /// WM_NCCREATE message - /// - WM_NCCREATE = 0x0081, - - WM_NCDESTROY = 0x0082, - WM_NCCALCSIZE = 0x0083, - WM_NCHITTEST = 0x0084, - WM_NCPAINT = 0x0085, - WM_NCACTIVATE = 0x0086, - WM_GETDLGCODE = 0x0087, - WM_SYNCPAINT = 0x0088, - WM_SYNCTASK = 0x0089, - WM_KLUDGEMINRECT = 0x008b, - WM_LPKDRAWSWITCHWND = 0x008c, - - WM_UAHDESTROYWINDOW = 0x0090, - WM_UAHDRAWMENU = 0x0091, - WM_UAHDRAWMENUITEM = 0x0092, - WM_UAHINITMENU = 0x0093, - WM_UAHMEASUREMENUITEM = 0x0094, - WM_UAHNCPAINTMENUPOPUP = 0x0095, - WM_UAHUPDATE = 0x0096, - - /// - /// Posted to a window when the cursor is moved within the nonclient area of the window. - /// This message is posted to the window that contains the cursor. - /// If a window has captured the mouse, this message is not posted. - /// - WM_NCMOUSEMOVE = 0x00A0, - /// - /// Posted when the user presses the left mouse button while the cursor is within the nonclient area of a window. - /// This message is posted to the window that contains the cursor. - /// If a window has captured the mouse, this message is not posted. - /// - WM_NCLBUTTONDOWN = 0x00A1, - /// - /// Posted when the user releases the left mouse button while the cursor is within the nonclient area of a window. - /// This message is posted to the window that contains the cursor. - /// If a window has captured the mouse, this message is not posted. - /// - WM_NCLBUTTONUP = 0x00A2, - WM_NCLBUTTONDBLCLK = 0x00A3, - /// - /// Posted when the user presses the right mouse button while the cursor is within the nonclient area of a window. - /// This message is posted to the window that contains the cursor. - /// If a window has captured the mouse, this message is not posted. - /// - WM_NCRBUTTONDOWN = 0x00A4, - /// - /// Posted when the user releases the right mouse button while the cursor is within the nonclient area of a window. - /// This message is posted to the window that contains the cursor. - /// If a window has captured the mouse, this message is not posted. - /// - WM_NCRBUTTONUP = 0x00A5, - WM_NCRBUTTONDBLCLK = 0x00A6, - /// - /// Posted when the user presses the middle mouse button while the cursor is within the nonclient area of a window. - /// This message is posted to the window that contains the cursor. - /// If a window has captured the mouse, this message is not posted. - /// - WM_NCMBUTTONDOWN = 0x00A7, - /// - /// Posted when the user releases the middle mouse button while the cursor is within the nonclient area of a window. - /// This message is posted to the window that contains the cursor. - /// If a window has captured the mouse, this message is not posted. - /// - WM_NCMBUTTONUP = 0x00A8, - WM_NCMBUTTONDBLCLK = 0x00A9, - WM_NCXBUTTONDOWN = 0x00AB, - WM_NCXBUTTONUP = 0x00AC, - WM_NCXBUTTONDBLCLK = 0x00AD, - WM_NCUAHDRAWCAPTION = 0x00ae, - WM_NCUAHDRAWFRAME = 0x00af, - - // Edit controls - EM_GETSEL = 0x00b0, - EM_SETSEL = 0x00b1, - EM_GETRECT = 0x00b2, - EM_SETRECT = 0x00b3, - EM_SETRECTNP = 0x00b4, - EM_SCROLL = 0x00b5, - EM_LINESCROLL = 0x00b6, - EM_SCROLLCARET = 0x00b7, - EM_GETMODIFY = 0x00b8, - EM_SETMODIFY = 0x00b9, - EM_GETLINECOUNT = 0x00ba, - EM_LINEINDEX = 0x00bb, - EM_SETHANDLE = 0x00bc, - EM_GETHANDLE = 0x00bd, - EM_GETTHUMB = 0x00be, - EM_LINELENGTH = 0x00c1, - EM_REPLACESEL = 0x00c2, - EM_SETFONT = 0x00c3, - EM_GETLINE = 0x00c4, - EM_LIMITTEXT = 0x00c5, - EM_CANUNDO = 0x00c6, - EM_UNDO = 0x00c7, - EM_FMTLINES = 0x00c8, - EM_LINEFROMCHAR = 0x00c9, - EM_SETWORDBREAK = 0x00ca, - EM_SETTABSTOPS = 0x00cb, - EM_SETPASSWORDCHAR = 0x00cc, - EM_EMPTYUNDOBUFFER = 0x00cd, - EM_GETFIRSTVISIBLELINE = 0x00ce, - EM_SETREADONLY = 0x00cf, - EM_SETWORDBREAKPROC = 0x00d0, - EM_GETWORDBREAKPROC = 0x00d1, - EM_GETPASSWORDCHAR = 0x00d2, - EM_SETMARGINS = 0x00d3, - EM_GETMARGINS = 0x00d4, - EM_GETLIMITTEXT = 0x00d5, - EM_POSFROMCHAR = 0x00d6, - EM_CHARFROMPOS = 0x00d7, - EM_SETIMESTATUS = 0x00d8, - EM_GETIMESTATUS = 0x00d9, - EM_MSGMAX = 0x00da, - - /// - /// Sent to the window that registered to receive raw input. - /// A window receives this message through its WindowProc function. - /// wParam - This parameter can be one of the following values: - /// GIDC_ARRIVAL (1) : A new device has been added to the system. - /// GIDC_REMOVAL (2) : A device has been removed from the system. - /// lParam - The handle to the raw input device. Call GetRawInputDeviceInfo to get more information regarding the device. - /// Return value - /// If an application processes this message, it should return zero. - /// - WM_INPUT_DEVICE_CHANGE = 0x00FE, - - /// - /// Sent to the window that is getting raw input. - /// Raw input is available only when the application calls RegisterRawInputDevices with valid device specifications - /// A window receives this message through its WindowProc function. - /// wParam - The input code. This parameter can be one of the following values: - /// RIM_INPUT (0) - Input occurred while the application was in the foreground. The application must call DefWindowProc so the system can perform cleanup. - /// RIM_INPUTSINK (1) - Input occurred while the application was not in the foreground. The application must call DefWindowProc so the system can perform the cleanup. - /// lParam - A handle to the RAWINPUT structure that contains the raw input from the device. - /// Return value - /// If an application processes this message, it should return zero. - /// - WM_INPUT = 0x00FF, - - WM_KEYFIRST = 0x0100, - WM_KEYDOWN = 0x0100, - WM_KEYUP = 0x0101, WM_CHAR = 0x0102, - WM_DEADCHAR = 0x0103, - WM_SYSKEYDOWN = 0x0104, - WM_SYSKEYUP = 0x0105, - WM_SYSCHAR = 0x0106, - WM_SYSDEADCHAR = 0x0107, - WM_UNICHAR = 0x0109, - WM_KEYLAST = 0x0109, - - WM_IME_STARTCOMPOSITION = 0x010D, - WM_IME_ENDCOMPOSITION = 0x010E, - WM_IME_COMPOSITION = 0x010F, - WM_IME_KEYLAST = 0x010F, - - WM_INITDIALOG = 0x0110, - WM_COMMAND = 0x0111, - WM_SYSCOMMAND = 0x0112, - WM_TIMER = 0x0113, - WM_HSCROLL = 0x0114, - WM_VSCROLL = 0x0115, - WM_INITMENU = 0x0116, - WM_INITMENUPOPUP = 0x0117, - WM_MENUSELECT = 0x011F, - WM_MENUCHAR = 0x0120, - WM_ENTERIDLE = 0x0121, - WM_MENURBUTTONUP = 0x0122, - WM_MENUDRAG = 0x0123, - WM_MENUGETOBJECT = 0x0124, - WM_UNINITMENUPOPUP = 0x0125, - WM_MENUCOMMAND = 0x0126, - - WM_CHANGEUISTATE = 0x0127, - WM_UPDATEUISTATE = 0x0128, - WM_QUERYUISTATE = 0x0129, - - WM_CTLCOLORMSGBOX = 0x0132, - WM_CTLCOLOREDIT = 0x0133, - WM_CTLCOLORLISTBOX = 0x0134, - WM_CTLCOLORBTN = 0x0135, - WM_CTLCOLORDLG = 0x0136, - WM_CTLCOLORSCROLLBAR = 0x0137, - WM_CTLCOLORSTATIC = 0x0138, - - // Combo Box - CB_GETEDITSEL = 0x00140, - CB_LIMITTEXT = 0x00141, - CB_SETEDITSEL = 0x00142, - CB_ADDSTRING = 0x00143, - CB_DELETESTRING = 0x00144, - CB_DIR = 0x00145, - CB_GETCOUNT = 0x00146, - CB_GETCURSEL = 0x00147, - CB_GETLBTEXT = 0x00148, - CB_GETLBTEXTLEN = 0x00149, - CB_INSERTSTRING = 0x0014a, - CB_RESETCONTENT = 0x0014b, - CB_FINDSTRING = 0x0014c, - CB_SELECTSTRING = 0x0014d, - CB_SETCURSEL = 0x0014e, - CB_SHOWDROPDOWN = 0x0014f, - CB_GETITEMDATA = 0x00150, - CB_SETITEMDATA = 0x00151, - CB_GETDROPPEDCONTROLRECT = 0x00152, - CB_SETITEMHEIGHT = 0x00153, - CB_GETITEMHEIGHT = 0x00154, - CB_SETEXTENDEDUI = 0x00155, - CB_GETEXTENDEDUI = 0x00156, - CB_GETDROPPEDSTATE = 0x00157, - CB_FINDSTRINGEXACT = 0x00158, - CB_SETLOCALE = 0x00159, - CB_GETLOCALE = 0x0015a, - CB_GETTOPINDEX = 0x0015b, - CB_SETTOPINDEX = 0x0015c, - CB_GETHORIZONTALEXTENT = 0x0015d, - CB_SETHORIZONTALEXTENT = 0x0015e, - CB_GETDROPPEDWIDTH = 0x0015f, - CB_SETDROPPEDWIDTH = 0x00160, - CB_INITSTORAGE = 0x00161, - CB_MSGMAX_OLD = 0x00162, - CB_MULTIPLEADDSTRING = 0x00163, - CB_GETCOMBOBOXINFO = 0x00164, - CB_MSGMAX = 0x00165, - - - LB_ADDSTRING = 0x00180, - LB_INSERTSTRING = 0x00181, - LB_DELETESTRING = 0x00182, - LB_SELITEMRANGEEX = 0x00183, - LB_RESETCONTENT = 0x00184, - LB_SETSEL = 0x00185, - LB_SETCURSEL = 0x00186, - LB_GETSEL = 0x00187, - LB_GETCURSEL = 0x00188, - LB_GETTEXT = 0x00189, - LB_GETTEXTLEN = 0x0018a, - LB_GETCOUNT = 0x0018b, - LB_SELECTSTRING = 0x0018c, - LB_DIR = 0x0018d, - LB_GETTOPINDEX = 0x0018e, - LB_FINDSTRING = 0x0018f, - LB_GETSELCOUNT = 0x00190, - LB_GETSELITEMS = 0x00191, - LB_SETTABSTOPS = 0x00192, - LB_GETHORIZONTALEXTENT = 0x00193, - LB_SETHORIZONTALEXTENT = 0x00194, - LB_SETCOLUMNWIDTH = 0x00195, - LB_ADDFILE = 0x00196, - LB_SETTOPINDEX = 0x00197, - LB_GETITEMRECT = 0x00198, - LB_GETITEMDATA = 0x00199, - LB_SETITEMDATA = 0x0019a, - LB_SELITEMRANGE = 0x0019b, - LB_SETANCHORINDEX = 0x0019c, - LB_GETANCHORINDEX = 0x0019d, - LB_SETCARETINDEX = 0x0019e, - LB_GETCARETINDEX = 0x0019f, - LB_SETITEMHEIGHT = 0x001a0, - LB_GETITEMHEIGHT = 0x001a1, - LB_FINDSTRINGEXACT = 0x001a2, - LBCB_CARETON = 0x001a3, - LBCB_CARETOFF = 0x001a4, - LB_SETLOCALE = 0x001a5, - LB_GETLOCALE = 0x001a6, - LB_SETCOUNT = 0x001a7, - LB_INITSTORAGE = 0x001a8, - LB_ITEMFROMPOINT = 0x001a9, - LB_INSERTSTRINGUPPER = 0x001aa, - LB_INSERTSTRINGLOWER = 0x001ab, - LB_ADDSTRINGUPPER = 0x001ac, - LB_ADDSTRINGLOWER = 0x001ad, - LBCB_STARTTRACK = 0x001ae, - LBCB_ENDTRACK = 0x001af, - LB_MSGMAX_OLD = 0x001b0, - LB_MULTIPLEADDSTRING = 0x001b1, - LB_GETLISTBOXINFO = 0x001b2, - LB_MSGMAX = 0x001b3, - - MN_FIRST = 0x01e0, - WM_GETHMENU = 0x01E1, - - /// - /// Defines the start of the mouse related messages - /// - WM_MOUSEFIRST = 0x0200, - - /// - /// Posted to a window when the cursor moves. - /// If the mouse is not captured, the message is posted to the window that contains the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_MOUSEMOVE message - /// - WM_MOUSEMOVE = 0x0200, - - /// - /// Posted when the user presses the left mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_LBUTTONDOWN message - /// - WM_LBUTTONDOWN = 0x0201, - - /// - /// Posted when the user releases the left mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_LBUTTONUP message - /// - WM_LBUTTONUP = 0x0202, - - /// - /// Posted when the user double-clicks the left mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_LBUTTONDBLCLK message - /// - WM_LBUTTONDBLCLK = 0x0203, - - /// - /// Posted when the user presses the right mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_RBUTTONDOWN message - /// - WM_RBUTTONDOWN = 0x0204, - - /// - /// Posted when the user releases the right mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_RBUTTONUP message - /// - WM_RBUTTONUP = 0x0205, - - /// - /// Posted when the user double-clicks the right mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_RBUTTONDBLCLK message - /// - WM_RBUTTONDBLCLK = 0x0206, - - /// - /// Posted when the user presses the middle mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_MBUTTONDOWN message - /// - WM_MBUTTONDOWN = 0x0207, - - /// - /// Posted when the user releases the middle mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_MBUTTONUP message - /// - WM_MBUTTONUP = 0x0208, - - /// - /// Posted when the user double-clicks the middle mouse button while the cursor is in the client area of a window. - /// If the mouse is not captured, the message is posted to the window beneath the cursor. - /// Otherwise, the message is posted to the window that has captured the mouse. - /// - /// See WM_MBUTTONDBLCLK message - /// - WM_MBUTTONDBLCLK = 0x0209, - - WM_MOUSEWHEEL = 0x020A, - WM_XBUTTONDOWN = 0x020B, - WM_XBUTTONUP = 0x020C, - WM_XBUTTONDBLCLK = 0x020D, - WM_MOUSEHWHEEL = 0x020E, - - WM_PARENTNOTIFY = 0x0210, - WM_ENTERMENULOOP = 0x0211, - WM_EXITMENULOOP = 0x0212, - - WM_NEXTMENU = 0x0213, - WM_SIZING = 0x0214, - WM_CAPTURECHANGED = 0x0215, - WM_MOVING = 0x0216, - - WM_POWERBROADCAST = 0x0218, - - /// - /// See WM_DEVICECHANGE message - /// Notifies an application of a change to the hardware configuration of a device or the computer. - /// wParam - The event that has occurred (DeviceChangeEvent) - /// lParam - A pointer to a structure that contains event-specific data. Its format depends on the value of the wParam parameter. For more information, refer to the documentation for each event - /// - /// Return TRUE to grant the request, return BROADCAST_QUERY_DENY to deny the request. - /// - WM_DEVICECHANGE = 0x0219, - - WM_MDICREATE = 0x0220, - WM_MDIDESTROY = 0x0221, - WM_MDIACTIVATE = 0x0222, - WM_MDIRESTORE = 0x0223, - WM_MDINEXT = 0x0224, - WM_MDIMAXIMIZE = 0x0225, - WM_MDITILE = 0x0226, - WM_MDICASCADE = 0x0227, - WM_MDIICONARRANGE = 0x0228, - WM_MDIGETACTIVE = 0x0229, - - - WM_MDISETMENU = 0x0230, - WM_ENTERSIZEMOVE = 0x0231, - WM_EXITSIZEMOVE = 0x0232, - WM_DROPFILES = 0x0233, - WM_MDIREFRESHMENU = 0x0234, - - WM_IME_REPORT = 0x0280, - WM_IME_SETCONTEXT = 0x0281, - WM_IME_NOTIFY = 0x0282, - WM_IME_CONTROL = 0x0283, - WM_IME_COMPOSITIONFULL = 0x0284, - WM_IME_SELECT = 0x0285, - WM_IME_CHAR = 0x0286, - WM_IME_REQUEST = 0x0288, - WM_IME_KEYDOWN = 0x0290, - WM_IME_KEYUP = 0x0291, - - WM_NCMOUSEHOVER = 0x02A0, - WM_MOUSEHOVER = 0x02A1, - WM_NCMOUSELEAVE = 0x02A2, - WM_MOUSELEAVE = 0x02A3, - - WM_WTSSESSION_CHANGE = 0x02B1, - - WM_TABLET_FIRST = 0x02C0, - WM_POINTERDEVICEADDED = 0x02c8, - WM_POINTERDEVICEDELETED = 0x02c9, - WM_FLICK = 0x02cb, - WM_FLICKINTERNAL = 0x02cd, - WM_BRIGHTNESSCHANGED = 0x02ce, - WM_TABLET_LAST = 0x02DF, - - /// - /// Sent when the effective dots per inch (dpi) for a window has changed. The DPI is the scale factor for a window. There are multiple events that can cause the DPI to change. The following list indicates the possible causes for the change in DPI. - /// * The window is moved to a new monitor that has a different DPI. - /// * The DPI of the monitor hosting the window changes. - /// The current DPI for a window always equals the last DPI sent by WM_DPICHANGED. - /// This is the scale factor that the window should be scaling to for threads that are aware of DPI changes. - /// See WM_DPICHANGED message - /// - WM_DPICHANGED = 0x02E0, - - /// - /// For Per Monitor v2 top-level windows, this message is sent to all HWNDs in the child HWDN tree of the window that is undergoing a DPI change. - /// This message occurs before the top-level window receives WM_DPICHANGED, and traverses the child tree from the bottom up. - /// See WM_DPICHANGED_BEFOREPARENT message - /// - WM_DPICHANGED_BEFOREPARENT = 0x02E2, - - /// - /// For Per Monitor v2 top-level windows, this message is sent to all HWNDs in the child HWDN tree of the window that is undergoing a DPI change. - /// This message occurs after the top-level window receives WM_DPICHANGED, and traverses the child tree from the top down. - /// See WM_DPICHANGED_AFTERPARENT message - /// - WM_DPICHANGED_AFTERPARENT = 0x02E3, - - /// - /// This message tells the operating system that the window will be sized to dimensions other than the default. - /// This message is sent to top-level windows with a DPI_AWARENESS_CONTEXT of Per Monitor v2 before a WM_DPICHANGED message is sent, and allows the window to compute its desired size for the pending DPI change. - /// As linear DPI scaling is the default behavior, this is only useful in scenarios where the window wants to scale non-linearly. - /// If the application responds to this message, the resulting size will be the candidate rectangle send to WM_DPICHANGED. - /// Use this message to alter the size of the rect that is provided with WM_DPICHANGED. - /// - /// wParam - /// The WPARAM contains a DPI value. The scaled window size that the application would set needs to be computed as if the window were to switch to this DPI. - /// - /// lParam - /// The LPARAM is an in/out pointer to a SIZE struct. The _In_ value in the LPARAM is the pending size of the window after a user-initiated move or a call to SetWindowPos. If the window is being resized, this size is not necessarily the same as the window's current size at the time this message is received. - /// - /// The _Out_ value in the LPARAM should be written to by the application to specify the desired scaled window size corresponding to the provided DPI value in the WPARAM. - /// - /// The function returns a BOOL. Returning TRUE indicates that a new size has been computed. Returning FALSE indicates that the message will not be handled, and the default linear DPI scaling will apply to the window. - /// - /// Remarks: - /// This message is only sent to top-level windows which have a DPI awareness context of Per Monitor v2. - /// This event is necessary to facilitate graceful non-linear scaling, and ensures that the windows's position remains constant in relationship to the cursor and when moving back and forth across monitors. - /// There is no specific default handling of this message in DefWindowProc. As for all messages it does not explicitly handle, DefWindowProc will return zero for this message. As noted above, this return tells the system to use the default linear behavior. - /// See WM_GETDPISCALEDSIZE message - /// - WM_GETDPISCALEDSIZE = 0x02E4, - - /// - /// An application sends a WM_CUT message to an edit control or combo box to delete (cut) the current selection, if any, in the edit control and copy the deleted text to the clipboard in CF_TEXT format. - /// WM_CUT message - /// - WM_CUT = 0x0300, - - /// - /// An application sends the WM_COPY message to an edit control or combo box to copy the current selection to the clipboard in CF_TEXT format. - /// WM_COPY message - /// - WM_COPY = 0x0301, - - /// - /// An application sends a WM_PASTE message to an edit control or combo box to copy the current content of the clipboard to the edit control at the current caret position. Data is inserted only if the clipboard contains data in CF_TEXT format. - /// WM_PASTE message - /// - WM_PASTE = 0x0302, - - /// - /// An application sends a WM_CLEAR message to an edit control or combo box to delete (clear) the current selection, if any, from the edit control. - /// WM_CLEAR message - /// - WM_CLEAR = 0x0303, - - /// - /// An application sends a WM_UNDO message to an edit control to undo the last operation. When this message is sent to an edit control, the previously deleted text is restored or the previously added text is deleted. - /// WM_UNDO message - /// - WM_UNDO = 0x0304, - - /// - /// Sent to the clipboard owner if it has delayed rendering a specific clipboard format and if an application has requested data in that format. The clipboard owner must render data in the specified format and place it on the clipboard by calling the SetClipboardData function. - /// WM_RENDERFORMAT message - /// - WM_RENDERFORMAT = 0x0305, - - /// - /// Sent to the clipboard owner before it is destroyed, if the clipboard owner has delayed rendering one or more clipboard formats. For the content of the clipboard to remain available to other applications, the clipboard owner must render data in all the formats it is capable of generating, and place the data on the clipboard by calling the SetClipboardData function. - /// A window receives this message through its WindowProc function. - /// WM_RENDERALLFORMATS message - /// - WM_RENDERALLFORMATS = 0x0306, - - /// - /// Sent to the clipboard owner when a call to the EmptyClipboard function empties the clipboard. - ///A window receives this message through its WindowProc function. - /// WM_DESTROYCLIPBOARD message - /// - WM_DESTROYCLIPBOARD = 0x0307, - - /// - /// Sent to the first window in the clipboard viewer chain when the content of the clipboard changes. This enables a clipboard viewer window to display the new content of the clipboard. - /// A window receives this message through its WindowProc function. - /// WM_DRAWCLIPBOARD message - /// - WM_DRAWCLIPBOARD = 0x0308, - - /// - /// Sent to the clipboard owner by a clipboard viewer window when the clipboard contains data in the CF_OWNERDISPLAY format and the clipboard viewer's client area needs repainting. - /// WM_PAINTCLIPBOARD message - /// - WM_PAINTCLIPBOARD = 0x0309, - - /// - /// Sent to the clipboard owner by a clipboard viewer window when the clipboard contains data in the CF_OWNERDISPLAY format and an event occurs in the clipboard viewer's vertical scroll bar. The owner should scroll the clipboard image and update the scroll bar values. - /// WM_VSCROLLCLIPBOARD message - /// - WM_VSCROLLCLIPBOARD = 0x030A, - - /// - /// Sent to the clipboard owner by a clipboard viewer window when the clipboard contains data in the CF_OWNERDISPLAY format and the clipboard viewer's client area has changed size. - /// WM_SIZECLIPBOARD message - /// - WM_SIZECLIPBOARD = 0x030B, - - /// - /// Sent to the clipboard owner by a clipboard viewer window to request the name of a CF_OWNERDISPLAY clipboard format. - /// A window receives this message through its WindowProc function. - /// See WM_ASKCBFORMATNAME message - /// - WM_ASKCBFORMATNAME = 0x030C, - - /// - /// Sent to the first window in the clipboard viewer chain when a window is being removed from the chain. - /// A window receives this message through its WindowProc function. - /// See WM_CHANGECBCHAIN message - /// - WM_CHANGECBCHAIN = 0x030D, - - /// - /// Sent to the clipboard owner by a clipboard viewer window. This occurs when the clipboard contains data in the CF_OWNERDISPLAY format and an event occurs in the clipboard viewer's horizontal scroll bar. The owner should scroll the clipboard image and update the scroll bar values. - /// See WM_HSCROLLCLIPBOARD message - /// - WM_HSCROLLCLIPBOARD = 0x030E, - - WM_QUERYNEWPALETTE = 0x030F, - WM_PALETTEISCHANGING = 0x0310, - - - WM_PALETTECHANGED = 0x0311, - WM_HOTKEY = 0x0312, - - WM_SYSMENU = 0x313, - WM_HOOKMSG = 0x314, - WM_EXITPROCESS = 0x315, - WM_WAKETHREAD = 0x316, - - /// - /// The WM_PRINT message is sent to a window to request that it draw itself in the specified device context, most commonly in a printer device context. - ///A window receives this message through its WindowProc function. - /// WM_PRINT message - /// - WM_PRINT = 0x0317, - - /// - /// The WM_PRINTCLIENT message is sent to a window to request that it draw its client area in the specified device context, most commonly in a printer device context. - /// Unlike WM_PRINT, WM_PRINTCLIENT is not processed by DefWindowProc. A window should process the WM_PRINTCLIENT message through an application-defined WindowProc function for it to be used properly. - /// WM_PRINTCLIENT message - /// - WM_PRINTCLIENT = 0x0318, - - /// - /// Notifies a window that the user generated an application command event, for example, by clicking an application command button using the mouse or typing an application command key on the keyboard. - /// WM_APPCOMMAND message - /// - WM_APPCOMMAND = 0x0319, - - WM_THEMECHANGED = 0x031A, - WM_UAHINIT = 0x031b, - WM_DESKTOPNOTIFY = 0x031c, - - /// - /// See WM_CLIPBOARDUPDATE message - /// - WM_CLIPBOARDUPDATE = 0x031D, - - WM_DWMCOMPOSITIONCHANGED = 0x031E, - WM_DWMNCRENDERINGCHANGED = 0x031F, - WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320, - WM_DWMWINDOWMAXIMIZEDCHANGE = 0x0321, - - WM_DWMEXILEFRAME = 0x0322, - WM_DWMSENDICONICTHUMBNAIL = 0x0323, - WM_MAGNIFICATION_STARTED = 0x0324, - WM_MAGNIFICATION_ENDED = 0x0325, - WM_DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326, - WM_DWMTHUMBNAILSIZECHANGED = 0x0327, - WM_MAGNIFICATION_OUTPUT = 0x0328, - WM_BSDRDATA = 0x0329, - WM_DWMTRANSITIONSTATECHANGED = 0x032a, - WM_KEYBOARDCORRECTIONCALLOUT = 0x032c, - WM_KEYBOARDCORRECTIONACTION = 0x032d, - WM_UIACTION = 0x032e, - WM_ROUTED_UI_EVENT = 0x032f, - WM_MEASURECONTROL = 0x0330, - WM_GETACTIONTEXT = 0x0331, - WM_FORWARDKEYDOWN = 0x0333, - WM_FORWARDKEYUP = 0x0334, - - - WM_GETTITLEBARINFOEX = 0x033F, - WM_NOTIFYWOW = 0x0340, - WM_HANDHELDFIRST = 0x0358, - WM_HANDHELDLAST = 0x035F, - - WM_AFXFIRST = 0x0360, - WM_AFXLAST = 0x037F, - - WM_PENWINFIRST = 0x0380, - WM_PENWINLAST = 0x038F, - - /// - /// See MM_JOY1MOVE message - /// - MM_JOY1MOVE = 0x03A0, - MM_JOY2MOVE = 0x03A1, - MM_JOY1ZMOVE = 0x03A2, - MM_JOY2ZMOVE = 0x03A3, - MM_JOY1BUTTONDOWN = 0x03B5, - MM_JOY2BUTTONDOWN = 0x03B6, - MM_JOY1BUTTONUP = 0x03B7, - MM_JOY2BUTTONUP = 0x03B8, - /// - /// See MM_MCINOTIFY message - /// - MM_MCINOTIFY = 0x3B9, - MM_WOM_OPEN = 0x03BB, - MM_WOM_CLOSE = 0x03BC, - MM_WOM_DONE = 0x03BD, - MM_WIM_OPEN = 0x03BE, - MM_WIM_CLOSE = 0x03BF, - MM_WIM_DATA = 0x03C0, - MM_MIM_OPEN = 0x03C1, - MM_MIM_CLOSE = 0x03C2, - MM_MIM_DATA = 0x03C3, - MM_MIM_LONGDATA = 0x03C4, - MM_MIM_ERROR = 0x03C5, - MM_MIM_LONGERROR = 0x03C6, - MM_MOM_OPEN = 0x03C7, - MM_MOM_CLOSE = 0x03C8, - MM_MOM_DONE = 0x03C9, - MM_DRVM_OPEN = 0x03D0, - MM_DRVM_CLOSE = 0x03D1, - MM_DRVM_DATA = 0x03D2, - MM_DRVM_ERROR = 0x03D3, - MM_STREAM_OPEN = 0x3D4, - MM_STREAM_CLOSE = 0x3D5, - MM_STREAM_DONE = 0x3D6, - MM_STREAM_ERROR = 0x3D7, - MM_MOM_POSITIONCB = 0x03CA, - MM_MCISIGNAL = 0x03CB, - MM_MIM_MOREDATA = 0x03CC, - MM_MIXM_LINE_CHANGE = 0x03D0, - MM_MIXM_CONTROL_CHANGE = 0x03D1, - - /// - /// Used to define private messages for use by private window classes, usually of the form WM_USER+x, where x is an integer value. - /// - WM_USER = 0x0400, - - /// - /// This message is only send when using NOTIFYICON_VERSION_4, the Shell now sends the associated application an NIN_SELECT notification. - /// Send when a notify icon is activated with mouse or ENTER key. - /// Earlier versions send WM_RBUTTONDOWN and WM_RBUTTONUP messages. - /// - /// See Shell_NotifyIcon function - /// - NIN_SELECT = WM_USER, - - /// - /// This message is only send when using NOTIFYICON_VERSION_4, the Shell now sends the associated application an NIN_SELECT notification. - /// Send when a notify icon is activated with SPACEBAR or ENTER key. - /// Earlier versions send WM_RBUTTONDOWN and WM_RBUTTONUP messages. - /// - /// See Shell_NotifyIcon function - /// - NIN_KEYSELECT = WM_USER + 1, - - /// - /// See Shell_NotifyIcon function - /// - /// Sent when the balloon is shown (balloons are queued). - /// - NIN_BALLOONSHOW = WM_USER + 2, - - /// - /// See Shell_NotifyIcon function - /// - /// Sent when the balloon disappears. For example, when the icon is deleted. - /// This message is not sent if the balloon is dismissed because of a timeout or if the user clicks the mouse. - /// - /// As of Windows 7, NIN_BALLOONHIDE is also sent when a notification with the NIIF_RESPECT_QUIET_TIME flag set attempts to display during quiet time (a user's first hour on a new computer). - /// In that case, the balloon is never displayed at all. - /// - NIN_BALLOONHIDE = WM_USER + 3, - - /// - /// See Shell_NotifyIcon function - /// - /// Sent when the balloon is dismissed because of a timeout. - /// - NIN_BALLOONTIMEOUT = WM_USER + 4, - - /// - /// See Shell_NotifyIcon function - /// - /// Sent when the balloon is dismissed because the user clicked the mouse. - /// - NIN_BALLOONUSERCLICK = WM_USER + 5, - - /// - /// See Shell_NotifyIcon function - /// - /// Sent when the user hovers the cursor over an icon to indicate that the richer pop-up UI should be used in place of a standard textual tooltip. - /// - NIN_POPUPOPEN = WM_USER + 6, - - /// - /// See Shell_NotifyIcon function - /// - /// Sent when a cursor no longer hovers over an icon to indicate that the rich pop-up UI should be closed. - /// - NIN_POPUPCLOSE = WM_USER + 7, - - /// - /// The WM_APP constant is used to distinguish between message values that are reserved for use by the system and values that can be used by an application to send messages within a private window class. - /// - WM_APP = 0x8000, - - OCM__BASE = WM_USER + 0x1C00, - WM_REFLECT = WM_USER + 0x1C00, - /// - /// From this value to - /// - WM_APPLICATION_STRING = 0xc000, - WM_RASDIALEVENT = 0xCCCD + WM_SYSCOMMAND = 0x0112 } } \ No newline at end of file diff --git a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs index 72f863e1a..0138d9faa 100644 --- a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs @@ -218,11 +218,7 @@ namespace GreenshotPlugin.UnmanagedHelpers { return true; } - public SafeSelectObjectHandle SelectObject(SafeHandle newHandle) { - return new SafeSelectObjectHandle(this, newHandle); - } - - public static SafeDeviceContextHandle FromGraphics(Graphics graphics) { + public static SafeDeviceContextHandle FromGraphics(Graphics graphics) { return new SafeDeviceContextHandle(graphics, graphics.GetHdc()); } } @@ -233,13 +229,11 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static class GDI32 { [DllImport("gdi32", SetLastError=true)] public static extern bool BitBlt(SafeHandle hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, SafeHandle hdcSrc, int nXSrc, int nYSrc, CopyPixelOperation dwRop); - [DllImport("gdi32", SetLastError=true)] - private static extern bool StretchBlt(SafeHandle hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, SafeHandle hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, CopyPixelOperation dwRop); - [DllImport("gdi32", SetLastError=true)] + + [DllImport("gdi32", SetLastError=true)] public static extern SafeCompatibleDCHandle CreateCompatibleDC(SafeHandle hDC); - [DllImport("gdi32", SetLastError=true)] - public static extern IntPtr SelectObject(SafeHandle hDC, SafeHandle hObject); - [DllImport("gdi32", SetLastError=true)] + + [DllImport("gdi32", SetLastError=true)] public static extern SafeDibSectionHandle CreateDIBSection(SafeHandle hdc, ref BITMAPINFOHEADER bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset); [DllImport("gdi32", SetLastError=true)] public static extern SafeRegionHandle CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); @@ -401,26 +395,4 @@ namespace GreenshotPlugin.UnmanagedHelpers { } } } - - [StructLayout(LayoutKind.Sequential)] - public struct BITMAPINFO { - /// - /// A BITMAPINFOHEADER structure that contains information about the dimensions of color format. - /// - public BITMAPINFOHEADER bmiHeader; - - /// - /// An array of RGBQUAD. The elements of the array that make up the color table. - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.Struct)] - public RGBQUAD[] bmiColors; - } - - [StructLayout(LayoutKind.Sequential)] - public struct RGBQUAD { - public byte rgbBlue; - public byte rgbGreen; - public byte rgbRed; - public byte rgbReserved; - } } diff --git a/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs b/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs index 9734806a1..101d74bbf 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs @@ -51,9 +51,8 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize); [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, uint uuchMax); - [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr GetModuleHandle(string lpModuleName); - [DllImport("kernel32", SetLastError = true)] + + [DllImport("kernel32", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); diff --git a/GreenshotPlugin/UnmanagedHelpers/Shell32.cs b/GreenshotPlugin/UnmanagedHelpers/Shell32.cs index e1b7ba0b0..f16d46cec 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Shell32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Shell32.cs @@ -21,7 +21,6 @@ using System; using System.Drawing; using System.Runtime.InteropServices; -using System.Text; using System.IO; namespace GreenshotPlugin.UnmanagedHelpers { @@ -31,9 +30,8 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static class Shell32 { [DllImport("shell32", CharSet = CharSet.Unicode)] public static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons); - [DllImport("shell32", CharSet = CharSet.Unicode)] - internal static extern IntPtr ExtractAssociatedIcon(HandleRef hInst, StringBuilder iconPath, ref int index); - [DllImport("shell32", CharSet = CharSet.Unicode)] + + [DllImport("shell32", CharSet = CharSet.Unicode)] private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags); [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] @@ -53,10 +51,7 @@ namespace GreenshotPlugin.UnmanagedHelpers { private const uint SHGFI_LINKOVERLAY = 0x000008000; // put a link overlay on icon private const uint SHGFI_LARGEICON = 0x000000000; // get large icon private const uint SHGFI_SMALLICON = 0x000000001; // get small icon - private const uint SHGFI_OPENICON = 0x000000002; // get open icon private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // use passed dwFileAttribute - - private const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010; private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; /// @@ -73,21 +68,7 @@ namespace GreenshotPlugin.UnmanagedHelpers { Small = 1 } - /// - /// Options to specify whether folders should be in the open or closed state. - /// - public enum FolderType { - /// - /// Specify open folder. - /// - Open = 0, - /// - /// Specify closed folder. - /// - Closed = 1 - } - - /// + /// /// Returns an icon for a given file extension - indicated by the name parameter. /// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179(v=vs.85).aspx /// @@ -123,73 +104,5 @@ namespace GreenshotPlugin.UnmanagedHelpers { } return null; } - - /// - /// Used to access system folder icons. - /// - /// Specify large or small icons. - /// Specify open or closed FolderType. - /// System.Drawing.Icon - public static Icon GetFolderIcon(IconSize size, FolderType folderType) { - // Need to add size check, although errors generated at present! - uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES; - - if (FolderType.Open == folderType) { - flags += SHGFI_OPENICON; - } - - if (IconSize.Small == size) { - flags += SHGFI_SMALLICON; - } else { - flags += SHGFI_LARGEICON; - } - - // Get the folder icon - SHFILEINFO shfi = new SHFILEINFO(); - SHGetFileInfo(null, FILE_ATTRIBUTE_DIRECTORY, ref shfi, (uint)Marshal.SizeOf(shfi), flags); - - //Icon.FromHandle(shfi.hIcon); // Load the icon from an HICON handle - // Now clone the icon, so that it can be successfully stored in an ImageList - Icon icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); - - // Cleanup - User32.DestroyIcon(shfi.hIcon); - return icon; - } - - /// - /// Returns an icon representation of an image contained in the specified file. - /// This function is identical to System.Drawing.Icon.ExtractAssociatedIcon, xcept this version works. - /// See: http://stackoverflow.com/questions/1842226/how-to-get-the-associated-icon-from-a-network-share-file - /// - /// The path to the file that contains an image. - /// The System.Drawing.Icon representation of the image contained in the specified file. - public static Icon ExtractAssociatedIcon(string filePath) { - int index = 0; - - Uri uri; - if (filePath == null) { - throw new ArgumentException("Null is not valid for filePath", nameof(filePath)); - } - try { - uri = new Uri(filePath); - } catch (UriFormatException) { - filePath = Path.GetFullPath(filePath); - uri = new Uri(filePath); - } - - if (uri.IsFile) { - if (File.Exists(filePath)) { - StringBuilder iconPath = new StringBuilder(1024); - iconPath.Append(filePath); - - IntPtr handle = ExtractAssociatedIcon(new HandleRef(null, IntPtr.Zero), iconPath, ref index); - if (handle != IntPtr.Zero) { - return Icon.FromHandle(handle); - } - } - } - return null; - } - } + } } diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/CursorInfo.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/CursorInfo.cs index 9b818288d..7f18bf9ec 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/CursorInfo.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/CursorInfo.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Runtime.InteropServices; namespace GreenshotPlugin.UnmanagedHelpers.Structs diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/IconInfo.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/IconInfo.cs index 5808f4883..ae8629b4d 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/IconInfo.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/IconInfo.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Runtime.InteropServices; namespace GreenshotPlugin.UnmanagedHelpers.Structs diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/POINT.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/POINT.cs index 9b78ab9a7..b94be1de4 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/POINT.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/POINT.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Drawing; using System.Runtime.InteropServices; diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/RECT.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/RECT.cs index a403cea9b..5186f072b 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/RECT.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/RECT.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Drawing; using System.Runtime.InteropServices; diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/RECTF.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/RECTF.cs index 5fa193343..471d0c4cb 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/RECTF.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/RECTF.cs @@ -1,4 +1,25 @@ -using System.Drawing; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.Drawing; using System.Runtime.InteropServices; namespace GreenshotPlugin.UnmanagedHelpers.Structs diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/SCROLLINFO.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/SCROLLINFO.cs index fec30ca08..0a6451b23 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/SCROLLINFO.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/SCROLLINFO.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Runtime.InteropServices; namespace GreenshotPlugin.UnmanagedHelpers.Structs diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/SIZE.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/SIZE.cs index be5d00bbc..bd1b78699 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/SIZE.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/SIZE.cs @@ -40,5 +40,7 @@ namespace GreenshotPlugin.UnmanagedHelpers.Structs { public Size ToSize() { return new Size(Width, Height); } + + public bool IsEmpty => Width * Height == 0; } } diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/WindowInfo.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/WindowInfo.cs index 8f0405125..532d597a3 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/WindowInfo.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/WindowInfo.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Runtime.InteropServices; namespace GreenshotPlugin.UnmanagedHelpers.Structs diff --git a/GreenshotPlugin/UnmanagedHelpers/Structs/WindowPlacement.cs b/GreenshotPlugin/UnmanagedHelpers/Structs/WindowPlacement.cs index f54baac86..1a7de8ebb 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Structs/WindowPlacement.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Structs/WindowPlacement.cs @@ -1,4 +1,25 @@ -using System; +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System; using System.Runtime.InteropServices; using GreenshotPlugin.UnmanagedHelpers.Enums; diff --git a/GreenshotPlugin/UnmanagedHelpers/User32.cs b/GreenshotPlugin/UnmanagedHelpers/User32.cs index 8ba05f48f..784b7d129 100644 --- a/GreenshotPlugin/UnmanagedHelpers/User32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/User32.cs @@ -39,16 +39,11 @@ namespace GreenshotPlugin.UnmanagedHelpers { private static readonly ILog LOG = LogManager.GetLogger(typeof(User32)); private static bool _CanCallGetPhysicalCursorPos = true; public const int SC_RESTORE = 0xF120; - public const int SC_CLOSE = 0xF060; public const int SC_MAXIMIZE = 0xF030; public const int SC_MINIMIZE = 0xF020; - public const int PW_DEFAULT = 0x00; - public const int PW_CLIENTONLY = 0x01; - - // For MonitorFromWindow + // For MonitorFromWindow public const int MONITOR_DEFAULTTONULL = 0; - public const int MONITOR_DEFAULTTOPRIMARY = 1; public const int MONITOR_DEFAULTTONEAREST = 2; public const int CURSOR_SHOWING = 0x00000001; @@ -76,19 +71,11 @@ namespace GreenshotPlugin.UnmanagedHelpers { [DllImport("user32", SetLastError = true)] public static extern IntPtr GetParent(IntPtr hWnd); - [DllImport("user32", SetLastError = true)] - public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent); - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCommand uCmd); - [DllImport("user32", SetLastError = true)] - public static extern int ShowWindow(IntPtr hWnd, ShowWindowCommand nCmdShow); - [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] + + [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int cch); - [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern int GetWindowTextLength(IntPtr hWnd); - [DllImport("user32", SetLastError = true)] - public static extern uint GetSysColor(int nIndex); - [DllImport("user32", SetLastError = true)] + + [DllImport("user32", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool BringWindowToTop(IntPtr hWnd); [DllImport("user32", SetLastError = true)] @@ -121,9 +108,8 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern bool PrintWindow(IntPtr hWnd, IntPtr hDc, uint nFlags); [DllImport("user32", CharSet=CharSet.Unicode, SetLastError=true)] public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam); - [DllImport("user32", SetLastError = true)] - public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam); - [DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLong")] + + [DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLong")] public static extern int GetWindowLong(IntPtr hWnd, int index); [DllImport("user32", SetLastError = true, EntryPoint = "GetWindowLongPtr")] public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); @@ -138,46 +124,20 @@ namespace GreenshotPlugin.UnmanagedHelpers { [DllImport("user32", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowInfo(IntPtr hWnd, ref WindowInfo pwi); - [DllImport("user32", SetLastError = true)] - public static extern int EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); - [DllImport("user32", SetLastError = true)] + + [DllImport("user32", SetLastError = true)] public static extern int EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetScrollInfo(IntPtr hWnd, int fnBar, ref SCROLLINFO lpsi); - [DllImport("user32", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool ShowScrollBar(IntPtr hWnd, ScrollBarDirection scrollBar, [MarshalAs(UnmanagedType.Bool)] bool show); - [DllImport("user32", SetLastError = true)] - public static extern int SetScrollPos(IntPtr hWnd, Orientation nBar, int nPos, [MarshalAs(UnmanagedType.Bool)] bool bRedraw); - [DllImport("user32", SetLastError = true)] + + [DllImport("user32", SetLastError = true)] public static extern RegionResult GetWindowRgn(IntPtr hWnd, SafeHandle hRgn); [DllImport("user32", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, WindowPos uFlags); - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetTopWindow(IntPtr hWnd); + public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, WindowPos uFlags); - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetDC(IntPtr hWnd); - - [DllImport("user32", SetLastError = true)] - public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc); - - [DllImport("user32", SetLastError = true)] + [DllImport("user32", SetLastError = true)] public static extern IntPtr GetClipboardOwner(); - [DllImport("user32", SetLastError = true)] - public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer); - [DllImport("user32", SetLastError = true)] - public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); - // Added for WinEventHook logic, Greenshot 1.2 - [DllImport("user32", SetLastError = true)] - public static extern bool UnhookWinEvent(IntPtr hWinEventHook); - [DllImport("user32", SetLastError = true)] - public static extern IntPtr SetWinEventHook(WinEvent eventMin, WinEvent eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, int idProcess, int idThread, WinEventHookFlags dwFlags); - - // Added for finding Metro apps, Greenshot 1.1 + // Added for finding Metro apps, Greenshot 1.1 [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] @@ -198,12 +158,8 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult); [DllImport("user32", SetLastError = true)] private static extern bool GetPhysicalCursorPos(out POINT cursorLocation); - [DllImport("user32", SetLastError=true)] - public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, ref POINT lpPoints, [MarshalAs(UnmanagedType.U4)] int cPoints); - [DllImport("user32", SetLastError = true)] - public static extern int GetSystemMetrics(SystemMetric index); - /// + /// /// The following is used for Icon handling /// /// @@ -231,18 +187,7 @@ namespace GreenshotPlugin.UnmanagedHelpers { [DllImport("user32", SetLastError = true)] public static extern bool CloseDesktop(IntPtr hDesktop); - /// - /// The GetWindowDC function retrieves the device context (DC) for the entire window, including title bar, menus, and scroll bars. A window device context permits painting anywhere in a window, because the origin of the device context is the upper-left corner of the window instead of the client area. - /// GetWindowDC assigns default attributes to the window device context each time it retrieves the device context.Previous attributes are lost. - /// See GetWindowDC function - /// - /// A handle to the window whose DC is to be retrieved. If this value is NULL, GetWindowDC retrieves the DC for the entire screen. - /// If the function succeeds, the return value is a handle to a device context for the specified window. - [DllImport("user32", SetLastError = true)] - public static extern IntPtr GetWindowDC(IntPtr hWnd); - - - /// + /// /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. /// /// Point with cursor location, relative to the origin of the monitor setup @@ -308,13 +253,13 @@ namespace GreenshotPlugin.UnmanagedHelpers { public static uint GetGuiResourcesGDICount() { - using Process currentProcess = Process.GetCurrentProcess(); + using var currentProcess = Process.GetCurrentProcess(); return GetGuiResources(currentProcess.Handle, 0); } public static uint GetGuiResourcesUserCount() { - using Process currentProcess = Process.GetCurrentProcess(); + using var currentProcess = Process.GetCurrentProcess(); return GetGuiResources(currentProcess.Handle, 1); } @@ -324,7 +269,7 @@ namespace GreenshotPlugin.UnmanagedHelpers { /// string with current method /// Exception public static Exception CreateWin32Exception(string method) { - Win32Exception exceptionToThrow = new Win32Exception(); + var exceptionToThrow = new Win32Exception(); exceptionToThrow.Data.Add("Method", method); return exceptionToThrow; } diff --git a/GreenshotPlugin/UnmanagedHelpers/Win32.cs b/GreenshotPlugin/UnmanagedHelpers/Win32.cs index 77aaf2256..7efb73292 100644 --- a/GreenshotPlugin/UnmanagedHelpers/Win32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/Win32.cs @@ -35,24 +35,14 @@ namespace GreenshotPlugin.UnmanagedHelpers { return (Win32Error)Marshal.GetLastWin32Error(); } - public static long GetHResult(Win32Error errorCode) { - int error = (int)errorCode; - - if ((error & 0x80000000) == 0x80000000) { - return error; - } - - return 0x80070000 | (uint)(error & 0xffff); - } - public static string GetMessage(Win32Error errorCode) { - StringBuilder buffer = new StringBuilder(0x100); + var buffer = new StringBuilder(0x100); if (FormatMessage(0x3200, IntPtr.Zero, (uint)errorCode, 0, buffer, buffer.Capacity, IntPtr.Zero) == 0) { return "Unknown error (0x" + ((int)errorCode).ToString("x") + ")"; } - StringBuilder result = new StringBuilder(); + var result = new StringBuilder(); int i = 0; while (i < buffer.Length) { diff --git a/GreenshotWin10Plugin/Internal/MemoryRandomAccessStream.cs b/GreenshotWin10Plugin/Internal/MemoryRandomAccessStream.cs index fb48f4a5b..e342f87ae 100644 --- a/GreenshotWin10Plugin/Internal/MemoryRandomAccessStream.cs +++ b/GreenshotWin10Plugin/Internal/MemoryRandomAccessStream.cs @@ -29,22 +29,6 @@ namespace GreenshotWin10Plugin.Internal /// internal sealed class MemoryRandomAccessStream : MemoryStream, IRandomAccessStream { - /// - /// Default constructor - /// - public MemoryRandomAccessStream() - { - } - - /// - /// Constructor where also bytes are already passed - /// - /// byte array - public MemoryRandomAccessStream(byte[] bytes) - { - Write(bytes, 0, bytes.Length); - } - /// public IInputStream GetInputStreamAt(ulong position) { diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 21d640496..369e584cb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,14 +43,14 @@ stages: platform: $(buildPlatform) configuration: $(buildConfiguration) env: - Box_ClientId: $(Box_ClientId) - Box_ClientSecret: $(Box_ClientSecret) - DropBox_ClientId: $(DropBox_ClientId) - DropBox_ClientSecret: $(DropBox_ClientSecret) + Box13_ClientId: $(Box13_ClientId) + Box13_ClientSecret: $(Box13_ClientSecret) + DropBox13_ClientId: $(DropBox13_ClientId) + DropBox13_ClientSecret: $(DropBox13_ClientSecret) Flickr_ClientId: $(Flickr_ClientId) Flickr_ClientSecret: $(Flickr_ClientSecret) - Imgur_ClientId: $(Imgur_ClientId) - Imgur_ClientSecret: $(Imgur_ClientSecret) + Imgur13_ClientId: $(Imgur13_ClientId) + Imgur13_ClientSecret: $(Imgur13_ClientSecret) Photobucket_ClientId: $(Photobucket_ClientId) Photobucket_ClientSecret: $(Photobucket_ClientSecret) Picasa_ClientId: $(Picasa_ClientId)