Merge remote-tracking branch 'origin/release/1.3' into bug/overflow-exception-on-scale

# Conflicts:
#	Greenshot/Helpers/ScaleHelper.cs
This commit is contained in:
jklingen 2021-03-27 18:11:04 +01:00
commit 20096720e8
237 changed files with 6533 additions and 13029 deletions

78
.editorconfig Normal file
View file

@ -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

46
CODE_OF_CONDUCT.md Normal file
View file

@ -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/

18
CONTRIBUTING.md Normal file
View file

@ -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).

View file

@ -65,17 +65,17 @@
</ItemGroup>
<ItemGroup>
<Tokens Include="Box_ClientId">
<ReplacementValue>$(Box_ClientId)</ReplacementValue>
<Tokens Include="Box13_ClientId">
<ReplacementValue>$(Box13_ClientId)</ReplacementValue>
</Tokens>
<Tokens Include="Box_ClientSecret">
<ReplacementValue>$(Box_ClientSecret)</ReplacementValue>
<Tokens Include="Box13_ClientSecret">
<ReplacementValue>$(Box13_ClientSecret)</ReplacementValue>
</Tokens>
<Tokens Include="DropBox_ClientId">
<ReplacementValue>$(DropBox_ClientId)</ReplacementValue>
<Tokens Include="DropBox13_ClientId">
<ReplacementValue>$(DropBox13_ClientId)</ReplacementValue>
</Tokens>
<Tokens Include="DropBox_ClientSecret">
<ReplacementValue>$(DropBox_ClientSecret)</ReplacementValue>
<Tokens Include="DropBox13_ClientSecret">
<ReplacementValue>$(DropBox13_ClientSecret)</ReplacementValue>
</Tokens>
<Tokens Include="Flickr_ClientId">
<ReplacementValue>$(Flickr_ClientId)</ReplacementValue>
@ -83,11 +83,11 @@
<Tokens Include="Flickr_ClientSecret">
<ReplacementValue>$(Flickr_ClientSecret)</ReplacementValue>
</Tokens>
<Tokens Include="Imgur_ClientId">
<ReplacementValue>$(Imgur_ClientId)</ReplacementValue>
<Tokens Include="Imgur13_ClientId">
<ReplacementValue>$(Imgur13_ClientId)</ReplacementValue>
</Tokens>
<Tokens Include="Imgur_ClientSecret">
<ReplacementValue>$(Imgur_ClientSecret)</ReplacementValue>
<Tokens Include="Imgur13_ClientSecret">
<ReplacementValue>$(Imgur13_ClientSecret)</ReplacementValue>
</Tokens>
<Tokens Include="Photobucket_ClientId">
<ReplacementValue>$(Photobucket_ClientId)</ReplacementValue>

View file

@ -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

View file

@ -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
}
}

View file

@ -28,8 +28,6 @@ namespace Greenshot.Controls {
/// See: http://blogs.msdn.com/b/rickbrew/archive/2006/01/09/511003.aspx
/// </summary>
public class MenuStripEx : MenuStrip {
private const int WM_MOUSEACTIVATE = 0x21;
private enum NativeConstants : uint {
MA_ACTIVATE = 1,
MA_ACTIVATEANDEAT = 2,

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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");
/// <summary>
/// Allows to override the initializing of the fields, so we can actually have our own defaults

View file

@ -30,17 +30,13 @@ namespace Greenshot.Drawing {
/// <summary>
/// empty container for filter-only elements
/// </summary>
[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();
}

View file

@ -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);
}
}

View file

@ -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
/// </summary>
/// <param name="shadow"></param>
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);
}
/// <summary>
@ -202,25 +207,28 @@ namespace Greenshot.Drawing {
/// </summary>
/// <param name="graphics"></param>
/// <param name="rm"></param>
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);
}
}

View file

@ -34,9 +34,7 @@ namespace Greenshot.Drawing {
/// </summary>
[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();
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Greenshot.Drawing {
/// <summary>
/// TODO: currently this is only used in the capture form, we might move this code directly to there!
/// </summary>
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);
}
}
}

View file

@ -598,9 +598,15 @@ namespace Greenshot.Drawing
DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font);
}
/// <summary>
/// Convert the StringFormat information into a TextFormatFlags
/// This is important for the rending to work, have it aligned to the correct place
/// </summary>
/// <param name="stringFormat">StringFormat</param>
/// <returns>TextFormatFlags</returns>
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)

View file

@ -21,6 +21,7 @@
using System.Windows.Forms;
using Greenshot.Helpers;
using GreenshotPlugin.Core;
namespace Greenshot.Forms {
partial class AboutForm {

View file

@ -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;
}
}
}

View file

@ -59,8 +59,6 @@ namespace Greenshot.Forms {
set { PreviewColor(value, this); }
}
public IList<Color> 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;

View file

@ -73,12 +73,7 @@ namespace Greenshot.Forms {
/// </summary>
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) };
/// <summary>
/// An Implementation for the IImageEditor, this way Plugins have access to the HWND handles wich can be used with Win32 API calls.
/// </summary>
public IWin32Window WindowHandle => this;
public static List<IImageEditor> Editors {
public static List<IImageEditor> 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) {

View file

@ -486,12 +486,7 @@ namespace Greenshot.Forms {
}
}
/// <summary>
/// Main context menu
/// </summary>
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;
}
/// <summary>
/// Create the "capture window from list" list
/// </summary>
/// <param name="menuItem">ToolStripMenuItem</param>
/// <param name="eventHandler">EventHandler</param>
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) {

View file

@ -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) {}
/// <summary>
/// gets or sets the currently checked item
/// </summary>
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;
}
}
}
}
/// <summary>
/// gets or sets the currently checked items
/// </summary>
public ToolStripMenuSelectListItem[] CheckedItems {
get {
List<ToolStripMenuSelectListItem> sel = new List<ToolStripMenuSelectListItem>();
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);
}
/// <summary>
/// adds an item to the select list
/// </summary>
/// <param name="label">the label to be displayed</param>
/// <param name="image">the icon to be displayed</param>
public void AddItem(string label, Image image) {
AddItem(label, image, null, false);
}
/// <summary>
/// adds an item to the select list
/// </summary>
/// <param name="label">the label to be displayed</param>
/// <param name="data">the data to be returned when an item is queried</param>
public void AddItem(string label, object data) {
AddItem(label, null, data, false);
}
/// <summary>
/// adds an item to the select list
/// </summary>
/// <param name="label">the label to be displayed</param>
public void AddItem(string label) {
AddItem(label, null, null, false);
}
/// <summary>
/// adds an item to the select list
/// </summary>
/// <param name="label">the label to be displayed</param>
/// <param name="image">the icon to be displayed</param>
/// <param name="isChecked">whether the item is initially checked</param>
public void AddItem(string label, Image image, bool isChecked) {
AddItem(label, image, null, isChecked);
}
/// <summary>
/// <summary>
/// adds an item to the select list
/// </summary>
/// <param name="label">the label to be displayed</param>
@ -219,16 +113,7 @@ namespace Greenshot.Forms {
AddItem(label, null, data, isChecked);
}
/// <summary>
/// adds an item to the select list
/// </summary>
/// <param name="label">the label to be displayed</param>
/// <param name="isChecked">whether the item is initially checked</param>
public void AddItem(string label, bool isChecked) {
AddItem(label, null, null, isChecked);
}
/// <summary>
/// <summary>
/// unchecks all items of the list
/// </summary>
public void UncheckAll() {

View file

@ -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();
// }

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of EnvironmentInfo.
/// </summary>
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<AssemblyFileVersionAttribute>();
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<AssemblyInformationalVersionAttribute>();
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();
}
}
/// <summary>
/// Provides detailed information about the host operating system.
/// Code is available at: http://www.csharp411.com/determine-windows-version-and-edition-with-c/
/// </summary>
public static class OsInfo
{
/// <summary>
/// Determines if the current application is 32 or 64-bit.
/// </summary>
public static int Bits => IntPtr.Size * 8;
private static string _sEdition;
/// <summary>
/// Gets the edition of the operating system running on this computer.
/// </summary>
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;
/// <summary>
/// Gets the name of the operating system running on this computer.
/// </summary>
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
{
/// <summary>
/// The size of this data structure, in bytes. Set this member to sizeof(OSVERSIONINFOEX).
/// </summary>
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;
/// <summary>
/// The major version number of the operating system.
/// </summary>
public int MajorVersion => _dwMajorVersion;
/// <summary>
/// The minor version number of the operating system.
/// </summary>
public int MinorVersion => _dwMinorVersion;
/// <summary>
/// The build number of the operating system.
/// </summary>
public int BuildNumber => _dwBuildNumber;
/// <summary>
/// The operating system platform. This member can be VER_PLATFORM_WIN32_NT (2).
/// </summary>
public int PlatformId => _dwPlatformId;
/// <summary>
/// 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.
/// </summary>
public string ServicePackVersion
{
get
{
fixed (char* servicePackVersion = _szCSDVersion)
{
return new string(servicePackVersion);
}
}
}
/// <summary>
/// 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.
/// </summary>
public short ServicePackMajor => _wServicePackMajor;
/// <summary>
/// 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.
/// </summary>
public short ServicePackMinor => _wServicePackMinor;
/// <summary>
/// A bit mask that identifies the product suites available on the system. This member can be a combination of the
/// following values.
/// </summary>
public ushort SuiteMask => _wSuiteMask;
/// <summary>
/// Any additional information about the system.
/// </summary>
public byte ProductType => _wProductType;
/// <summary>
/// Factory for an empty OsVersionInfoEx
/// </summary>
/// <returns>OSVERSIONINFOEX</returns>
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;
/// <summary>
/// Gets the service pack information of the operating system running on this computer.
/// </summary>
public static string ServicePack
{
get
{
string servicePack = string.Empty;
OSVERSIONINFOEX osVersionInfo = OSVERSIONINFOEX.Create();
if (GetVersionEx(ref osVersionInfo))
{
servicePack = osVersionInfo.ServicePackVersion;
}
return servicePack;
}
}
/// <summary>
/// Gets the build version number of the operating system running on this computer.
/// </summary>
public static int BuildVersion => Environment.OSVersion.Version.Build;
/// <summary>
/// Gets the full version string of the operating system running on this computer.
/// </summary>
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}";
}
}
/// <summary>
/// Gets the full version of the operating system running on this computer.
/// </summary>
public static Version Version
{
get
{
return Environment.OSVersion.Version;
}
}
/// <summary>
/// Gets the major version number of the operating system running on this computer.
/// </summary>
public static int MajorVersion
{
get
{
return Environment.OSVersion.Version.Major;
}
}
/// <summary>
/// Gets the minor version number of the operating system running on this computer.
/// </summary>
public static int MinorVersion
{
get
{
return Environment.OSVersion.Version.Minor;
}
}
/// <summary>
/// Gets the revision version number of the operating system running on this computer.
/// </summary>
public static int RevisionVersion
{
get
{
return Environment.OSVersion.Version.Revision;
}
}
}
}

View file

@ -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;
}
}
}
}
}

View file

@ -60,27 +60,7 @@ namespace Greenshot.Helpers {
ieAccessible.ActivateIETab(tabIndex);
}
/// <summary>
/// Return true if the supplied window has a sub-window which covers more than the supplied percentage
/// </summary>
/// <param name="someWindow">WindowDetails to check</param>
/// <param name="minimumPercentage">min percentage</param>
/// <returns></returns>
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;
}
/// <summary>
/// <summary>
/// Does the supplied window have a IE part?
/// </summary>
/// <param name="someWindow"></param>
@ -321,15 +301,7 @@ namespace Greenshot.Helpers {
return returnDocumentContainer;
}
/// <summary>
/// Here the logic for capturing the IE Content is located
/// </summary>
/// <param name="capture">ICapture where the capture needs to be stored</param>
/// <returns>ICapture with the content (if any)</returns>
public static ICapture CaptureIe(ICapture capture) {
return CaptureIe(capture, WindowDetails.GetActiveWindow());
}
/// <summary>
/// <summary>
/// Here the logic for capturing the IE Content is located
/// </summary>
/// <param name="capture">ICapture where the capture needs to be stored</param>

View file

@ -126,14 +126,7 @@ namespace Greenshot.Helpers {
_manualResetEvent = new ManualResetEvent(false);
}
/// <summary>
/// Creates a new mail message with the specified subject.
/// </summary>
public MapiMailMessage(string subject) : this() {
Subject = subject;
}
/// <summary>
/// <summary>
/// Creates a new mail message with the specified subject and body.
/// </summary>
public MapiMailMessage(string subject, string body) : this() {
@ -437,21 +430,6 @@ namespace Greenshot.Helpers {
public MapiMailMessage.RecipientType RecipientType = MapiMailMessage.RecipientType.To;
/// <summary>
/// Creates a new recipient with the specified address.
/// </summary>
public Recipient(string address) {
Address = address;
}
/// <summary>
/// Creates a new recipient with the specified address and display name.
/// </summary>
public Recipient(string address, string displayName) {
Address = address;
DisplayName = displayName;
}
/// <summary>
/// Creates a new recipient with the specified address and recipient type.
/// </summary>
public Recipient(string address, MapiMailMessage.RecipientType recipientType) {
@ -459,15 +437,6 @@ namespace Greenshot.Helpers {
RecipientType = recipientType;
}
/// <summary>
/// Creates a new recipient with the specified address, display name and recipient type.
/// </summary>
public Recipient(string address, string displayName, MapiMailMessage.RecipientType recipientType) {
Address = address;
DisplayName = displayName;
RecipientType = recipientType;
}
/// <summary>
/// Returns an interop representation of a recepient.
/// </summary>
@ -499,40 +468,7 @@ namespace Greenshot.Helpers {
List.Add(value);
}
/// <summary>
/// Adds a new recipient with the specified address to this collection.
/// </summary>
public void Add(string address) {
Add(new Recipient(address));
}
/// <summary>
/// Adds a new recipient with the specified address and display name to this collection.
/// </summary>
public void Add(string address, string displayName) {
Add(new Recipient(address, displayName));
}
/// <summary>
/// Adds a new recipient with the specified address and recipient type to this collection.
/// </summary>
public void Add(string address, MapiMailMessage.RecipientType recipientType) {
Add(new Recipient(address, recipientType));
}
/// <summary>
/// Adds a new recipient with the specified address, display name and recipient type to this collection.
/// </summary>
public void Add(string address, string displayName, MapiMailMessage.RecipientType recipientType) {
Add(new Recipient(address, displayName, recipientType));
}
/// <summary>
/// Returns the recipient stored in this collection at the specified index.
/// </summary>
public Recipient this[int index] => (Recipient)List[index];
internal InteropRecipientCollection GetInteropRepresentation() {
internal InteropRecipientCollection GetInteropRepresentation() {
return new InteropRecipientCollection(this);
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Windows.Forms;
using Greenshot.Drawing;
namespace Greenshot.Helpers {
/// <summary>
/// Offers a few helper functions for scaling/aligning an element with another element
/// </summary>
public static class ScaleHelper {
[Flags]
public enum ScaleOptions {
/// <summary>
/// Default scale behavior.
/// </summary>
Default = 0x00,
/// <summary>
/// Scale a rectangle in two our four directions, mirrored at it's center coordinates
/// </summary>
Centered = 0x01,
/// <summary>
/// Scale a rectangle maintaining it's aspect ratio
/// </summary>
Rational = 0x02
}
/// <summary>
/// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio
/// </summary>
/// <param name="currentSize">the size of the element to be resized</param>
/// <param name="targetSize">the target size of the element</param>
/// <param name="crop">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)</param>
/// <returns>a new SizeF object indicating the width and height the element should be scaled to</returns>
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);
}
/// <summary>
/// calculates the position of an element depending on the desired alignment within a RectangleF
/// </summary>
/// <param name="currentRect">the bounds of the element to be aligned</param>
/// <param name="targetRect">the rectangle reference for alignment of the element</param>
/// <param name="alignment">the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize</param>
/// <returns>a new RectangleF object with Location aligned aligned to targetRect</returns>
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;
}
/// <summary>
/// calculates the Rectangle an element must be resized an positioned to, in ordder to fit another element, keeping aspect ratio
/// </summary>
/// <param name="currentRect">the rectangle of the element to be resized/repositioned</param>
/// <param name="targetRect">the target size/position of the element</param>
/// <param name="crop">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)</param>
/// <param name="alignment">the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize</param>
/// <returns>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</returns>
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);
}
/// <summary>
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
/// </summary>
/// <param name="originalRectangle">bounds of the current rectangle, scaled values will be written to this reference</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
/// <param name="options">ScaleOptions to use when scaling</param>
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);
}
}
/// <summary>
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
/// </summary>
/// <param name="originalRectangle">bounds of the current rectangle, scaled values will be written to this reference</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
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);
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="originalRectangle">bounds of the current rectangle</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see Position</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper, adjusted coordinates will be written to this reference</param>
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;
}
}
/// <summary>
/// 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
/// </summary>
/// <param name="originalSize">size to be considered for keeping aspect ratio</param>
/// <param name="selectedSize">selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio)</param>
/// <returns></returns>
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;
}
}
/// <returns>the current ScaleOptions depending on modifier keys held down</returns>
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Drawing;
using System.Windows.Forms;
using Greenshot.Drawing;
namespace Greenshot.Helpers {
/// <summary>
/// Offers a few helper functions for scaling/aligning an element with another element
/// </summary>
public static class ScaleHelper {
[Flags]
public enum ScaleOptions {
/// <summary>
/// Default scale behavior.
/// </summary>
Default = 0x00,
/// <summary>
/// Scale a rectangle in two our four directions, mirrored at it's center coordinates
/// </summary>
Centered = 0x01,
/// <summary>
/// Scale a rectangle maintaining it's aspect ratio
/// </summary>
Rational = 0x02
}
/// <summary>
/// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio
/// </summary>
/// <param name="currentSize">the size of the element to be resized</param>
/// <param name="targetSize">the target size of the element</param>
/// <param name="crop">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)</param>
/// <returns>a new SizeF object indicating the width and height the element should be scaled to</returns>
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);
}
/// <summary>
/// calculates the position of an element depending on the desired alignment within a RectangleF
/// </summary>
/// <param name="currentRect">the bounds of the element to be aligned</param>
/// <param name="targetRect">the rectangle reference for alignment of the element</param>
/// <param name="alignment">the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize</param>
/// <returns>a new RectangleF object with Location aligned aligned to targetRect</returns>
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;
}
/// <summary>
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
/// </summary>
/// <param name="originalRectangle">bounds of the current rectangle, scaled values will be written to this reference</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
/// <param name="options">ScaleOptions to use when scaling</param>
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);
}
}
/// <summary>
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
/// </summary>
/// <param name="originalRectangle">bounds of the current rectangle, scaled values will be written to this reference</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
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);
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="originalRectangle">bounds of the current rectangle</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see Position</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper, adjusted coordinates will be written to this reference</param>
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;
}
}
/// <summary>
/// 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
/// </summary>
/// <param name="originalSize">size to be considered for keeping aspect ratio</param>
/// <param name="selectedSize">selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio)</param>
/// <returns></returns>
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;
}
}
/// <returns>the current ScaleOptions depending on modifier keys held down</returns>
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;
}
}
}
}

View file

@ -54,16 +54,8 @@ namespace Greenshot.Helpers {
public static void Enable(ToolStripItem tsi) {
Endisable(tsi, true, PropagationMode.CHILDREN | PropagationMode.ANCESTORS);
}
/// <summary>
/// Disables the ToolStripItem, including children (ToolStripDropDownItem),
/// but NOT the ancestor (OwnerItem)
/// </summary>
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;

View file

@ -93,17 +93,6 @@ namespace Greenshot.Helpers
_ = BackgroundTask(() => TimeSpan.FromDays(CoreConfig.UpdateCheckInterval), UpdateCheck, _cancellationTokenSource.Token);
}
/// <summary>
/// Stop the update checks
/// </summary>
public void Shutdown()
{
if (!_cancellationTokenSource.IsCancellationRequested)
{
_cancellationTokenSource.Cancel();
}
}
/// <summary>
/// This runs a periodic task in the background
/// </summary>

View file

@ -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')

View file

@ -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 {

View file

@ -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 {
/// <summary>
/// Description of ImgurUtils.
/// </summary>
public static class BoxUtils {
/// <summary>
/// Description of BoxUtils.
/// </summary>
public static class BoxUtils {
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(BoxUtils));
private static readonly BoxConfiguration Config = IniConfig.GetIniSection<BoxConfiguration>();
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
/// </summary>
internal static class JsonSerializer {
/// <summary>
/// Helper method to serialize object to JSON
/// </summary>
/// <param name="jsonObject">JSON object</param>
/// <returns>string</returns>
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());
}
/// <summary>
/// <summary>
/// Helper method to parse JSON to object
/// </summary>
/// <typeparam name="T"></typeparam>
@ -141,7 +128,7 @@ namespace GreenshotBoxPlugin {
/// <returns></returns>
public static T Deserialize<T>(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);

View file

@ -25,7 +25,7 @@ namespace GreenshotBoxPlugin {
/// You can set your own values here
/// </summary>
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}";
}
}

View file

@ -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
}
}

View file

@ -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) {

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Collections;
using System.Windows.Forms;
namespace GreenshotConfluencePlugin.Forms
{
/// <summary>
/// This class is an implementation of the 'IComparer' interface.
/// </summary>
public class ListViewColumnSorter : IComparer {
/// <summary>
/// Specifies the column to be sorted
/// </summary>
private int _columnToSort;
/// <summary>
/// Specifies the order in which to sort (i.e. 'Ascending').
/// </summary>
private SortOrder _orderOfSort;
/// <summary>
/// Case insensitive comparer object
/// </summary>
private readonly CaseInsensitiveComparer _objectCompare;
/// <summary>
/// Class constructor. Initializes various elements
/// </summary>
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();
}
/// <summary>
/// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
/// </summary>
/// <param name="x">First object to be compared</param>
/// <param name="y">Second object to be compared</param>
/// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
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;
}
}
/// <summary>
/// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
/// </summary>
public int SortColumn {
set {
_columnToSort = value;
}
get {
return _columnToSort;
}
}
/// <summary>
/// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
/// </summary>
public SortOrder Order {
set {
_orderOfSort = value;
}
get {
return _orderOfSort;
}
}
}
}

View file

@ -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
}
}

View file

@ -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;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
@ -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;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
/// <summary>
@ -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);

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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; }
/// <summary>
/// AccessToken, not stored
/// </summary>
public string AccessToken { get; set; }
/// <summary>
/// AccessTokenExpires, not stored
/// </summary>
public DateTimeOffset AccessTokenExpires { get; set; }
/// <summary>
/// A form for token

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 {
/// <summary>
@ -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<string, object> arguments = new Dictionary<string, object>
{
{ "autorename", true },
{ "mute", true },
{ "path", "/" + filename.Replace(Path.DirectorySeparatorChar, '\\')}
};
IDictionary<string, object> headers = new Dictionary<string, object>
{
{ "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<IDictionary<string, string>>(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<string, object> 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();
}
}
}
}

View file

@ -25,7 +25,7 @@ namespace GreenshotDropboxPlugin {
/// You can set your own values here
/// </summary>
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}";
}
}

View file

@ -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
}
}

View file

@ -29,134 +29,158 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin;
namespace GreenshotExternalCommandPlugin {
/// <summary>
/// An Plugin to run commands after an image was written
/// </summary>
namespace GreenshotExternalCommandPlugin
{
/// <summary>
/// An Plugin to run commands after an image was written
/// </summary>
[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<CoreConfiguration>();
private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>();
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<CoreConfiguration>();
private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection<ExternalCommandConfiguration>();
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<IDestination> Destinations() {
foreach(string command in ExternalCommandConfig.Commands) {
yield return new ExternalCommandDestination(command);
}
}
private IEnumerable<IDestination> Destinations()
{
foreach (string command in ExternalCommandConfig.Commands)
{
yield return new ExternalCommandDestination(command);
}
}
/// <summary>
/// Check and eventually fix the command settings
/// </summary>
/// <param name="command"></param>
/// <returns>false if the command is not correctly configured</returns>
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);
/// <summary>
/// Check and eventually fix the command settings
/// </summary>
/// <param name="command"></param>
/// <returns>false if the command is not correctly configured</returns>
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;
}
/// <summary>
/// Implementation of the IGreenshotPlugin.Initialize
/// </summary>
public virtual bool Initialize()
{
Log.DebugFormat("Initialize called");
var commandsToDelete = new List<string>();
// 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;
}
/// <summary>
/// Implementation of the IGreenshotPlugin.Initialize
/// </summary>
public virtual bool Initialize() {
Log.DebugFormat("Initialize called");
List<string> commandsToDelete = new List<string>();
// 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;
}
/// <summary>
/// Fix icon reference
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
/// <summary>
/// Fix icon reference
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
/// <summary>
/// Implementation of the IPlugin.Configure
/// </summary>
public virtual void Configure() {
Log.Debug("Configure called");
new SettingsForm().ShowDialog();
}
}
/// <summary>
/// Implementation of the IPlugin.Configure
/// </summary>
public virtual void Configure()
{
Log.Debug("Configure called");
new SettingsForm().ShowDialog();
}
}
}

View file

@ -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;

View file

@ -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
}
}

View file

@ -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 {
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPicasaPlugin.Forms {
partial class SettingsForm {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// 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.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotGooglePhotosPlugin.Forms {
partial class SettingsForm {
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// 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.
/// </summary>
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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPicasaPlugin.Forms {
/// <summary>
/// Description of PasswordRequestForm.
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotGooglePhotosPlugin.Forms {
/// <summary>
/// Description of PasswordRequestForm.
/// </summary>
public partial class SettingsForm : GooglePhotosForm {
public SettingsForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
CancelButton = buttonCancel;
AcceptButton = buttonOK;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Windows.Forms;
using GreenshotPlugin.Core;
using System;
using GreenshotPicasaPlugin.Forms;
using GreenshotPlugin.IniFile;
namespace GreenshotPicasaPlugin {
/// <summary>
/// Description of PicasaConfiguration.
/// </summary>
[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;
}
/// <summary>
/// Not stored
/// </summary>
public string AccessToken {
get;
set;
}
/// <summary>
/// Not stored
/// </summary>
public DateTimeOffset AccessTokenExpires {
get;
set;
}
/// <summary>
/// A form for token
/// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns>
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 <http://www.gnu.org/licenses/>.
*/
using System.Windows.Forms;
using GreenshotPlugin.Core;
using System;
using GreenshotGooglePhotosPlugin.Forms;
using GreenshotPlugin.IniFile;
namespace GreenshotGooglePhotosPlugin {
/// <summary>
/// Description of GooglePhotosConfiguration.
/// </summary>
[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;
}
/// <summary>
/// Not stored
/// </summary>
public string AccessToken {
get;
set;
}
/// <summary>
/// Not stored
/// </summary>
public DateTimeOffset AccessTokenExpires {
get;
set;
}
/// <summary>
/// A form for token
/// </summary>
/// <returns>bool true if OK was pressed, false if cancel</returns>
public bool ShowConfigDialog() {
DialogResult result = new SettingsForm().ShowDialog();
if (result == DialogResult.OK) {
return true;
}
return false;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 {
/// <summary>
/// This is the Picasa base code
/// </summary>
[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;
}
}
}
/// <summary>
/// Implementation of the IGreenshotPlugin.Initialize
/// </summary>
public bool Initialize() {
SimpleServiceProvider.Current.AddService<IDestination>(new PicasaDestination(this));
// Get configuration
_config = IniConfig.GetIniSection<PicasaConfiguration>();
_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);
}
/// <summary>
/// Implementation of the IPlugin.Configure
/// </summary>
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 <http://www.gnu.org/licenses/>.
*/
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 {
/// <summary>
/// This is the GooglePhotos base code
/// </summary>
[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;
}
/// <summary>
/// Implementation of the IGreenshotPlugin.Initialize
/// </summary>
public bool Initialize() {
SimpleServiceProvider.Current.AddService<IDestination>(new GooglePhotosDestination(this));
// Get configuration
_config = IniConfig.GetIniSection<GooglePhotosConfiguration>();
_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);
}
/// <summary>
/// Implementation of the IPlugin.Configure
/// </summary>
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;
}
}
}

View file

@ -118,7 +118,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Picasa" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>picasa.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="GooglePhotos" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>GooglePhotos.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Core;
using System;
using System.Xml;
using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin;
namespace GreenshotPicasaPlugin {
/// <summary>
/// Description of PicasaUtils.
/// </summary>
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<PicasaConfiguration>();
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}";
/// <summary>
/// Do the actual upload to Picasa
/// </summary>
/// <param name="surfaceToUpload">Image to upload</param>
/// <param name="outputSettings"></param>
/// <param name="title"></param>
/// <param name="filename"></param>
/// <returns>PicasaResponse</returns>
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();
}
}
/// <summary>
/// Parse the upload URL from the response
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
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 <http://www.gnu.org/licenses/>.
*/
using GreenshotPlugin.Core;
using System;
using System.Xml;
using GreenshotPlugin.Core.OAuth;
using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Plugin;
namespace GreenshotGooglePhotosPlugin {
/// <summary>
/// Description of GooglePhotosUtils.
/// </summary>
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<GooglePhotosConfiguration>();
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}";
/// <summary>
/// Do the actual upload to GooglePhotos
/// </summary>
/// <param name="surfaceToUpload">Image to upload</param>
/// <param name="outputSettings">SurfaceOutputSettings</param>
/// <param name="title">string</param>
/// <param name="filename">string</param>
/// <returns>GooglePhotosResponse</returns>
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();
}
}
/// <summary>
/// Parse the upload URL from the response
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
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;
}
}
}

View file

@ -19,13 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GreenshotPicasaPlugin {
namespace GreenshotGooglePhotosPlugin {
/// <summary>
/// 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
/// </summary>
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}";
}
}

View file

@ -1,16 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<RootNamespace>GreenshotOCRPlugin</RootNamespace>
<AssemblyName>GreenshotOCRPlugin</AssemblyName>
</PropertyGroup>
<ItemGroup>
<None Include="Languages\language*.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GreenshotPlugin\GreenshotPlugin.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<ItemGroup>
<None Include="Languages\language*.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="GooglePhotos.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GreenshotPlugin\GreenshotPlugin.csproj" />
</ItemGroup>
</Project>

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
}
}

View file

@ -1,29 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Czech" ietf="cs-CZ" version="1.1.0.2411" languagegroup="">
<resources>
<resource name="CANCEL">Zrušit</resource>
<resource name="communication_wait">Probíhá komunikace s Picasem. Prosím počkejte ...</resource>
<resource name="Configure">Konfigurace</resource>
<resource name="delete_question">Opravdu chcete odstranit obrázek {0} z Picasa?</resource>
<resource name="delete_title">Odstranit Picasa {0}</resource>
<resource name="History">Historie</resource>
<resource name="InvalidCredentials">Neplatná oprávnění. Otevřít nastavení pro provedené změn.</resource>
<resource name="label_AfterUpload">Po odeslání</resource>
<resource name="label_AfterUploadLinkToClipBoard">Kopírovat odkaz do schránky</resource>
<resource name="label_AfterUploadOpenHistory">Zobrazit historii</resource>
<resource name="label_DefaultSize">Výchozí velikost</resource>
<resource name="label_Password">Heslo</resource>
<resource name="label_upload_format">Formát obrázku</resource>
<resource name="label_Username">Jméno</resource>
<resource name="OK">OK</resource>
<resource name="PictureDisplaySize.OriginalUrl">Originál URL</resource>
<resource name="PictureDisplaySize.SquareThumbnailUrl">Čtvercové náhledy URL ???</resource>
<resource name="PictureDisplaySize.WebUrl">Webová adresa URL</resource>
<resource name="settings_title">Nastavení Picasa</resource>
<resource name="Upload">Nahrát</resource>
<resource name="upload_failure">Nahrání obrázku do Picasa se nezdařilo:</resource>
<resource name="upload_menu_item">Nahrát do Picasa</resource>
<resource name="upload_success">Úspěšně odeslaný obrázek do Picasa!</resource>
<resource name="UsernameNotSet">Prosím ověřit aplikaci Picasa. Otevřít nastavení obrazovky. ???</resource>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<language description="Czech" ietf="cs-CZ" version="1.1.0.2411" languagegroup="">
<resources>
<resource name="CANCEL">Zrušit</resource>
<resource name="communication_wait">Probíhá komunikace s Picasem. Prosím počkejte ...</resource>
<resource name="Configure">Konfigurace</resource>
<resource name="delete_question">Opravdu chcete odstranit obrázek {0} z GooglePhotos?</resource>
<resource name="delete_title">Odstranit GooglePhotos {0}</resource>
<resource name="History">Historie</resource>
<resource name="InvalidCredentials">Neplatná oprávnění. Otevřít nastavení pro provedené změn.</resource>
<resource name="label_AfterUpload">Po odeslání</resource>
<resource name="label_AfterUploadLinkToClipBoard">Kopírovat odkaz do schránky</resource>
<resource name="label_AfterUploadOpenHistory">Zobrazit historii</resource>
<resource name="label_DefaultSize">Výchozí velikost</resource>
<resource name="label_Password">Heslo</resource>
<resource name="label_upload_format">Formát obrázku</resource>
<resource name="label_Username">Jméno</resource>
<resource name="OK">OK</resource>
<resource name="PictureDisplaySize.OriginalUrl">Originál URL</resource>
<resource name="PictureDisplaySize.SquareThumbnailUrl">Čtvercové náhledy URL ???</resource>
<resource name="PictureDisplaySize.WebUrl">Webová adresa URL</resource>
<resource name="settings_title">Nastavení GooglePhotos</resource>
<resource name="Upload">Nahrát</resource>
<resource name="upload_failure">Nahrání obrázku do GooglePhotos se nezdařilo:</resource>
<resource name="upload_menu_item">Nahrát do GooglePhotos</resource>
<resource name="upload_success">Úspěšně odeslaný obrázek do GooglePhotos!</resource>
<resource name="UsernameNotSet">Prosím ověřit aplikaci GooglePhotos. Otevřít nastavení obrazovky. ???</resource>
</resources>
</language>

View file

@ -8,25 +8,25 @@
Anschliessend
</resource>
<resource name="Configure">
Picasa konfigurieren
GooglePhotos konfigurieren
</resource>
<resource name="upload_menu_item">
Hochladen zu Picasa
Hochladen zu GooglePhotos
</resource>
<resource name="settings_title">
Picasa Einstellungen
GooglePhotos Einstellungen
</resource>
<resource name="upload_success">
Hochladen zu Picasa war erfolgreich !
Hochladen zu GooglePhotos war erfolgreich !
</resource>
<resource name="upload_failure">
Fehler beim Hochladen zu Picasa:
Fehler beim Hochladen zu GooglePhotos:
</resource>
<resource name="label_upload_format">
Grafikformat
</resource>
<resource name="communication_wait">
Übermittle Daten zu Picasa. Bitte warten...
Übermittle Daten zu GooglePhotos. Bitte warten...
</resource>
</resources>
</language>

View file

@ -8,25 +8,25 @@
After upload
</resource>
<resource name="Configure">
Configure Picasa
Configure GooglePhotos
</resource>
<resource name="upload_menu_item">
Upload to Picasa
Upload to GooglePhotos
</resource>
<resource name="settings_title">
Picasa settings
GooglePhotos settings
</resource>
<resource name="upload_success">
Successfully uploaded image to Picasa!
Successfully uploaded image to GooglePhotos!
</resource>
<resource name="upload_failure">
An error occured while uploading to Picasa:
An error occured while uploading to GooglePhotos:
</resource>
<resource name="label_upload_format">
Image format
</resource>
<resource name="communication_wait">
Communicating with Picasa. Please wait...
Communicating with GooglePhotos. Please wait...
</resource>
</resources>
</language>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Français" ietf="fr-FR" version="1.0.0" languagegroup="">
<resources>
<resource name="communication_wait">Communication en cours avec Picasa. Veuillez patientez...</resource>
<resource name="Configure">Configurer Picasa</resource>
<resource name="label_AfterUpload">Après téléversement</resource>
<resource name="label_AfterUploadLinkToClipBoard">Copier le lien dans le presse-papier</resource>
<resource name="label_upload_format">Format image</resource>
<resource name="settings_title">Paramètres Picasa</resource>
<resource name="upload_failure">Une erreur s'est produite lors du téléversement vers Picasa :</resource>
<resource name="upload_menu_item">Téléverser vers Picasa</resource>
<resource name="upload_success">Image téléversée avec succès vers Picasa !</resource>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<language description="Français" ietf="fr-FR" version="1.0.0" languagegroup="">
<resources>
<resource name="communication_wait">Communication en cours avec GooglePhotos. Veuillez patientez...</resource>
<resource name="Configure">Configurer GooglePhotos</resource>
<resource name="label_AfterUpload">Après téléversement</resource>
<resource name="label_AfterUploadLinkToClipBoard">Copier le lien dans le presse-papier</resource>
<resource name="label_upload_format">Format image</resource>
<resource name="settings_title">Paramètres GooglePhotos</resource>
<resource name="upload_failure">Une erreur s'est produite lors du téléversement vers GooglePhotos :</resource>
<resource name="upload_menu_item">Téléverser vers GooglePhotos</resource>
<resource name="upload_success">Image téléversée avec succès vers GooglePhotos !</resource>
</resources>
</language>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Bahasa Indonesia" ietf="id-ID" version="1.0.0.0" languagegroup="">
<resources>
<resource name="communication_wait">Menyambungkan ke Picasa. Tunggu sebentar...</resource>
<resource name="Configure">Konfigurasi Picasa</resource>
<resource name="label_AfterUpload">Sesudah mengunggah</resource>
<resource name="label_AfterUploadLinkToClipBoard">Sambung ke papanklip</resource>
<resource name="label_upload_format">Format gambar</resource>
<resource name="settings_title">Pengaturan Picasa</resource>
<resource name="upload_failure">Kesalahan terjadi ketika mengunggah ke Picasa:</resource>
<resource name="upload_menu_item">Unggah ke Picasa</resource>
<resource name="upload_success">Berhasil mengunggah gambar ke Picasa!</resource>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<language description="Bahasa Indonesia" ietf="id-ID" version="1.0.0.0" languagegroup="">
<resources>
<resource name="communication_wait">Menyambungkan ke GooglePhotos. Tunggu sebentar...</resource>
<resource name="Configure">Konfigurasi GooglePhotos</resource>
<resource name="label_AfterUpload">Sesudah mengunggah</resource>
<resource name="label_AfterUploadLinkToClipBoard">Sambung ke papanklip</resource>
<resource name="label_upload_format">Format gambar</resource>
<resource name="settings_title">Pengaturan GooglePhotos</resource>
<resource name="upload_failure">Kesalahan terjadi ketika mengunggah ke GooglePhotos:</resource>
<resource name="upload_menu_item">Unggah ke GooglePhotos</resource>
<resource name="upload_success">Berhasil mengunggah gambar ke GooglePhotos!</resource>
</resources>
</language>

View file

@ -1,32 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Italiano" ietf="it-IT" version="1.1.5">
<resources>
<resource name="label_AfterUploadLinkToClipBoard">
Collegamento agli Appunti
</resource>
<resource name="label_AfterUpload">
Dopo il caricamento
</resource>
<resource name="Configure">
Impostazioni Picasa
</resource>
<resource name="upload_menu_item">
Carica su Picasa
</resource>
<resource name="settings_title">
Impostazioni Picasa
</resource>
<resource name="upload_success">
Caricamento immagine su Picasa completato!
</resource>
<resource name="upload_failure">
Si è verificato un errore durante il caricamento su Picasa:
</resource>
<resource name="label_upload_format">
Formato immagine
</resource>
<resource name="communication_wait">
Comunicazione con Picasa...
</resource>
</resources>
</language>
<?xml version="1.0" encoding="utf-8"?>
<language description="Italiano" ietf="it-IT" version="1.1.5">
<resources>
<resource name="label_AfterUploadLinkToClipBoard">
Collegamento agli Appunti
</resource>
<resource name="label_AfterUpload">
Dopo il caricamento
</resource>
<resource name="Configure">
Impostazioni GooglePhotos
</resource>
<resource name="upload_menu_item">
Carica su GooglePhotos
</resource>
<resource name="settings_title">
Impostazioni GooglePhotos
</resource>
<resource name="upload_success">
Caricamento immagine su GooglePhotos completato!
</resource>
<resource name="upload_failure">
Si è verificato un errore durante il caricamento su GooglePhotos:
</resource>
<resource name="label_upload_format">
Formato immagine
</resource>
<resource name="communication_wait">
Comunicazione con GooglePhotos...
</resource>
</resources>
</language>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="日本語" ietf="ja-JP" version="1.0.0">
<resources>
<resource name="label_AfterUploadLinkToClipBoard">リンクをクリップボードへコピー</resource>
<resource name="label_AfterUpload">アップロード後</resource>
<resource name="Configure">GooglePhotos の設定</resource>
<resource name="upload_menu_item">GooglePhotos にアップロード</resource>
<resource name="settings_title">GooglePhotos の設定</resource>
<resource name="upload_success">GooglePhotos へのアップロードに成功しました!</resource>
<resource name="upload_failure">GooglePhotos へのアップロード中にエラーが発生しました:</resource>
<resource name="label_upload_format">画像フォーマット</resource>
<resource name="communication_wait">GooglePhotos に接続中です。しばらくお待ち下さい...</resource>
</resources>
</language>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Taqbaylit" ietf="kab-DZ" version="1.0.0" languagegroup="">
<resources>
<resource name="communication_wait">S tidett tebɣiḍ ad tekkseḍ amazray adigan n Picasa ?...</resource>
<resource name="Configure">Swel Picasa</resource>
<resource name="communication_wait">S tidett tebɣiḍ ad tekkseḍ amazray adigan n GooglePhotos ?...</resource>
<resource name="Configure">Swel GooglePhotos</resource>
<resource name="label_AfterUpload">Ticki yemmed usali</resource>
<resource name="label_AfterUploadLinkToClipBoard">Nɣel aseɣwen ɣef afus</resource>
<resource name="label_upload_format">Amsal n tugna</resource>
<resource name="settings_title">Iɣewwaṛen Picasa</resource>
<resource name="upload_failure">Teḍra-d tuccḍa deg usali ɣer Picasa :</resource>
<resource name="upload_menu_item">Sali ɣer Picasa</resource>
<resource name="upload_success">Tugna tuli ɣer Picasa !</resource>
<resource name="settings_title">Iɣewwaṛen GooglePhotos</resource>
<resource name="upload_failure">Teḍra-d tuccḍa deg usali ɣer GooglePhotos :</resource>
<resource name="upload_menu_item">Sali ɣer GooglePhotos</resource>
<resource name="upload_success">Tugna tuli ɣer GooglePhotos !</resource>
</resources>
</language>

View file

@ -8,25 +8,25 @@
얼로드 후
</resource>
<resource name="Configure">
Picasa 설정
GooglePhotos 설정
</resource>
<resource name="upload_menu_item">
Picasa로 업로드
GooglePhotos로 업로드
</resource>
<resource name="settings_title">
Picasa 설정
GooglePhotos 설정
</resource>
<resource name="upload_success">
Picasa로 이미지 업로드 성공!
GooglePhotos로 이미지 업로드 성공!
</resource>
<resource name="upload_failure">
Picasa로 업로드시 오류 발생:
GooglePhotos로 업로드시 오류 발생:
</resource>
<resource name="label_upload_format">
이미지 형식
</resource>
<resource name="communication_wait">
Picasa와 연결 중 잠시 기다리세요...
GooglePhotos와 연결 중 잠시 기다리세요...
</resource>
</resources>
</language>

View file

@ -9,25 +9,25 @@
Pēc augšupielādes
</resource>
<resource name="Configure">
Picasa iestatījumi
GooglePhotos iestatījumi
</resource>
<resource name="upload_menu_item">
Augšupieladēt uz Picasa
Augšupieladēt uz GooglePhotos
</resource>
<resource name="settings_title">
Picasa iestatījumi
GooglePhotos iestatījumi
</resource>
<resource name="upload_success">
Attēls veiksmīgi augšupielādēts uz Picasa!
Attēls veiksmīgi augšupielādēts uz GooglePhotos!
</resource>
<resource name="upload_failure">
Kļūda augšuplādējot uz Picasa:
Kļūda augšuplādējot uz GooglePhotos:
</resource>
<resource name="label_upload_format">
Attēla formāts
</resource>
<resource name="communication_wait">
Savienojos ar Picasa. Lūdzu uzgaidiet...
Savienojos ar GooglePhotos. Lūdzu uzgaidiet...
</resource>
</resources>
</language>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Polski" ietf="pl-PL" version="1.1.4" languagegroup="2">
<resources>
<resource name="communication_wait">Trwa komunikacja z GooglePhotos. Proszę czekać...</resource>
<resource name="Configure">Konfiguruj GooglePhotos</resource>
<resource name="label_AfterUpload">Po wysłaniu</resource>
<resource name="label_AfterUploadLinkToClipBoard">Link do schowka</resource>
<resource name="label_upload_format">Format obrazów</resource>
<resource name="settings_title">Ustawienia GooglePhotos</resource>
<resource name="upload_failure">Wystąpił błąd przy wysyłaniu do GooglePhotos:</resource>
<resource name="upload_menu_item">Wyślij do GooglePhotos</resource>
<resource name="upload_success">Wysyłanie obrazu do GooglePhotos powiodło się!</resource>
</resources>
</language>

View file

@ -8,25 +8,25 @@
Após enviar
</resource>
<resource name="Configure">
Configurar o Picasa
Configurar o GooglePhotos
</resource>
<resource name="upload_menu_item">
enviar para o Picasa
enviar para o GooglePhotos
</resource>
<resource name="settings_title">
Definições Picasa
Definições GooglePhotos
</resource>
<resource name="upload_success">
Imagem enviada com êxito para o Picasa!
Imagem enviada com êxito para o GooglePhotos!
</resource>
<resource name="upload_failure">
Ocorreu um erro ao enviar para o Picasa:
Ocorreu um erro ao enviar para o GooglePhotos:
</resource>
<resource name="label_upload_format">
Formato da imagem
</resource>
<resource name="communication_wait">
A comunicar com o Picasa. Por favor aguarde...
A comunicar com o GooglePhotos. Por favor aguarde...
</resource>
</resources>
</language>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Русский" ietf="ru-RU" version="1.1.0.2515" languagegroup="5">
<resources>
<resource name="communication_wait">Обмен данными с Picasa. Подождите...</resource>
<resource name="Configure">Настройка Picasa</resource>
<resource name="label_AfterUpload">После загрузки</resource>
<resource name="label_AfterUploadLinkToClipBoard">Ссылки в буфер обмена</resource>
<resource name="label_upload_format">Формат изображения</resource>
<resource name="settings_title">Настройки Picasa</resource>
<resource name="upload_failure">Произошла ошибка при загрузке на Picasa:</resource>
<resource name="upload_menu_item">Загрузить на Picasa</resource>
<resource name="upload_success">Изображение успешно загружено на Picasa!</resource>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<language description="Русский" ietf="ru-RU" version="1.1.0.2515" languagegroup="5">
<resources>
<resource name="communication_wait">Обмен данными с GooglePhotos. Подождите...</resource>
<resource name="Configure">Настройка GooglePhotos</resource>
<resource name="label_AfterUpload">После загрузки</resource>
<resource name="label_AfterUploadLinkToClipBoard">Ссылки в буфер обмена</resource>
<resource name="label_upload_format">Формат изображения</resource>
<resource name="settings_title">Настройки GooglePhotos</resource>
<resource name="upload_failure">Произошла ошибка при загрузке на GooglePhotos:</resource>
<resource name="upload_menu_item">Загрузить на GooglePhotos</resource>
<resource name="upload_success">Изображение успешно загружено на GooglePhotos!</resource>
</resources>
</language>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Српски" ietf="sr-RS" version="1.0.5" languagegroup="">
<resources>
<resource name="communication_wait">Комуницирам с Пикасом. Сачекајте…</resource>
<resource name="Configure">Поставке Пикасе</resource>
<resource name="label_AfterUpload">Након отпремања:</resource>
<resource name="label_AfterUploadLinkToClipBoard">Веза ка остави</resource>
<resource name="label_upload_format">Формат слике:</resource>
<resource name="settings_title">Поставке Пикасе</resource>
<resource name="upload_failure">Дошло је до грешке при отпремању на Пикасу:</resource>
<resource name="upload_menu_item">Отпреми на Пикасу</resource>
<resource name="upload_success">Слика је успешно отпремљена на Пикасу.</resource>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<language description="Српски" ietf="sr-RS" version="1.0.5" languagegroup="">
<resources>
<resource name="communication_wait">Комуницирам с Пикасом. Сачекајте…</resource>
<resource name="Configure">Поставке Пикасе</resource>
<resource name="label_AfterUpload">Након отпремања:</resource>
<resource name="label_AfterUploadLinkToClipBoard">Веза ка остави</resource>
<resource name="label_upload_format">Формат слике:</resource>
<resource name="settings_title">Поставке Пикасе</resource>
<resource name="upload_failure">Дошло је до грешке при отпремању на Пикасу:</resource>
<resource name="upload_menu_item">Отпреми на Пикасу</resource>
<resource name="upload_success">Слика је успешно отпремљена на Пикасу.</resource>
</resources>
</language>

View file

@ -8,25 +8,25 @@
Vid uppladdning
</resource>
<resource name="Configure">
Konfigurera Picasa
Konfigurera GooglePhotos
</resource>
<resource name="upload_menu_item">
Ladda upp till Picasa
Ladda upp till GooglePhotos
</resource>
<resource name="settings_title">
Picasa-inställningar
GooglePhotos-inställningar
</resource>
<resource name="upload_success">
Skärmdumpen laddades upp till Picasa!
Skärmdumpen laddades upp till GooglePhotos!
</resource>
<resource name="upload_failure">
Ett fel uppstod vid uppladdning till Picasa:
Ett fel uppstod vid uppladdning till GooglePhotos:
</resource>
<resource name="label_upload_format">
Bildformat
</resource>
<resource name="communication_wait">
Kommunicerar med Picasa. Vänta...
Kommunicerar med GooglePhotos. Vänta...
</resource>
</resources>
</language>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="Українська" ietf="uk-UA" version="1.0.0">
<resources>
<resource name="label_AfterUploadLinkToClipBoard">Посилання в буфер обміну</resource>
<resource name="label_AfterUpload">Після вивантаження</resource>
<resource name="Configure">Налаштувати Picasa</resource>
<resource name="upload_menu_item">Вивантажити на Picasa</resource>
<resource name="settings_title">Параметри Picasa</resource>
<resource name="upload_success">Зображення вдало вивантажено на Picasa!</resource>
<resource name="upload_failure">Відбулась помилка під час вивантаження на Picasa:</resource>
<resource name="label_upload_format">Формат зображення</resource>
<resource name="communication_wait">З’єднання з Picasa. Будь ласка, зачекайте...</resource>
</resources>
</language>
<?xml version="1.0" encoding="utf-8"?>
<language description="Українська" ietf="uk-UA" version="1.0.0">
<resources>
<resource name="label_AfterUploadLinkToClipBoard">Посилання в буфер обміну</resource>
<resource name="label_AfterUpload">Після вивантаження</resource>
<resource name="Configure">Налаштувати GooglePhotos</resource>
<resource name="upload_menu_item">Вивантажити на GooglePhotos</resource>
<resource name="settings_title">Параметри GooglePhotos</resource>
<resource name="upload_success">Зображення вдало вивантажено на GooglePhotos!</resource>
<resource name="upload_failure">Відбулась помилка під час вивантаження на GooglePhotos:</resource>
<resource name="label_upload_format">Формат зображення</resource>
<resource name="communication_wait">З’єднання з GooglePhotos. Будь ласка, зачекайте...</resource>
</resources>
</language>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="简体中文" ietf="zh-CN" version="1.0.3" languagegroup="a">
<resources>
<resource name="communication_wait">正在连接到GooglePhotos。请稍后...</resource>
<resource name="Configure">配置 GooglePhotos</resource>
<resource name="label_AfterUpload">上传之后</resource>
<resource name="label_AfterUploadLinkToClipBoard">复制链接到剪贴板</resource>
<resource name="label_upload_format">图片格式</resource>
<resource name="settings_title">GooglePhotos设置</resource>
<resource name="upload_failure">上传到GooglePhotos时发生错误</resource>
<resource name="upload_menu_item">上传到GooglePhotos</resource>
<resource name="upload_success">图片已成功上传到了GooglePhotos</resource>
</resources>
</language>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<language description="正體中文" ietf="zh-TW" version="1.0.0" languagegroup="9">
<resources>
<resource name="communication_wait">正在與 GooglePhotos 通訊,請稍候...</resource>
<resource name="Configure">組態 GooglePhotos</resource>
<resource name="label_AfterUpload">上傳後</resource>
<resource name="label_AfterUploadLinkToClipBoard">連結到剪貼簿</resource>
<resource name="label_upload_format">圖片格式</resource>
<resource name="settings_title">GooglePhotos 設定</resource>
<resource name="upload_failure">上傳到 GooglePhotos 時發生錯誤:</resource>
<resource name="upload_menu_item">上傳到 GooglePhotos</resource>
<resource name="upload_success">上傳圖片到 GooglePhotos 成功!</resource>
</resources>
</language>

View file

@ -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.

View file

@ -25,7 +25,7 @@ namespace GreenshotImgurPlugin {
/// You can set your own values here
/// </summary>
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}";
}
}

View file

@ -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<ImgurConfiguration>();
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";
/// <summary>
/// <summary>
/// Check if we need to load the history
/// </summary>
/// <returns></returns>
@ -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;

View file

@ -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
}

View file

@ -80,39 +80,7 @@ namespace GreenshotJiraPlugin
return keyObject.ToString();
}
/// <summary>
/// Get an element from the cache, if this is not available call the create function.
/// </summary>
/// <param name="keyObject">object for the key</param>
/// <param name="cancellationToken">CancellationToken</param>
/// <returns>TResult</returns>
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();
}
}
/// <summary>
/// Get a task element from the cache, if this is not available return null.
/// You probably want to call GetOrCreateAsync
/// </summary>
/// <param name="keyObject">object for the key</param>
/// <returns>Task with TResult, null if no value</returns>
public Task<TResult> GetAsync(TKey keyObject)
{
var key = CreateKey(keyObject);
return _cache.Get(key) as Task<TResult> ?? EmptyValueTask;
}
/// <summary>
/// <summary>
/// Get a task element from the cache, if this is not available call the create function.
/// </summary>
/// <param name="keyObject">object for the key</param>
@ -124,20 +92,7 @@ namespace GreenshotJiraPlugin
return _cache.Get(key) as Task<TResult> ?? GetOrCreateInternalAsync(keyObject, null, cancellationToken);
}
/// <summary>
/// Get a task element from the cache, if this is not available call the create function.
/// </summary>
/// <param name="keyObject">object for the key</param>
/// <param name="cacheItemPolicy">CacheItemPolicy for when you want more control over the item</param>
/// <param name="cancellationToken">CancellationToken</param>
/// <returns>Task with TResult</returns>
public Task<TResult> GetOrCreateAsync(TKey keyObject, CacheItemPolicy cacheItemPolicy, CancellationToken cancellationToken = default)
{
var key = CreateKey(keyObject);
return _cache.Get(key) as Task<TResult> ?? GetOrCreateInternalAsync(keyObject, cacheItemPolicy, cancellationToken);
}
/// <summary>
/// <summary>
/// This takes care of the real async part of the code.
/// </summary>
/// <param name="keyObject"></param>
@ -213,7 +168,7 @@ namespace GreenshotJiraPlugin
/// Override to know when an item is removed, make sure to configure ActivateUpdateCallback / ActivateRemovedCallback
/// </summary>
/// <param name="cacheEntryRemovedArguments">CacheEntryRemovedArguments</param>
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
/// </summary>
/// <param name="cacheEntryUpdateArguments">CacheEntryUpdateArguments</param>
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);
}

View file

@ -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")]

View file

@ -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,
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 {
/// <summary>
/// Wraps a late-bound COM server.
/// </summary>
public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo {
private const int MK_E_UNAVAILABLE = -2147221021;
private const int CO_E_CLASSSTRING = -2147221005;
/// <summary>
/// Holds reference to the actual COM object which is wrapped by this proxy
/// </summary>
private readonly object _comObject;
/// <summary>
/// Type of the COM object, set on constructor after getting the COM reference
/// </summary>
private readonly Type _comType;
/// <summary>
/// The type of which method calls are intercepted and executed on the COM object.
/// </summary>
private readonly Type _interceptType;
/// <summary>
/// Gets a COM object and returns the transparent proxy which intercepts all calls to the object
/// </summary>
/// <typeparam name="T">Interface which defines the method and properties to intercept</typeparam>
/// <returns>Transparent proxy to the real proxy for the object</returns>
/// <remarks>T must be an interface decorated with the <see cref="ComProgIdAttribute"/>attribute.</remarks>
public static T GetInstance<T>() {
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;
}
/// <summary>
/// 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:"
/// </summary>
/// <typeparam name="T">Interface which defines the method and properties to intercept</typeparam>
/// <returns>Transparent proxy to the real proxy for the object</returns>
/// <remarks>The type must be an interface decorated with the <see cref="ComProgIdAttribute"/>attribute.</remarks>
public static T GetOrCreateInstance<T>() {
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;
}
/// <summary>
/// Wrap an object and return the transparent proxy which intercepts all calls to the object
/// </summary>
/// <param name="comObject">An object to intercept</param>
/// <param name="type">Interface which defines the method and properties to intercept</param>
/// <returns>Transparent proxy to the real proxy for the object</returns>
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();
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="comObject">
/// The COM object to wrap.
/// </param>
/// <param name="type">
/// The interface type to impersonate.
/// </param>
private COMWrapper(object comObject, Type type)
: base(type) {
_comObject = comObject;
_comType = comObject.GetType();
_interceptType = type;
}
/// <summary>
/// If <see cref="Dispose"/> is not called, we need to make
/// sure that the COM object is still cleaned up.
/// </summary>
~COMWrapper() {
Dispose(false);
}
/// <summary>
/// Cleans up the COM object.
/// </summary>
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Release the COM reference
/// </summary>
/// <param name="disposing">
/// <see langword="true"/> if this was called from the
/// <see cref="IDisposable"/> interface.
/// </param>
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);
}
}
}
}
/// <summary>
/// Returns a string representing the wrapped object.
/// </summary>
/// <returns>
/// The full name of the intercepted type.
/// </returns>
public override string ToString() {
return _interceptType.FullName;
}
/// <summary>
/// Returns the hash code of the wrapped object.
/// </summary>
/// <returns>
/// The hash code of the wrapped object.
/// </returns>
public override int GetHashCode() {
return _comObject.GetHashCode();
}
/// <summary>
/// Compares this object to another.
/// </summary>
/// <param name="value">
/// The value to compare to.
/// </param>
/// <returns>
/// <see langword="true"/> if the objects are equal.
/// </returns>
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);
}
/// <summary>
/// Returns the base type for a reference type.
/// </summary>
/// <param name="byRefType">
/// The reference type.
/// </param>
/// <returns>
/// The base value type.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="byRefType"/> is <see langword="null"/>.
/// </exception>
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;
}
/// <summary>
/// Intercept method calls
/// </summary>
/// <param name="myMessage">
/// Contains information about the method being called
/// </param>
/// <returns>
/// A <see cref="ReturnMessage"/>.
/// </returns>
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);
}
/// <summary>
/// Implementation for the interface IRemotingTypeInfo
/// This makes it possible to cast the COMWrapper
/// </summary>
/// <param name="toType">Type to cast to</param>
/// <param name="o">object to cast</param>
/// <returns></returns>
public bool CanCastTo(Type toType, object o) {
bool returnValue = _interceptType.IsAssignableFrom(toType);
return returnValue;
}
/// <summary>
/// Implementation for the interface IRemotingTypeInfo
/// </summary>
public string TypeName {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace GreenshotOCRCommand {
/// <summary>
/// An attribute to specifiy the ProgID of the COM class to create. (As suggested by Kristen Wegner)
/// </summary>
[AttributeUsage(AttributeTargets.Interface)]
public sealed class ComProgIdAttribute : Attribute {
/// <summary>
/// Extracts the attribute from the specified type.
/// </summary>
/// <param name="interfaceType">
/// The interface type.
/// </param>
/// <returns>
/// The <see cref="ComProgIdAttribute"/>.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="interfaceType"/> is <see langword="null"/>.
/// </exception>
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];
}
/// <summary>Constructor</summary>
/// <param name="value">The COM ProgID.</param>
public ComProgIdAttribute(string value) {
Value = value;
}
/// <summary>
/// Returns the COM ProgID
/// </summary>
public string Value { get; }
}
}

View file

@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<RootNamespace>GreenshotOCRCommand</RootNamespace>
<AssemblyName>GreenshotOCRCommand</AssemblyName>
<OutputType>WinExe</OutputType>
</PropertyGroup>
<ItemGroup>
<Reference Include="CustomMarshalers" />
</ItemGroup>
<Target Name="PostBuild" BeforeTargets="PostBuildEvent" Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<Exec Command="xcopy /q /y /d &quot;$(TargetDir)*.exe&quot; &quot;$(SolutionDir)$(SolutionName)\$(OutDir)&quot;" />
</Target>
</Project>

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotOCRCommand.Modi
{
public enum CompressionLevel {
miCOMP_LEVEL_LOW = 0,
miCOMP_LEVEL_MEDIUM = 1,
miCOMP_LEVEL_HIGH = 2
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotOCRCommand.Modi
{
public enum FileFormat {
miFILE_FORMAT_DEFAULTVALUE = -1,
miFILE_FORMAT_TIFF = 1,
miFILE_FORMAT_TIFF_LOSSLESS = 2,
miFILE_FORMAT_MDI = 4
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
namespace GreenshotOCRCommand.Modi
{
/// <summary>
/// Base class for the common properties of the Modi interfaces
/// </summary>
public interface ICommon : IDisposable {
IDocument Application { get; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotOCRCommand.Modi {
/// <summary>
/// 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.
/// </summary>
[ComProgId("MODI.Document")]
public interface IDocument : ICommon {
/// <summary>
/// Closes the document.
/// </summary>
/// <param name="saveCall"></param>
void Close(bool saveCall);
/// <summary>
/// The document's collection of pages.
/// </summary>
IImages Images
{
get;
}
/// <summary>
/// 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.
/// </summary>
// event OnOCRProgress { get; }
/// <summary>
/// Indicates whether the active document has unsaved changes.
/// </summary>
bool Dirty { get; }
/// <summary>
/// Creates a new document.
/// </summary>
/// <param name="file">Optional String. The path and filename of the optional document file that is to be loaded into the new document.</param>
void Create(string file);
/// <summary>
/// Performs optical character recognition (OCR) on the specified document or image.
/// </summary>
/// <param name="language">ModiLanguage</param>
/// <param name="orientimage">Optional Boolean. Specifies whether the OCR engine attempts to determine the orientation of the page. Default is true.</param>
/// <param name="straightenImage">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.</param>
void OCR(ModiLanguage language, bool orientimage, bool straightenImage);
/// <summary>
///
/// </summary>
/// <param name="filename"></param>
/// <param name="fileFormat"></param>
/// <param name="compressionLevel"></param>
void SaveAs(string filename, FileFormat fileFormat, CompressionLevel compressionLevel);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotOCRCommand.Modi
{
/// <summary>
/// Describes the page in a scan
/// </summary>
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; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Collections;
namespace GreenshotOCRCommand.Modi
{
/// <summary>
/// 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.
/// </summary>
public interface IImages : ICommon, IEnumerable {
int Count {
get;
}
IImage this [int index] {
get;
}
new IEnumerator GetEnumerator();
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotOCRCommand.Modi
{
/// <summary>
/// Layout of the IImage
/// </summary>
public interface ILayout : ICommon {
/// <summary>
/// Returns the recognized text as a Unicode string.
/// </summary>
string Text {
get;
}
/// <summary>
/// An accessor property that returns the Words collection recognized in the text during an optical character recognition (OCR) operation.
/// </summary>
IWords Words { get; }
/// <summary>
/// Returns the number of characters in the recognized text.
/// </summary>
int NumChars { get; }
/// <summary>
/// Returns the number of words in the recognized text.
/// </summary>
int NumWords { get; }
/// <summary>
/// Returns the language identifier for the recognized text. Read-only Long.
/// </summary>
ModiLanguage Language { get; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotOCRCommand.Modi
{
/// <summary>
/// Represents a bounding rectangle in the optical character recognition (OCR) layout.
/// </summary>
public interface IMiRect : ICommon {
/// <summary>
/// The Bottom property represent the distance in pixels from the top edge of the containing image.
/// </summary>
int Bottom { get; }
/// <summary>
/// The Left property represent the distance in pixels from the left edge of the containing image.
/// </summary>
int Left { get; }
/// <summary>
/// The Right property represent the distance in pixels from the left edge of the containing image.
/// </summary>
int Right { get; }
/// <summary>
/// The Top property represent the distance in pixels from the top edge of the containing image.
/// </summary>
int Top { get; }
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
using System.Collections;
namespace GreenshotOCRCommand.Modi
{
/// <summary>
/// Represents the collection of bounding rectangles in the optical character recognition (OCR) layout. A collection of MiRect objects.
/// </summary>
public interface IMiRects : ICommon, IEnumerable {
int Count {
get;
}
IMiRect this [int index] {
get;
}
new IEnumerator GetEnumerator();
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
namespace GreenshotOCRCommand.Modi
{
/// <summary>
/// Represents a word recognized in the text during an optical character recognition (OCR) operation.
/// </summary>
public interface IWord : ICommon
{
/// <summary>
/// Returns the index of the specified word in the Words collection of the Layout or IMiSelectableItem object.
/// </summary>
long Id { get; }
/// <summary>
/// Returns the number of the region in the optical character recognition (OCR) layout where the word occurs.
/// </summary>
long RegionId { get; }
/// <summary>
/// Returns the number of the line in the optical character recognition (OCR) layout where the word occurs.
/// </summary>
long LineId { get; }
/// <summary>
/// Returns the recognized text as a Unicode string.
/// </summary>
string Text { get; }
/// <summary>
/// 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.
/// </summary>
short RecognitionConfidence { get; }
/// <summary>
/// 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.
/// </summary>
long FontId { get; }
/// <summary>
/// Rectangles
/// </summary>
IMiRects Rects { get; }
}
}

Some files were not shown because too many files have changed in this diff Show more