Merge branch 'release/v3.5.1'

This commit is contained in:
Lorenz Cuno Klopfenstein 2018-04-10 23:39:22 +02:00
commit 4f7343576a
237 changed files with 28882 additions and 28199 deletions

5
.gitignore vendored
View file

@ -1,8 +1,9 @@
.vs/*
**/.vs/*
**/bin/*
**/obj/*
**/publish/*
Installer/OnTopReplica-Setup.exe
src/Installer/output/*
*.user
*.suo
packages/
src/packages/*

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -1,55 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2008
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnTopReplica", "OnTopReplica\OnTopReplica.csproj", "{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x64.ActiveCfg = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x64.Build.0 = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x86.ActiveCfg = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x86.Build.0 = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|Any CPU.Build.0 = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x64.ActiveCfg = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x64.Build.0 = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x86.ActiveCfg = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x86.Build.0 = Release|Any CPU
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|x64.ActiveCfg = Debug|x64
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|x64.Build.0 = Debug|x64
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|x64.Deploy.0 = Debug|x64
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|x86.ActiveCfg = Debug|x86
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|x86.Build.0 = Debug|x86
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Debug|x86.Deploy.0 = Debug|x86
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|Any CPU.Build.0 = Release|Any CPU
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|Any CPU.Deploy.0 = Release|Any CPU
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|x64.ActiveCfg = Release|x64
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|x64.Build.0 = Release|x64
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|x64.Deploy.0 = Release|x64
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|x86.ActiveCfg = Release|x86
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|x86.Build.0 = Release|x86
{01391A7F-A9A1-4C90-89EB-29E0C98BF9BE}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3F135F78-F70E-4127-BA77-6C262C7CCCEF}
EndGlobalSection
EndGlobal

View file

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishUrlHistory>publish\</PublishUrlHistory>
<InstallUrlHistory>http://www.klopfenstein.net/public/Uploads/ontopreplica/|http://www.klopfenstein.net/download.aspx%3ffile=ontopreplica%252fsetup.exe/|http://www.klopfenstein.net/lorenz/programming/ontopreplica/|http://www.klopfenstein.net/lorenz/programming/|http://lorenz.klopfenstein.net/</InstallUrlHistory>
<SupportUrlHistory>http://www.klopfenstein.net/lorenz.aspx/ontopreplica|http://www.klopfenstein.net/loader.php%3fsection=lorenz&amp;page=on_top_replica|http://www.klopfenstein.net/loader.php%3fsection=lorenz&amp;page=programming_on_top_replica</SupportUrlHistory>
<UpdateUrlHistory>http://www.klopfenstein.net/public/Uploads/ontopreplica/|http://www.klopfenstein.net/lorenz/programming/ontopreplica/</UpdateUrlHistory>
<BootstrapperUrlHistory>
</BootstrapperUrlHistory>
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
<ErrorReportUrlHistory>
</ErrorReportUrlHistory>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
<PropertyGroup>
<EnableSecurityDebugging>false</EnableSecurityDebugging>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<StartArguments>
</StartArguments>
</PropertyGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

View file

@ -28,7 +28,7 @@ Very useful for monitoring background processes, wrangling with complex multi-wi
## Installation
Get the [latest version (v.3.5.1)](https://github.com/paulodeleo/OnTopReplica/releases/tag/v3.5.1) from the releases section, both as installer and as a standalone portable executable.
Get the [latest version](/releases/) from the releases section.
## Contributions

33
src/.editorconfig Normal file
View file

@ -0,0 +1,33 @@
root = true
[*]
insert_final_newline = true
trim_trailing_whitespace = true
[*.cs]
indent_style = space
indent_size = tab
tab_size = 4
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
csharp_style_inlined_variable_declaration = true
csharp_style_conditional_delegate_call = true
csharp_prefer_braces = true
dotnet_sort_system_directives_first = true
csharp_new_line_before_open_brace = false
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 = false
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_preserve_single_line_blocks = true

File diff suppressed because it is too large Load diff

280
src/Installer/License.rtf Normal file
View file

@ -0,0 +1,280 @@
{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}
{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f380\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f381\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}
{\f383\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f384\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f387\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f388\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}
{\f410\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f411\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f413\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f414\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
{\f415\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f416\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\f417\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f418\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}
{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}
{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}
{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}
{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;
\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\sb240\sa60\sl259\slmult1
\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs32\alang1025 \ltrch\fcs0 \b\fs32\lang1033\langfe1033\kerning32\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033
\sbasedon0 \snext0 \slink15 \sqformat \spriority9 \styrsid12543645 heading 1;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\*
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused
Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\kerning32\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 \styrsid12543645 Heading 1 Char;}{\s16\ql \li0\ri0\sa160\sl259\slmult1\widctlpar
\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033
\sbasedon0 \snext16 \slink17 \sunhideused \styrsid3805024 header;}{\*\cs17 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \sbasedon10 \slink16 \slocked \styrsid3805024 Header Char;}{\s18\ql \li0\ri0\sa160\sl259\slmult1\widctlpar
\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033
\sbasedon0 \snext18 \slink19 \sunhideused \styrsid3805024 footer;}{\*\cs19 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \sbasedon10 \slink18 \slocked \styrsid3805024 Footer Char;}}{\*\listtable{\list\listtemplateid-620591136\listhybrid{\listlevel\levelnfc0
\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67698703\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc3\levelnfcn3\leveljc0
\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid1300900046\'03(\'01);}{\levelnumbers\'02;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2
\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698715\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0
\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698703\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1
\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698713\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative
\levelspace0\levelindent0{\leveltext\leveltemplateid67698715\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0
\levelindent0{\leveltext\leveltemplateid67698703\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
{\leveltext\leveltemplateid67698713\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
\leveltemplateid67698715\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid537085589}}{\*\listoverridetable{\listoverride\listid537085589\listoverridecount0\ls1}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0
\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid3504841\rsid3559829\rsid3805024\rsid3959765\rsid10841800\rsid12543645}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}
{\info{\creatim\yr2018\mo4\dy1\hr15\min39}{\revtim\yr2018\mo4\dy1\hr15\min40}{\version1}{\edmins0}{\nofpages2}{\nofwords441}{\nofchars2520}{\nofcharsws2956}{\vern57443}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}
\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701
\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rempersonalinfo\rsidroot12543645\remdttm \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0{\*\ftnsep \ltrpar \pard\plain \ltrpar
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3805024 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1
\af0 \ltrch\fcs0 \insrsid3504841 \chftnsep
\par }}{\*\ftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3805024 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3504841 \chftnsepc
\par }}{\*\aftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3805024 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3504841 \chftnsep
\par }}{\*\aftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3805024 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3504841 \chftnsepc
\par }}\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\headerl \ltrpar \pard\plain \ltrpar\s16\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1
\af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3805024
\par }}{\headerr \ltrpar \pard\plain \ltrpar\s16\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3805024
\par }}{\footerl \ltrpar \pard\plain \ltrpar\s18\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3805024
\par }}{\footerr \ltrpar \pard\plain \ltrpar\s18\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3805024
\par }}{\headerf \ltrpar \pard\plain \ltrpar\s16\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3805024
\par }}{\footerf \ltrpar \pard\plain \ltrpar\s18\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid3805024
\par }}{\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}
{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8
\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\qc \li0\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12543645 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af37
\ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 Microsoft Reciprocal License (M}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3559829 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af37 \ltrch\fcs0
\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 -RL)}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid10841800\charrsid12543645
\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12543645 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765\charrsid12543645
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 1.\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\adjustright\rin0\lin720\itap0\pararsid3959765 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 Definitions}{\rtlch\fcs1 \af37 \ltrch\fcs0
\insrsid3959765
\par }\pard \ltrpar\ql \li720\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\pararsid3959765 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506
The terms "reproduce," "reproduction," "derivative works," and "distribution"\hich\af31506\dbch\af31505\loch\f31506 have the same meaning he}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765 \hich\af31506\dbch\af31505\loch\f31506
re as under U.S. copyright law.
\par }{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 A "contribution" is the original software, or any additions or changes to the software.}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765
\par }{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 A "contributor" is any person that distributes its contribution under this license.}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765
\par }{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 "Licensed patents" are a c\hich\af31506\dbch\af31505\loch\f31506 ontributor's patent claims that read directly on its contribution.}{\rtlch\fcs1
\af37 \ltrch\fcs0 \insrsid3959765\charrsid12543645
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 2.\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\adjustright\rin0\lin720\itap0\pararsid3959765 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 Grant of Rights}{\rtlch\fcs1 \af37 \ltrch\fcs0
\insrsid3959765
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid3959765 \hich\af31506\dbch\af31505\loch\f31506 (A)\tab}}\pard \ltrpar\ql \fi-360\li1080\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\ilvl1\adjustright\rin0\lin1080\itap0\pararsid3959765 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid3959765 \hich\af31506\dbch\af31505\loch\f31506
Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, wor\hich\af31506\dbch\af31505\loch\f31506
ldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any de}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765\charrsid3959765
\hich\af31506\dbch\af31505\loch\f31506 rivative works that you create.}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid3959765 \hich\af31506\dbch\af31505\loch\f31506 (B)\tab}}\pard \ltrpar\ql \fi-360\li1440\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\ilvl1\adjustright\rin0\lin1440\itap0\pararsid3959765 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid3959765 \hich\af31506\dbch\af31505\loch\f31506
Patent Grant- Subject to the terms of this license, including t\hich\af31506\dbch\af31505\loch\f31506
he license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution
\hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 in the software or derivative works of the contribution in the software.}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765\charrsid3959765
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid3959765 \hich\af31506\dbch\af31505\loch\f31506 3.\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\adjustright\rin0\lin720\itap0\pararsid3959765 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765 \hich\af31506\dbch\af31505\loch\f31506 C}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645
\hich\af31506\dbch\af31505\loch\f31506 onditions and Limitations}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 (A)\tab}}\pard \ltrpar\ql \fi-360\li1440\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\ilvl1\adjustright\rin0\lin1440\itap0\pararsid3959765 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506
Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients th\hich\af31506\dbch\af31505\loch\f31506
e source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the softw}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765
\hich\af31506\dbch\af31505\loch\f31506 are under any terms you choose.
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 (B)\tab}}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645
\hich\af31506\dbch\af31505\loch\f31506 No Trademark License- T\hich\af31506\dbch\af31505\loch\f31506 his license does not grant you rights to use any contribut}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765 \hich\af31506\dbch\af31505\loch\f31506
ors' name, logo, or trademarks.
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 (C)\tab}}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645
\hich\af31506\dbch\af31505\loch\f31506 If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the so\hich\af31506\dbch\af31505\loch\f31506 f}{\rtlch\fcs1
\af37 \ltrch\fcs0 \insrsid3959765 \hich\af31506\dbch\af31505\loch\f31506 tware ends automatically.
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 (D)\tab}}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645
\hich\af31506\dbch\af31505\loch\f31506 If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices th}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765 \hich\af31506\dbch\af31505\loch\f31506
at are present in the software.
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 (E)\tab}}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645
\hich\af31506\dbch\af31505\loch\f31506 If you distribute any portion of the software in source code form,\hich\af31506\dbch\af31505\loch\f31506
you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.}
{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid3959765
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f31506\fs22\insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506 (F)\tab}}\pard \ltrpar\ql \fi-360\li1440\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\ilvl1\adjustright\rin0\lin1440\itap0\pararsid12543645 {\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid12543645 \hich\af31506\dbch\af31505\loch\f31506
The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitt
\hich\af31506\dbch\af31505\loch\f31506 ed under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.}{\rtlch\fcs1 \af37 \ltrch\fcs0 \insrsid12543645\charrsid3959765
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100aa5225dfc60600008b1a0000160000007468656d652f7468656d652f
7468656d65312e786d6cec595d8bdb46147d2ff43f08bd3bfe92fcb1c41b6cd9ceb6d94d42eca4e4716c8fadc98e344633de8d0981923c160aa569e943037deb
43691b48a02fe9afd936a54d217fa17746b63c638fbb9b2585a5640d8b343af7ce997bafce1d4997afdc8fa87384134e58dc708b970aae83e3211b9178d2706f
f7bbb99aeb7081e211a22cc60d778eb97b65f7c30f2ea31d11e2083b601ff31dd4704321a63bf93c1fc230e297d814c7706dcc920809384d26f951828ec16f44
f3a542a1928f10895d274611b8bd311e932176fad2a5bbbb74dea1701a0b2e078634e949d7d8b050d8d1615122f89c0734718e106db830cf881df7f17de13a14
7101171a6e41fdb9f9ddcb79b4b330a2628bad66d7557f0bbb85c1e8b0a4e64c26836c52cff3bd4a33f3af00546ce23ad54ea553c9fc29001a0e61a52917dda7
dfaab7dafe02ab81d2438bef76b55d2e1a78cd7f798373d3973f03af40a97f6f03dfed06104503af4029dedfc07b5eb51478065e81527c65035f2d34db5ed5c0
2b5048497cb8812ef89572b05c6d061933ba6785d77daf5b2d2d9caf50500d5975c929c62c16db6a2d42f758d2058004522448ec88f9148fd110aa3840940c12
e2ec93490885374531e3305c2815ba8532fc973f4f1da988a01d8c346bc90b98f08d21c9c7e1c3844c45c3fd18bcba1ae4cdcb1fdfbc7cee9c3c7a71f2e89793
c78f4f1efd9c3a32acf6503cd1ad5e7fffc5df4f3f75fe7afeddeb275fd9f15cc7fffed367bffdfaa51d082b5d85e0d5d7cffe78f1ecd5379ffff9c3130bbc99
a0810eef930873e73a3e766eb10816a6426032c783e4ed2cfa2122ba45339e701423398bc57f478406fafa1c5164c1b5b019c13b09488c0d787576cf20dc0b93
9920168fd7c2c8001e30465b2cb146e19a9c4b0b737f164fec9327331d770ba123dbdc018a8dfc766653d05662731984d8a07993a258a0098eb170e4357688b1
6575770931e27a408609e36c2c9cbbc46921620d499f0c8c6a5a19ed9108f232b711847c1bb139b8e3b418b5adba8d8f4c24dc15885ac8f73135c27815cd048a
6c2efb28a27ac0f791086d247bf364a8e33a5c40a6279832a733c29cdb6c6e24b05e2de9d7405eec693fa0f3c84426821cda7cee23c674649b1d06218aa6366c
8fc4a18efd881f428922e7261336f80133ef10790e7940f1d674df21d848f7e96a701b9455a7b42a107965965872791533a37e7b733a4658490d08bfa1e71189
4f15f73559f7ff5b5907217df5ed53cbaa2eaaa0371362bda3f6d6647c1b6e5dbc03968cc8c5d7ee369ac53731dc2e9b0decbd74bf976ef77f2fdddbeee7772f
d82b8d06f9965bc574abae36eed1d67dfb9850da13738af7b9daba73e84ca32e0c4a3bf5cc8ab3e7b8690887f24e86090cdc2441cac64998f88488b017a229ec
ef8bae7432e10bd713ee4c19876dbf1ab6fa96783a8b0ed8287d5c2d16e5a3692a1e1c89d578c1cfc6e15143a4e84a75f50896b9576c27ea51794940dabe0d09
6d329344d942a2ba1c9441520fe610340b09b5b277c2a26e615193ee97a9da6001d4b2acc0d6c9810d57c3f53d30012378a242148f649ed2542fb3ab92f92e33
bd2d984605c03e625901ab4cd725d7adcb93ab4b4bed0c99364868e566925091513d8c87688417d52947cf42e36d735d5fa5d4a02743a1e683d25ad1a8d6fe8d
c579730d76ebda40635d2968ec1c37dc4ad9879219a269c31dc3633f1c4653a81d2eb7bc884ee0ddd95024e90d7f1e6599265cb4110fd3802bd149d520220227
0e2551c395cbcfd24063a5218a5bb104827061c9d541562e1a3948ba99643c1ee3a1d0d3ae8dc848a7a7a0f0a95658af2af3f383a5259b41ba7be1e8d819d059
720b4189f9d5a20ce0887078fb534ca33922f03a3313b255fdad35a685eceaef13550da5e3884e43b4e828ba98a77025e5191d7596c5403b5bac1902aa8564d1
080713d960f5a01add34eb1a2987ad5df7742319394d34573dd35015d935ed2a66ccb06c036bb13c5f93d7582d430c9aa677f854bad725b7bed4bab57d42d625
20e059fc2c5df70c0d41a3b69acca026196fcab0d4ecc5a8d93b960b3c85da599a84a6fa95a5dbb5b8653dc23a1d0c9eabf383dd7ad5c2d078b9af549156df3d
f44f136c700fc4a30d2f81675470954af8f09020d810f5d49e24950db845ee8bc5ad0147ce2c210df741c16f7a41c90f72859adfc97965af90abf9cd72aee9fb
e562c72f16daadd243682c228c8a7efacda50bafa2e87cf1e5458d6f7c7d89966fdb2e0d599467eaeb4a5e11575f5f8aa5ed5f5f1c02a2f3a052ead6cbf55625
572f37bb39afddaae5ea41a5956b57826abbdb0efc5abdfbd0758e14d86b9603afd2a9e52ac520c8799582a45fabe7aa5ea9d4f4aacd5ac76b3e5c6c6360e5a9
7c2c6201e155bc76ff010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f
7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be
9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980
ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5b
babac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000000000000000000000000000005b436f6e74656e
745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f
2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000190200007468656d652f7468656d652f74
68656d654d616e616765722e786d6c504b01022d0014000600080000002100aa5225dfc60600008b1a00001600000000000000000000000000d6020000746865
6d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000d00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000cb0a00000000}
{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;
\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;
\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;
\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;
\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;
\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;
\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;
\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000
4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000609c
cc3cf1c9d301feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000105000000000000}}

65
src/OnTopReplica.sln Normal file
View file

@ -0,0 +1,65 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2008
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnTopReplica", "OnTopReplica\OnTopReplica.csproj", "{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}"
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Installer", "Installer\Installer.vdproj", "{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostInstaller", "PostInstaller\PostInstaller.csproj", "{05F8E270-8B47-449B-8755-4599B3B3A565}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x64.ActiveCfg = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x64.Build.0 = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x86.ActiveCfg = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Debug|x86.Build.0 = Debug|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|Any CPU.Build.0 = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x64.ActiveCfg = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x64.Build.0 = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x86.ActiveCfg = Release|Any CPU
{E626BD6E-BF38-4EB7-A128-5CA6F40EF557}.Release|x86.Build.0 = Release|Any CPU
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Debug|Any CPU.ActiveCfg = Debug
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Debug|Any CPU.Build.0 = Debug
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Debug|x64.ActiveCfg = Debug
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Debug|x64.Build.0 = Debug
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Debug|x86.ActiveCfg = Debug
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Debug|x86.Build.0 = Debug
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Release|Any CPU.ActiveCfg = Release
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Release|Any CPU.Build.0 = Release
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Release|x64.ActiveCfg = Release
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Release|x64.Build.0 = Release
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Release|x86.ActiveCfg = Release
{EA7C9C89-0CCF-41E3-A379-D593AAF7A941}.Release|x86.Build.0 = Release
{05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|x64.ActiveCfg = Debug|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|x64.Build.0 = Debug|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|x86.ActiveCfg = Debug|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|x86.Build.0 = Debug|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Release|Any CPU.Build.0 = Release|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Release|x64.ActiveCfg = Release|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Release|x64.Build.0 = Release|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Release|x86.ActiveCfg = Release|Any CPU
{05F8E270-8B47-449B-8755-4599B3B3A565}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3F135F78-F70E-4127-BA77-6C262C7CCCEF}
EndGlobalSection
EndGlobal

View file

@ -1,34 +1,34 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace OnTopReplica {
public static class AppPaths {
const string AppDataFolder = "OnTopReplica";
public static void SetupPaths() {
var roamingAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var roamingAppDataApplicationPath = Path.Combine(roamingAppData, AppDataFolder);
if (!Directory.Exists(roamingAppDataApplicationPath)) {
Directory.CreateDirectory(roamingAppDataApplicationPath);
}
PrivateRoamingFolderPath = roamingAppDataApplicationPath;
}
public static string PrivateRoamingFolderPath { get; private set; }
public static string GenerateCrashDumpPath() {
var now = DateTime.Now;
string dump = string.Format("OnTopReplica-dump-{0}{1}{2}-{3}{4}.txt",
now.Year, now.Month, now.Day,
now.Hour, now.Minute);
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), dump);
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace OnTopReplica {
public static class AppPaths {
const string AppDataFolder = "OnTopReplica";
public static void SetupPaths() {
var roamingAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var roamingAppDataApplicationPath = Path.Combine(roamingAppData, AppDataFolder);
if (!Directory.Exists(roamingAppDataApplicationPath)) {
Directory.CreateDirectory(roamingAppDataApplicationPath);
}
PrivateRoamingFolderPath = roamingAppDataApplicationPath;
}
public static string PrivateRoamingFolderPath { get; private set; }
public static string GenerateCrashDumpPath() {
var now = DateTime.Now;
string dump = string.Format("OnTopReplica-dump-{0}{1}{2}-{3}{4}.txt",
now.Year, now.Month, now.Day,
now.Hour, now.Minute);
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), dump);
}
}
}

View file

@ -1,135 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ApplicationWebsite" xml:space="preserve">
<value>http://ontopreplica.codeplex.com</value>
</data>
<data name="AuthorWebsite" xml:space="preserve">
<value>http://lorenz.klopfenstein.net</value>
</data>
<data name="LatestCommitsLink" xml:space="preserve">
<value>http://ontopreplica.codeplex.com/SourceControl/list/changesets</value>
</data>
<data name="MsRlLicenseLink" xml:space="preserve">
<value>http://opensource.org/licenses/ms-rl.html</value>
</data>
<data name="UpdateFeed" xml:space="preserve">
<value>http://ontopreplica.codeplex.com/project/feeds/rss?ProjectRSSFeed=codeplex%3a%2f%2frelease%2fontopreplica</value>
</data>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ApplicationWebsite" xml:space="preserve">
<value>http://ontopreplica.codeplex.com</value>
</data>
<data name="AuthorWebsite" xml:space="preserve">
<value>http://lorenz.klopfenstein.net</value>
</data>
<data name="LatestCommitsLink" xml:space="preserve">
<value>http://ontopreplica.codeplex.com/SourceControl/list/changesets</value>
</data>
<data name="MsRlLicenseLink" xml:space="preserve">
<value>http://opensource.org/licenses/ms-rl.html</value>
</data>
<data name="UpdateFeed" xml:space="preserve">
<value>http://ontopreplica.codeplex.com/project/feeds/rss?ProjectRSSFeed=codeplex%3a%2f%2frelease%2fontopreplica</value>
</data>
</root>

View file

@ -1,266 +1,266 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica {
/// <summary>
/// Form that automatically keeps a certain aspect ratio and resizes without flickering.
/// </summary>
public class AspectRatioForm : WindowsFormsAero.AeroForm {
bool _keepAspectRatio = true;
/// <summary>
/// Gets or sets whether the form should keep its aspect ratio.
/// </summary>
/// <remarks>
/// Refreshes the window's size if set to true.
/// </remarks>
[Description("Enables fixed aspect ratio for this form."), Category("Appearance"), DefaultValue(true)]
public bool KeepAspectRatio {
get {
return _keepAspectRatio;
}
set {
_keepAspectRatio = value;
if (value)
RefreshAspectRatio();
}
}
double _aspectRatio = 1.0;
/// <summary>
/// Gets or sets the form's aspect ratio that will be kept automatically when resizing.
/// </summary>
[Description("Determines this form's fixed aspect ratio."), Category("Appearance"), DefaultValue(1.0)]
public double AspectRatio {
get {
return _aspectRatio;
}
set {
if (value <= 0.0 || Double.IsInfinity(value))
return;
_aspectRatio = value;
}
}
Padding _extraPadding;
/// <summary>
/// Gets or sets some additional internal padding of the form that is ignored when keeping the aspect ratio.
/// </summary>
[Description("Sets some padding inside the form's client area that is ignored when keeping the aspect ratio."),
Category("Appearance")]
public Padding ExtraPadding {
get {
return _extraPadding;
}
set {
_extraPadding = value;
if(KeepAspectRatio)
RefreshAspectRatio();
}
}
/// <summary>
/// Forces the form to update its height based on the current aspect ratio setting.
/// </summary>
public void RefreshAspectRatio() {
int newWidth = ClientSize.Width;
int newHeight = (int)((ClientSize.Width - ExtraPadding.Horizontal) / AspectRatio) + ExtraPadding.Vertical;
//Adapt height if it doesn't respect the form's minimum size
Size clientMinimumSize = FromSizeToClientSize(MinimumSize);
if (newHeight < clientMinimumSize.Height) {
newHeight = clientMinimumSize.Height;
newWidth = (int)((newHeight - ExtraPadding.Vertical) * AspectRatio) + ExtraPadding.Horizontal;
}
//Adapt height if it exceeds the screen's height
var workingArea = Screen.GetWorkingArea(this);
if (newHeight >= workingArea.Height) {
newHeight = workingArea.Height;
newWidth = (int)((newHeight - ExtraPadding.Vertical) * AspectRatio) + ExtraPadding.Horizontal;
}
//Update size
ClientSize = new Size(newWidth, newHeight);
//Move form vertically to adapt to new size
//REMOVED: allows the window to correctly be restored slightly off screen
/*if (Location.Y + Size.Height > workingArea.Y + workingArea.Height) {
int offsetY = (workingArea.Y + workingArea.Height) - (Location.Y + Size.Height);
Location = new Point(Location.X, Location.Y - offsetY);
}*/
}
/// <summary>
/// Adjusts the size of the form by a pixel increment while keeping its aspect ratio.
/// </summary>
/// <param name="pixelIncrement">Change of size in pixels.</param>
public void AdjustSize(int pixelOffset) {
Size origSize = Size;
//Resize to new width (clamped to max allowed size and minimum form size)
int newWidth = Math.Max(Math.Min(origSize.Width + pixelOffset,
SystemInformation.MaxWindowTrackSize.Width),
MinimumSize.Width);
//Determine new height while keeping aspect ratio
var clientConversionDifference = ClientWindowDifference;
int newHeight = (int)((newWidth - ExtraPadding.Horizontal - clientConversionDifference.Width) / AspectRatio) + ExtraPadding.Vertical + clientConversionDifference.Height;
//Apply and move form to recenter
Size = new Size(newWidth, newHeight);
int deltaX = Size.Width - origSize.Width;
int deltaY = Size.Height - origSize.Height;
Location = new System.Drawing.Point(Location.X - (deltaX / 2), Location.Y - (deltaY / 2));
}
/// <summary>
/// Updates the aspect ratio of the form and optionally forces a refresh.
/// </summary>
/// <param name="aspectRatioSource">Size from which aspect ratio should be computed.</param>
/// <param name="forceRefresh">True if the size of the form should be refreshed to match the new aspect ratio.</param>
public void SetAspectRatio(Size aspectRatioSource, bool forceRefresh) {
AspectRatio = ((double)aspectRatioSource.Width / (double)aspectRatioSource.Height);
_keepAspectRatio = true;
//Log.Write("Setting new aspect ratio {0} (for {1})", AspectRatio, aspectRatioSource);
if (forceRefresh) {
RefreshAspectRatio();
}
}
#region Event overriding
protected override void OnResizeEnd(EventArgs e) {
base.OnResizeEnd(e);
//Ensure that the ClientSize of the form is always respected
//(not ensured by the WM_SIZING message alone because of rounding errors and the chrome space)
if (KeepAspectRatio) {
var newHeight = ComputeHeightFromWidth(ClientSize.Width);
ClientSize = new Size(ClientSize.Width, newHeight);
}
}
protected virtual void OnResizing(EventArgs e) {
}
/// <summary>
/// Override WM_SIZING message to restrict resizing.
/// Taken from: http://www.vcskicks.com/maintain-aspect-ratio.php
/// Improved with code from: http://stoyanoff.info/blog/2010/06/27/resizing-forms-while-keeping-aspect-ratio/
/// </summary>
protected override void WndProc(ref Message m) {
if (m.Msg == WM.SIZING) {
this.OnResizing(EventArgs.Empty);
if (KeepAspectRatio) {
var clientSizeConversion = ClientWindowDifference;
var rc = (Native.NRectangle)Marshal.PtrToStructure(m.LParam, typeof(Native.NRectangle));
int res = m.WParam.ToInt32();
int width = (rc.Right - rc.Left) - clientSizeConversion.Width - ExtraPadding.Horizontal;
int height = (rc.Bottom - rc.Top) - clientSizeConversion.Height - ExtraPadding.Vertical;
if (res == WMSZ.LEFT || res == WMSZ.RIGHT) {
//Left or right resize, adjust top and bottom
int targetHeight = (int)(width / AspectRatio);
int diffHeight = height - targetHeight;
rc.Top += (int)(diffHeight / 2.0);
rc.Bottom = rc.Top + targetHeight + ExtraPadding.Vertical + clientSizeConversion.Height;
}
else if (res == WMSZ.TOP || res == WMSZ.BOTTOM) {
//Up or down resize, adjust left and right
int targetWidth = (int)(height * AspectRatio);
int diffWidth = width - targetWidth;
rc.Left += (int)(diffWidth / 2.0);
rc.Right = rc.Left + targetWidth + ExtraPadding.Horizontal + clientSizeConversion.Width;
}
else if (res == WMSZ.RIGHT + WMSZ.BOTTOM || res == WMSZ.LEFT + WMSZ.BOTTOM) {
//Lower corner resize, adjust bottom
rc.Bottom = rc.Top + (int)(width / AspectRatio) + ExtraPadding.Vertical + clientSizeConversion.Height;
}
else if (res == WMSZ.LEFT + WMSZ.TOP || res == WMSZ.RIGHT + WMSZ.TOP) {
//Upper corner resize, adjust top
rc.Top = rc.Bottom - (int)(width / AspectRatio) - ExtraPadding.Vertical - clientSizeConversion.Height;
}
Marshal.StructureToPtr(rc, m.LParam, false);
}
}
base.WndProc(ref m);
}
#endregion
#region Conversion helpers
/// <summary>
/// Converts a client size measurement to a window size measurement.
/// </summary>
/// <param name="clientSize">Size of the window's client area.</param>
/// <returns>Size of the whole window.</returns>
public Size FromClientSizeToSize(Size clientSize) {
var difference = ClientWindowDifference;
return new Size(clientSize.Width + difference.Width, clientSize.Height + difference.Height);
}
/// <summary>
/// Converts a window size measurement to a client size measurement.
/// </summary>
/// <param name="size">Size of the whole window.</param>
/// <returns>Size of the window's client area.</returns>
public Size FromSizeToClientSize(Size size) {
var difference = ClientWindowDifference;
return new Size(size.Width - difference.Width, size.Height - difference.Height);
}
/// <summary>
/// Computes height from width value, according to aspect ratio of window.
/// </summary>
public int ComputeHeightFromWidth(int width) {
return (int)Math.Round(((width - ExtraPadding.Horizontal) / AspectRatio) + ExtraPadding.Vertical);
}
/// <summary>
/// Computes width from height value, according to aspect ratio of window.
/// </summary>
public int ComputeWidthFromHeight(int height) {
return (int)Math.Round(((height - ExtraPadding.Vertical) * AspectRatio) + ExtraPadding.Horizontal);
}
#endregion
/// <summary>
/// Gets the difference in pixels between a client size value and a window size value (depending on window decoration).
/// </summary>
protected Size ClientWindowDifference {
get {
long style = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.Style).ToInt64();
long exStyle = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.ExStyle).ToInt64();
return WindowMethods.ConvertClientToWindowRect(new NRectangle(0, 0, 0, 0), style, exStyle).Size;
}
}
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica {
/// <summary>
/// Form that automatically keeps a certain aspect ratio and resizes without flickering.
/// </summary>
public class AspectRatioForm : WindowsFormsAero.AeroForm {
bool _keepAspectRatio = true;
/// <summary>
/// Gets or sets whether the form should keep its aspect ratio.
/// </summary>
/// <remarks>
/// Refreshes the window's size if set to true.
/// </remarks>
[Description("Enables fixed aspect ratio for this form."), Category("Appearance"), DefaultValue(true)]
public bool KeepAspectRatio {
get {
return _keepAspectRatio;
}
set {
_keepAspectRatio = value;
if (value)
RefreshAspectRatio();
}
}
double _aspectRatio = 1.0;
/// <summary>
/// Gets or sets the form's aspect ratio that will be kept automatically when resizing.
/// </summary>
[Description("Determines this form's fixed aspect ratio."), Category("Appearance"), DefaultValue(1.0)]
public double AspectRatio {
get {
return _aspectRatio;
}
set {
if (value <= 0.0 || Double.IsInfinity(value))
return;
_aspectRatio = value;
}
}
Padding _extraPadding;
/// <summary>
/// Gets or sets some additional internal padding of the form that is ignored when keeping the aspect ratio.
/// </summary>
[Description("Sets some padding inside the form's client area that is ignored when keeping the aspect ratio."),
Category("Appearance")]
public Padding ExtraPadding {
get {
return _extraPadding;
}
set {
_extraPadding = value;
if(KeepAspectRatio)
RefreshAspectRatio();
}
}
/// <summary>
/// Forces the form to update its height based on the current aspect ratio setting.
/// </summary>
public void RefreshAspectRatio() {
int newWidth = ClientSize.Width;
int newHeight = (int)((ClientSize.Width - ExtraPadding.Horizontal) / AspectRatio) + ExtraPadding.Vertical;
//Adapt height if it doesn't respect the form's minimum size
Size clientMinimumSize = FromSizeToClientSize(MinimumSize);
if (newHeight < clientMinimumSize.Height) {
newHeight = clientMinimumSize.Height;
newWidth = (int)((newHeight - ExtraPadding.Vertical) * AspectRatio) + ExtraPadding.Horizontal;
}
//Adapt height if it exceeds the screen's height
var workingArea = Screen.GetWorkingArea(this);
if (newHeight >= workingArea.Height) {
newHeight = workingArea.Height;
newWidth = (int)((newHeight - ExtraPadding.Vertical) * AspectRatio) + ExtraPadding.Horizontal;
}
//Update size
ClientSize = new Size(newWidth, newHeight);
//Move form vertically to adapt to new size
//REMOVED: allows the window to correctly be restored slightly off screen
/*if (Location.Y + Size.Height > workingArea.Y + workingArea.Height) {
int offsetY = (workingArea.Y + workingArea.Height) - (Location.Y + Size.Height);
Location = new Point(Location.X, Location.Y - offsetY);
}*/
}
/// <summary>
/// Adjusts the size of the form by a pixel increment while keeping its aspect ratio.
/// </summary>
/// <param name="pixelIncrement">Change of size in pixels.</param>
public void AdjustSize(int pixelOffset) {
Size origSize = Size;
//Resize to new width (clamped to max allowed size and minimum form size)
int newWidth = Math.Max(Math.Min(origSize.Width + pixelOffset,
SystemInformation.MaxWindowTrackSize.Width),
MinimumSize.Width);
//Determine new height while keeping aspect ratio
var clientConversionDifference = ClientWindowDifference;
int newHeight = (int)((newWidth - ExtraPadding.Horizontal - clientConversionDifference.Width) / AspectRatio) + ExtraPadding.Vertical + clientConversionDifference.Height;
//Apply and move form to recenter
Size = new Size(newWidth, newHeight);
int deltaX = Size.Width - origSize.Width;
int deltaY = Size.Height - origSize.Height;
Location = new System.Drawing.Point(Location.X - (deltaX / 2), Location.Y - (deltaY / 2));
}
/// <summary>
/// Updates the aspect ratio of the form and optionally forces a refresh.
/// </summary>
/// <param name="aspectRatioSource">Size from which aspect ratio should be computed.</param>
/// <param name="forceRefresh">True if the size of the form should be refreshed to match the new aspect ratio.</param>
public void SetAspectRatio(Size aspectRatioSource, bool forceRefresh) {
AspectRatio = ((double)aspectRatioSource.Width / (double)aspectRatioSource.Height);
_keepAspectRatio = true;
//Log.Write("Setting new aspect ratio {0} (for {1})", AspectRatio, aspectRatioSource);
if (forceRefresh) {
RefreshAspectRatio();
}
}
#region Event overriding
protected override void OnResizeEnd(EventArgs e) {
base.OnResizeEnd(e);
//Ensure that the ClientSize of the form is always respected
//(not ensured by the WM_SIZING message alone because of rounding errors and the chrome space)
if (KeepAspectRatio) {
var newHeight = ComputeHeightFromWidth(ClientSize.Width);
ClientSize = new Size(ClientSize.Width, newHeight);
}
}
protected virtual void OnResizing(EventArgs e) {
}
/// <summary>
/// Override WM_SIZING message to restrict resizing.
/// Taken from: http://www.vcskicks.com/maintain-aspect-ratio.php
/// Improved with code from: http://stoyanoff.info/blog/2010/06/27/resizing-forms-while-keeping-aspect-ratio/
/// </summary>
protected override void WndProc(ref Message m) {
if (m.Msg == WM.SIZING) {
this.OnResizing(EventArgs.Empty);
if (KeepAspectRatio) {
var clientSizeConversion = ClientWindowDifference;
var rc = (Native.NRectangle)Marshal.PtrToStructure(m.LParam, typeof(Native.NRectangle));
int res = m.WParam.ToInt32();
int width = (rc.Right - rc.Left) - clientSizeConversion.Width - ExtraPadding.Horizontal;
int height = (rc.Bottom - rc.Top) - clientSizeConversion.Height - ExtraPadding.Vertical;
if (res == WMSZ.LEFT || res == WMSZ.RIGHT) {
//Left or right resize, adjust top and bottom
int targetHeight = (int)(width / AspectRatio);
int diffHeight = height - targetHeight;
rc.Top += (int)(diffHeight / 2.0);
rc.Bottom = rc.Top + targetHeight + ExtraPadding.Vertical + clientSizeConversion.Height;
}
else if (res == WMSZ.TOP || res == WMSZ.BOTTOM) {
//Up or down resize, adjust left and right
int targetWidth = (int)(height * AspectRatio);
int diffWidth = width - targetWidth;
rc.Left += (int)(diffWidth / 2.0);
rc.Right = rc.Left + targetWidth + ExtraPadding.Horizontal + clientSizeConversion.Width;
}
else if (res == WMSZ.RIGHT + WMSZ.BOTTOM || res == WMSZ.LEFT + WMSZ.BOTTOM) {
//Lower corner resize, adjust bottom
rc.Bottom = rc.Top + (int)(width / AspectRatio) + ExtraPadding.Vertical + clientSizeConversion.Height;
}
else if (res == WMSZ.LEFT + WMSZ.TOP || res == WMSZ.RIGHT + WMSZ.TOP) {
//Upper corner resize, adjust top
rc.Top = rc.Bottom - (int)(width / AspectRatio) - ExtraPadding.Vertical - clientSizeConversion.Height;
}
Marshal.StructureToPtr(rc, m.LParam, false);
}
}
base.WndProc(ref m);
}
#endregion
#region Conversion helpers
/// <summary>
/// Converts a client size measurement to a window size measurement.
/// </summary>
/// <param name="clientSize">Size of the window's client area.</param>
/// <returns>Size of the whole window.</returns>
public Size FromClientSizeToSize(Size clientSize) {
var difference = ClientWindowDifference;
return new Size(clientSize.Width + difference.Width, clientSize.Height + difference.Height);
}
/// <summary>
/// Converts a window size measurement to a client size measurement.
/// </summary>
/// <param name="size">Size of the whole window.</param>
/// <returns>Size of the window's client area.</returns>
public Size FromSizeToClientSize(Size size) {
var difference = ClientWindowDifference;
return new Size(size.Width - difference.Width, size.Height - difference.Height);
}
/// <summary>
/// Computes height from width value, according to aspect ratio of window.
/// </summary>
public int ComputeHeightFromWidth(int width) {
return (int)Math.Round(((width - ExtraPadding.Horizontal) / AspectRatio) + ExtraPadding.Vertical);
}
/// <summary>
/// Computes width from height value, according to aspect ratio of window.
/// </summary>
public int ComputeWidthFromHeight(int height) {
return (int)Math.Round(((height - ExtraPadding.Vertical) * AspectRatio) + ExtraPadding.Horizontal);
}
#endregion
/// <summary>
/// Gets the difference in pixels between a client size value and a window size value (depending on window decoration).
/// </summary>
protected Size ClientWindowDifference {
get {
long style = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.Style).ToInt64();
long exStyle = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.ExStyle).ToInt64();
return WindowMethods.ConvertClientToWindowRect(new NRectangle(0, 0, 0, 0), style, exStyle).Size;
}
}
}
}

View file

Before

Width:  |  Height:  |  Size: 639 B

After

Width:  |  Height:  |  Size: 639 B

View file

Before

Width:  |  Height:  |  Size: 218 B

After

Width:  |  Height:  |  Size: 218 B

View file

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 209 B

View file

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 147 KiB

View file

Before

Width:  |  Height:  |  Size: 951 B

After

Width:  |  Height:  |  Size: 951 B

View file

Before

Width:  |  Height:  |  Size: 731 B

After

Width:  |  Height:  |  Size: 731 B

View file

Before

Width:  |  Height:  |  Size: 794 B

After

Width:  |  Height:  |  Size: 794 B

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

Before

Width:  |  Height:  |  Size: 241 B

After

Width:  |  Height:  |  Size: 241 B

View file

Before

Width:  |  Height:  |  Size: 347 B

After

Width:  |  Height:  |  Size: 347 B

View file

Before

Width:  |  Height:  |  Size: 202 B

After

Width:  |  Height:  |  Size: 202 B

View file

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 209 B

View file

Before

Width:  |  Height:  |  Size: 183 B

After

Width:  |  Height:  |  Size: 183 B

View file

Before

Width:  |  Height:  |  Size: 300 B

After

Width:  |  Height:  |  Size: 300 B

View file

Before

Width:  |  Height:  |  Size: 205 B

After

Width:  |  Height:  |  Size: 205 B

View file

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 355 B

View file

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

View file

Before

Width:  |  Height:  |  Size: 837 B

After

Width:  |  Height:  |  Size: 837 B

View file

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View file

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View file

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

Before

Width:  |  Height:  |  Size: 681 B

After

Width:  |  Height:  |  Size: 681 B

View file

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 770 B

View file

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 267 B

View file

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 267 B

View file

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 231 B

View file

Before

Width:  |  Height:  |  Size: 250 B

After

Width:  |  Height:  |  Size: 250 B

View file

Before

Width:  |  Height:  |  Size: 280 B

After

Width:  |  Height:  |  Size: 280 B

View file

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 278 B

View file

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 259 B

View file

Before

Width:  |  Height:  |  Size: 296 B

After

Width:  |  Height:  |  Size: 296 B

View file

Before

Width:  |  Height:  |  Size: 207 B

After

Width:  |  Height:  |  Size: 207 B

View file

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

View file

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 862 B

View file

Before

Width:  |  Height:  |  Size: 683 B

After

Width:  |  Height:  |  Size: 683 B

View file

Before

Width:  |  Height:  |  Size: 894 B

After

Width:  |  Height:  |  Size: 894 B

View file

Before

Width:  |  Height:  |  Size: 1,012 B

After

Width:  |  Height:  |  Size: 1,012 B

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

Before

Width:  |  Height:  |  Size: 894 B

After

Width:  |  Height:  |  Size: 894 B

View file

Before

Width:  |  Height:  |  Size: 810 B

After

Width:  |  Height:  |  Size: 810 B

View file

Before

Width:  |  Height:  |  Size: 456 B

After

Width:  |  Height:  |  Size: 456 B

View file

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

Before

Width:  |  Height:  |  Size: 753 B

After

Width:  |  Height:  |  Size: 753 B

View file

Before

Width:  |  Height:  |  Size: 437 B

After

Width:  |  Height:  |  Size: 437 B

View file

Before

Width:  |  Height:  |  Size: 715 B

After

Width:  |  Height:  |  Size: 715 B

View file

Before

Width:  |  Height:  |  Size: 761 B

After

Width:  |  Height:  |  Size: 761 B

View file

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 752 B

View file

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 752 B

View file

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

View file

Before

Width:  |  Height:  |  Size: 459 B

After

Width:  |  Height:  |  Size: 459 B

View file

@ -1,17 +1,17 @@
OnTopReplica credits
--------------------
This application was inspired by Switcher (http://insentient.net) and other
DWM based application.
All Aero controls are part of the open-source WindowsFormsAero
(http://windowsformsaero.codeplex.com) library for .NET.
Some DWM example code has ben taken from user Ookii (http://www.ookii.org) on
Channel 9 MSDN.
The NativeToolstripRenderer class has been taken from asztal.net
(http://wp.asztal.net/2007/12/vista-style-menus-in-dotnet).
Some of the icons used by OnTopReplica have been taken from VistaICO.com and
the Xiao icon set.
OnTopReplica credits
--------------------
This application was inspired by Switcher (http://insentient.net) and other
DWM based application.
All Aero controls are part of the open-source WindowsFormsAero
(http://windowsformsaero.codeplex.com) library for .NET.
Some DWM example code has ben taken from user Ookii (http://www.ookii.org) on
Channel 9 MSDN.
The NativeToolstripRenderer class has been taken from asztal.net
(http://wp.asztal.net/2007/12/vista-style-menus-in-dotnet).
Some of the icons used by OnTopReplica have been taken from VistaICO.com and
the Xiao icon set.

View file

@ -1,32 +1,32 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace OnTopReplica {
/// <summary>
/// EventArgs structure for clicks on a cloned window.
/// </summary>
public class CloneClickEventArgs : EventArgs {
public Point ClientClickLocation { get; set; }
public bool IsDoubleClick { get; set; }
public MouseButtons Buttons { get; set; }
public CloneClickEventArgs(Point location, MouseButtons buttons) {
ClientClickLocation = location;
Buttons = buttons;
IsDoubleClick = false;
}
public CloneClickEventArgs(Point location, MouseButtons buttons, bool doubleClick) {
ClientClickLocation = location;
Buttons = buttons;
IsDoubleClick = doubleClick;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace OnTopReplica {
/// <summary>
/// EventArgs structure for clicks on a cloned window.
/// </summary>
public class CloneClickEventArgs : EventArgs {
public Point ClientClickLocation { get; set; }
public bool IsDoubleClick { get; set; }
public MouseButtons Buttons { get; set; }
public CloneClickEventArgs(Point location, MouseButtons buttons) {
ClientClickLocation = location;
Buttons = buttons;
IsDoubleClick = false;
}
public CloneClickEventArgs(Point location, MouseButtons buttons, bool doubleClick) {
ClientClickLocation = location;
Buttons = buttons;
IsDoubleClick = doubleClick;
}
}
}

View file

@ -1,14 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace OnTopReplica {
public class CloseRequestEventArgs : EventArgs {
public WindowHandle LastWindowHandle { get; set; }
public Rectangle? LastRegion { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace OnTopReplica {
public class CloseRequestEventArgs : EventArgs {
public WindowHandle LastWindowHandle { get; set; }
public Rectangle? LastRegion { get; set; }
}
}

View file

@ -1,68 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WindowsFormsAero;
using System.Windows.Forms;
namespace OnTopReplica {
class FocusedTextBox : System.Windows.Forms.TextBox {
protected override bool IsInputChar(char charCode) {
if (charCode == '\n' || charCode == '\r')
return true;
return base.IsInputChar(charCode);
}
protected override void OnKeyUp(KeyEventArgs e) {
if (e.KeyCode == Keys.Return) {
if(!string.IsNullOrEmpty(Text))
OnConfirmInput();
e.Handled = true;
e.SuppressKeyPress = true;
}
else if (e.KeyCode == Keys.Escape) {
OnAbortInput();
e.Handled = true;
e.SuppressKeyPress = true;
}
base.OnKeyUp(e);
}
//List of characters to ignore on KeyPress events (because they generate bell rings)
readonly char[] IgnoreChars = new char[] {
(char)27, (char)13
};
protected override void OnKeyPress(KeyPressEventArgs e) {
if (IgnoreChars.Contains(e.KeyChar)) {
e.Handled = true;
}
base.OnKeyPress(e);
}
public event EventHandler ConfirmInput;
protected virtual void OnConfirmInput() {
var evt = ConfirmInput;
if (evt != null)
evt(this, EventArgs.Empty);
}
public event EventHandler AbortInput;
protected virtual void OnAbortInput() {
var evt = AbortInput;
if (evt != null)
evt(this, EventArgs.Empty);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WindowsFormsAero;
using System.Windows.Forms;
namespace OnTopReplica {
class FocusedTextBox : System.Windows.Forms.TextBox {
protected override bool IsInputChar(char charCode) {
if (charCode == '\n' || charCode == '\r')
return true;
return base.IsInputChar(charCode);
}
protected override void OnKeyUp(KeyEventArgs e) {
if (e.KeyCode == Keys.Return) {
if(!string.IsNullOrEmpty(Text))
OnConfirmInput();
e.Handled = true;
e.SuppressKeyPress = true;
}
else if (e.KeyCode == Keys.Escape) {
OnAbortInput();
e.Handled = true;
e.SuppressKeyPress = true;
}
base.OnKeyUp(e);
}
//List of characters to ignore on KeyPress events (because they generate bell rings)
readonly char[] IgnoreChars = new char[] {
(char)27, (char)13
};
protected override void OnKeyPress(KeyPressEventArgs e) {
if (IgnoreChars.Contains(e.KeyChar)) {
e.Handled = true;
}
base.OnKeyPress(e);
}
public event EventHandler ConfirmInput;
protected virtual void OnConfirmInput() {
var evt = ConfirmInput;
if (evt != null)
evt(this, EventArgs.Empty);
}
public event EventHandler AbortInput;
protected virtual void OnAbortInput() {
var evt = AbortInput;
if (evt != null)
evt(this, EventArgs.Empty);
}
}
}

View file

@ -1,116 +1,116 @@
using OnTopReplica.Properties;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica {
class FullscreenFormManager {
private readonly MainForm _mainForm;
public FullscreenFormManager(MainForm form) {
_mainForm = form;
IsFullscreen = false;
}
Point _preFullscreenLocation;
Size _preFullscreenSize;
FormBorderStyle _preFullscreenBorderStyle;
public bool IsFullscreen {
get;
private set;
}
public void SwitchFullscreen() {
SwitchFullscreen(Settings.Default.GetFullscreenMode());
}
public void SwitchFullscreen(FullscreenMode mode) {
if (IsFullscreen) {
MoveToFullscreenMode(mode);
return;
}
if (!_mainForm.ThumbnailPanel.IsShowingThumbnail)
return;
//On switch, always hide side panels
_mainForm.CloseSidePanel();
//Store state
_preFullscreenLocation = _mainForm.Location;
_preFullscreenSize = _mainForm.ClientSize;
_preFullscreenBorderStyle = _mainForm.FormBorderStyle;
//Change state to fullscreen
_mainForm.FormBorderStyle = FormBorderStyle.None;
MoveToFullscreenMode(mode);
CommonCompleteSwitch(true);
}
private void MoveToFullscreenMode(FullscreenMode mode) {
var screens = Screen.AllScreens;
var currentScreen = Screen.FromControl(_mainForm);
Size size = _mainForm.Size;
Point location = _mainForm.Location;
switch (mode) {
case FullscreenMode.Standard:
default:
size = currentScreen.WorkingArea.Size;
location = currentScreen.WorkingArea.Location;
break;
case FullscreenMode.Fullscreen:
size = currentScreen.Bounds.Size;
location = currentScreen.Bounds.Location;
break;
case FullscreenMode.AllScreens:
size = SystemInformation.VirtualScreen.Size;
location = SystemInformation.VirtualScreen.Location;
break;
}
_mainForm.Size = size;
_mainForm.Location = location;
}
public void SwitchBack() {
if (!IsFullscreen)
return;
//Restore state
_mainForm.FormBorderStyle = _preFullscreenBorderStyle;
_mainForm.Location = _preFullscreenLocation;
_mainForm.ClientSize = _preFullscreenSize;
_mainForm.RefreshAspectRatio();
CommonCompleteSwitch(false);
}
private void CommonCompleteSwitch(bool enabled) {
//UI stuff switching
_mainForm.GlassMargins = (!enabled) ? new Padding(-1) : Padding.Empty;
_mainForm.TopMost = !enabled;
IsFullscreen = enabled;
Program.Platform.OnFormStateChange(_mainForm);
}
public void Toggle() {
if (IsFullscreen)
SwitchBack();
else
SwitchFullscreen(Settings.Default.GetFullscreenMode());
}
}
}
using OnTopReplica.Properties;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica {
class FullscreenFormManager {
private readonly MainForm _mainForm;
public FullscreenFormManager(MainForm form) {
_mainForm = form;
IsFullscreen = false;
}
Point _preFullscreenLocation;
Size _preFullscreenSize;
FormBorderStyle _preFullscreenBorderStyle;
public bool IsFullscreen {
get;
private set;
}
public void SwitchFullscreen() {
SwitchFullscreen(Settings.Default.GetFullscreenMode());
}
public void SwitchFullscreen(FullscreenMode mode) {
if (IsFullscreen) {
MoveToFullscreenMode(mode);
return;
}
if (!_mainForm.ThumbnailPanel.IsShowingThumbnail)
return;
//On switch, always hide side panels
_mainForm.CloseSidePanel();
//Store state
_preFullscreenLocation = _mainForm.Location;
_preFullscreenSize = _mainForm.ClientSize;
_preFullscreenBorderStyle = _mainForm.FormBorderStyle;
//Change state to fullscreen
_mainForm.FormBorderStyle = FormBorderStyle.None;
MoveToFullscreenMode(mode);
CommonCompleteSwitch(true);
}
private void MoveToFullscreenMode(FullscreenMode mode) {
var screens = Screen.AllScreens;
var currentScreen = Screen.FromControl(_mainForm);
Size size = _mainForm.Size;
Point location = _mainForm.Location;
switch (mode) {
case FullscreenMode.Standard:
default:
size = currentScreen.WorkingArea.Size;
location = currentScreen.WorkingArea.Location;
break;
case FullscreenMode.Fullscreen:
size = currentScreen.Bounds.Size;
location = currentScreen.Bounds.Location;
break;
case FullscreenMode.AllScreens:
size = SystemInformation.VirtualScreen.Size;
location = SystemInformation.VirtualScreen.Location;
break;
}
_mainForm.Size = size;
_mainForm.Location = location;
}
public void SwitchBack() {
if (!IsFullscreen)
return;
//Restore state
_mainForm.FormBorderStyle = _preFullscreenBorderStyle;
_mainForm.Location = _preFullscreenLocation;
_mainForm.ClientSize = _preFullscreenSize;
_mainForm.RefreshAspectRatio();
CommonCompleteSwitch(false);
}
private void CommonCompleteSwitch(bool enabled) {
//UI stuff switching
_mainForm.GlassMargins = (!enabled) ? new Padding(-1) : Padding.Empty;
_mainForm.TopMost = !enabled;
IsFullscreen = enabled;
Program.Platform.OnFormStateChange(_mainForm);
}
public void Toggle() {
if (IsFullscreen)
SwitchBack();
else
SwitchFullscreen(Settings.Default.GetFullscreenMode());
}
}
}

View file

@ -1,39 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using OnTopReplica.Properties;
namespace OnTopReplica {
/// <summary>
/// Describes a fullscreen mode.
/// </summary>
enum FullscreenMode {
Standard,
Fullscreen,
AllScreens
}
static class FullscreenModeExtensions {
/// <summary>
/// Gets the fullscreen mode as an enumeration value.
/// </summary>
public static FullscreenMode GetFullscreenMode(this Settings settings) {
FullscreenMode retMode = FullscreenMode.Standard;
Enum.TryParse<FullscreenMode>(settings.FullscreenMode, out retMode);
return retMode;
}
/// <summary>
/// Sets the fullscreen mode.
/// </summary>
public static void SetFullscreenMode(this Settings settings, FullscreenMode mode) {
settings.FullscreenMode = mode.ToString();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using OnTopReplica.Properties;
namespace OnTopReplica {
/// <summary>
/// Describes a fullscreen mode.
/// </summary>
enum FullscreenMode {
Standard,
Fullscreen,
AllScreens
}
static class FullscreenModeExtensions {
/// <summary>
/// Gets the fullscreen mode as an enumeration value.
/// </summary>
public static FullscreenMode GetFullscreenMode(this Settings settings) {
FullscreenMode retMode = FullscreenMode.Standard;
Enum.TryParse<FullscreenMode>(settings.FullscreenMode, out retMode);
return retMode;
}
/// <summary>
/// Sets the fullscreen mode.
/// </summary>
public static void SetFullscreenMode(this Settings settings, FullscreenMode mode) {
settings.FullscreenMode = mode.ToString();
}
}
}

View file

@ -1,74 +1,74 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace OnTopReplica {
/// <summary>
/// Common geometry extension methods.
/// </summary>
static class GeometryExtensions {
/// <summary>
/// Returns the difference (offset vector) between two points.
/// </summary>
public static Point Difference(this Point a, Point b) {
return new Point(a.X - b.X, a.Y - b.Y);
}
/// <summary>
/// Expands a size value by a padding distance.
/// </summary>
public static Size Expand(this Size size, Padding padding) {
return new Size(size.Width + padding.Horizontal, size.Height + padding.Vertical);
}
/// <summary>
/// Expands a size value by a size distance.
/// </summary>
public static Size Expand(this Size size, Size expandSize) {
return new Size(size.Width + expandSize.Width, size.Height + expandSize.Height);
}
/// <summary>
/// Computes the difference between two size values.
/// </summary>
public static Size Difference(this Size a, Size b) {
return new Size(a.Width - b.Width, a.Height - b.Height);
}
/// <summary>
/// Ensures that the minimum size of a control respects a minimum
/// client size area.
/// </summary>
/// <param name="ctrl">Control whose MinimumSize should be altered.</param>
/// <param name="minimumClientSize">Minimum client size value to ensure.</param>
public static void EnsureMinimumClientSize(this Control ctrl, Size minimumClientSize) {
Size offset = ctrl.Size.Difference(ctrl.ClientSize);
ctrl.MinimumSize = minimumClientSize.Expand(offset);
}
/// <summary>
/// Attempts to fit a size structure to another fixed destination size, by maintaining
/// the original aspect ratio.
/// </summary>
public static Size Fit(this Size sourceSize, Size destinationSize) {
double sourceRatio = (double)sourceSize.Width / (double)sourceSize.Height;
double clientRatio = (double)destinationSize.Width / (double)destinationSize.Height;
Size ret;
if (sourceRatio >= clientRatio) {
ret = new Size(destinationSize.Width, (int)((double)destinationSize.Width / sourceRatio));
}
else {
ret = new Size((int)((double)destinationSize.Height * sourceRatio), destinationSize.Height);
}
return ret;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace OnTopReplica {
/// <summary>
/// Common geometry extension methods.
/// </summary>
static class GeometryExtensions {
/// <summary>
/// Returns the difference (offset vector) between two points.
/// </summary>
public static Point Difference(this Point a, Point b) {
return new Point(a.X - b.X, a.Y - b.Y);
}
/// <summary>
/// Expands a size value by a padding distance.
/// </summary>
public static Size Expand(this Size size, Padding padding) {
return new Size(size.Width + padding.Horizontal, size.Height + padding.Vertical);
}
/// <summary>
/// Expands a size value by a size distance.
/// </summary>
public static Size Expand(this Size size, Size expandSize) {
return new Size(size.Width + expandSize.Width, size.Height + expandSize.Height);
}
/// <summary>
/// Computes the difference between two size values.
/// </summary>
public static Size Difference(this Size a, Size b) {
return new Size(a.Width - b.Width, a.Height - b.Height);
}
/// <summary>
/// Ensures that the minimum size of a control respects a minimum
/// client size area.
/// </summary>
/// <param name="ctrl">Control whose MinimumSize should be altered.</param>
/// <param name="minimumClientSize">Minimum client size value to ensure.</param>
public static void EnsureMinimumClientSize(this Control ctrl, Size minimumClientSize) {
Size offset = ctrl.Size.Difference(ctrl.ClientSize);
ctrl.MinimumSize = minimumClientSize.Expand(offset);
}
/// <summary>
/// Attempts to fit a size structure to another fixed destination size, by maintaining
/// the original aspect ratio.
/// </summary>
public static Size Fit(this Size sourceSize, Size destinationSize) {
double sourceRatio = (double)sourceSize.Width / (double)sourceSize.Height;
double clientRatio = (double)destinationSize.Width / (double)destinationSize.Height;
Size ret;
if (sourceRatio >= clientRatio) {
ret = new Size(destinationSize.Width, (int)((double)destinationSize.Width / sourceRatio));
}
else {
ret = new Size((int)((double)destinationSize.Height * sourceRatio), destinationSize.Height);
}
return ret;
}
}
}

View file

@ -1,56 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica {
class HotKeyTextBox : TextBox {
protected override void OnCreateControl() {
ReadOnly = true;
base.OnCreateControl();
}
readonly Keys[] IgnoredKeys = new Keys[] {
Keys.ControlKey,
Keys.Control,
Keys.Alt,
Keys.Menu,
Keys.ShiftKey,
Keys.Shift,
Keys.LWin,
Keys.RWin
};
readonly Keys[] CancelKeys = new Keys[] {
Keys.Back,
Keys.Escape
};
protected override void OnKeyUp(KeyEventArgs e) {
if (CancelKeys.Contains(e.KeyCode)) {
Text = string.Empty;
}
else if (!IgnoredKeys.Contains(e.KeyCode)) {
var sb = new StringBuilder();
if (e.Control)
sb.Append("[CTRL]+");
if (e.Alt)
sb.Append("[ALT]+");
if (e.Shift)
sb.Append("[SHIFT]+");
sb.Append(e.KeyCode.ToString());
Text = sb.ToString();
}
e.Handled = true;
base.OnKeyUp(e);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica {
class HotKeyTextBox : TextBox {
protected override void OnCreateControl() {
ReadOnly = true;
base.OnCreateControl();
}
readonly Keys[] IgnoredKeys = new Keys[] {
Keys.ControlKey,
Keys.Control,
Keys.Alt,
Keys.Menu,
Keys.ShiftKey,
Keys.Shift,
Keys.LWin,
Keys.RWin
};
readonly Keys[] CancelKeys = new Keys[] {
Keys.Back,
Keys.Escape
};
protected override void OnKeyUp(KeyEventArgs e) {
if (CancelKeys.Contains(e.KeyCode)) {
Text = string.Empty;
}
else if (!IgnoredKeys.Contains(e.KeyCode)) {
var sb = new StringBuilder();
if (e.Control)
sb.Append("[CTRL]+");
if (e.Alt)
sb.Append("[ALT]+");
if (e.Shift)
sb.Append("[SHIFT]+");
sb.Append(e.KeyCode.ToString());
Text = sb.ToString();
}
e.Handled = true;
base.OnKeyUp(e);
}
}
}

View file

@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica {
interface IMessagePumpProcessor : IDisposable {
void Initialize(MainForm form);
bool Process(ref Message msg);
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica {
interface IMessagePumpProcessor : IDisposable {
void Initialize(MainForm form);
bool Process(ref Message msg);
}
}

View file

@ -1,77 +1,77 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace OnTopReplica {
class ImageComboBox : ComboBox {
public ImageComboBox() {
DrawMode = DrawMode.OwnerDrawFixed;
}
protected override void OnDrawItem(DrawItemEventArgs ea) {
ea.DrawBackground();
ea.DrawFocusRectangle();
if (ea.Index == -1)
return;
Rectangle bounds = ea.Bounds;
var foreBrush = new SolidBrush(ea.ForeColor);
int textLeftBound = (IconList == null) ? bounds.Left : bounds.Left + IconList.ImageSize.Width;
var drawObject = Items[ea.Index];
if (drawObject is ImageComboBoxItem) {
var drawItem = (ImageComboBoxItem)drawObject;
if (drawItem.ImageListIndex != -1 && IconList != null) {
//ea.Graphics.FillRectangle(Brushes.Gray, bounds.Left, bounds.Top, IconList.ImageSize.Width, IconList.ImageSize.Height);
ea.Graphics.DrawImage(IconList.Images[drawItem.ImageListIndex], bounds.Left, bounds.Top);
}
ea.Graphics.DrawString(drawItem.Text, ea.Font, foreBrush, textLeftBound, bounds.Top);
}
else {
ea.Graphics.DrawString(drawObject.ToString(), ea.Font, foreBrush, textLeftBound, bounds.Top);
}
base.OnDrawItem(ea);
}
public ImageList IconList { get; set; }
}
class ImageComboBoxItem {
public ImageComboBoxItem() {
Text = "";
ImageListIndex = -1;
}
public ImageComboBoxItem(string text) {
if (text == null)
throw new ArgumentNullException();
Text = text;
ImageListIndex = -1;
}
public ImageComboBoxItem(string text, int imageListIndex) {
if (text == null)
throw new ArgumentNullException();
Text = text;
ImageListIndex = imageListIndex;
}
public string Text { get; private set; }
public int ImageListIndex { get; private set; }
public object Tag { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace OnTopReplica {
class ImageComboBox : ComboBox {
public ImageComboBox() {
DrawMode = DrawMode.OwnerDrawFixed;
}
protected override void OnDrawItem(DrawItemEventArgs ea) {
ea.DrawBackground();
ea.DrawFocusRectangle();
if (ea.Index == -1)
return;
Rectangle bounds = ea.Bounds;
var foreBrush = new SolidBrush(ea.ForeColor);
int textLeftBound = (IconList == null) ? bounds.Left : bounds.Left + IconList.ImageSize.Width;
var drawObject = Items[ea.Index];
if (drawObject is ImageComboBoxItem) {
var drawItem = (ImageComboBoxItem)drawObject;
if (drawItem.ImageListIndex != -1 && IconList != null) {
//ea.Graphics.FillRectangle(Brushes.Gray, bounds.Left, bounds.Top, IconList.ImageSize.Width, IconList.ImageSize.Height);
ea.Graphics.DrawImage(IconList.Images[drawItem.ImageListIndex], bounds.Left, bounds.Top);
}
ea.Graphics.DrawString(drawItem.Text, ea.Font, foreBrush, textLeftBound, bounds.Top);
}
else {
ea.Graphics.DrawString(drawObject.ToString(), ea.Font, foreBrush, textLeftBound, bounds.Top);
}
base.OnDrawItem(ea);
}
public ImageList IconList { get; set; }
}
class ImageComboBoxItem {
public ImageComboBoxItem() {
Text = "";
ImageListIndex = -1;
}
public ImageComboBoxItem(string text) {
if (text == null)
throw new ArgumentNullException();
Text = text;
ImageListIndex = -1;
}
public ImageComboBoxItem(string text, int imageListIndex) {
if (text == null)
throw new ArgumentNullException();
Text = text;
ImageListIndex = imageListIndex;
}
public string Text { get; private set; }
public int ImageListIndex { get; private set; }
public object Tag { get; set; }
}
}

View file

@ -1,54 +1,54 @@
Microsoft Reciprocal License (Ms-RL)
This license governs use of the accompanying software. If you use the
software, you accept this license. If you do not accept the license, do not
use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution"
have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the
software.
A "contributor" is any person that distributes its contribution under this
license.
"Licensed patents" are a contributor's patent claims that read directly on its
contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the
license conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free copyright license to reproduce its
contribution, prepare derivative works of its contribution, and distribute its
contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free license under its licensed patents to
make, have made, use, sell, offer for sale, import, and/or otherwise dispose
of its contribution in the software or derivative works of the contribution
in the software.
3. Conditions and Limitations
(A) Reciprocal Grants- For any file you distribute that contains code from the
software (in source code or binary format), you must provide recipients the
source code to that file along with a copy of this license, which license will
govern that file. You may license other files that are entirely your own work
and do not contain code from the software under any terms you choose.
(B) No Trademark License- This license does not grant you rights to use any
contributors' name, logo, or trademarks.
(C) If you bring a patent claim against any contributor over patents that you
claim are infringed by the software, your patent license from such contributor
to the software ends automatically.
(D) If you distribute any portion of the software, you must retain all
copyright, patent, trademark, and attribution notices that are present in the
software.
(E) If you distribute any portion of the software in source code form, you may
do so only under this license by including a complete copy of this license
with your distribution. If you distribute any portion of the software in
compiled or object code form, you may only do so under a license that complies
with this license.
(F) The software is licensed "as-is." You bear the risk of using it. The
contributors give no express warranties, guarantees or conditions. You may
have additional consumer rights under your local laws which this license
cannot change. To the extent permitted under your local laws, the contributors
exclude the implied warranties of merchantability, fitness for a particular
purpose and non-infringement.
Microsoft Reciprocal License (Ms-RL)
This license governs use of the accompanying software. If you use the
software, you accept this license. If you do not accept the license, do not
use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution"
have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the
software.
A "contributor" is any person that distributes its contribution under this
license.
"Licensed patents" are a contributor's patent claims that read directly on its
contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the
license conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free copyright license to reproduce its
contribution, prepare derivative works of its contribution, and distribute its
contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free license under its licensed patents to
make, have made, use, sell, offer for sale, import, and/or otherwise dispose
of its contribution in the software or derivative works of the contribution
in the software.
3. Conditions and Limitations
(A) Reciprocal Grants- For any file you distribute that contains code from the
software (in source code or binary format), you must provide recipients the
source code to that file along with a copy of this license, which license will
govern that file. You may license other files that are entirely your own work
and do not contain code from the software under any terms you choose.
(B) No Trademark License- This license does not grant you rights to use any
contributors' name, logo, or trademarks.
(C) If you bring a patent claim against any contributor over patents that you
claim are infringed by the software, your patent license from such contributor
to the software ends automatically.
(D) If you distribute any portion of the software, you must retain all
copyright, patent, trademark, and attribution notices that are present in the
software.
(E) If you distribute any portion of the software in source code form, you may
do so only under this license by including a complete copy of this license
with your distribution. If you distribute any portion of the software in
compiled or object code form, you may only do so under a license that complies
with this license.
(F) The software is licensed "as-is." You bear the risk of using it. The
contributors give no express warranties, guarantees or conditions. You may
have additional consumer rights under your local laws which this license
cannot change. To the extent permitted under your local laws, the contributors
exclude the implied warranties of merchantability, fitness for a particular
purpose and non-infringement.

View file

@ -1,109 +1,109 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace OnTopReplica {
static class Log {
const string LogFileName = "lastrun.log.txt";
const string ConflictLogFileName = "run-{0}.log.txt";
private readonly static StreamWriter Writer;
static Log() {
try {
var filepath = Path.Combine(AppPaths.PrivateRoamingFolderPath, LogFileName);
Writer = new StreamWriter(new FileStream(filepath, FileMode.Create));
Writer.AutoFlush = true;
}
catch (Exception) {
try {
var filepath = Path.Combine(AppPaths.PrivateRoamingFolderPath, string.Format(ConflictLogFileName, System.Diagnostics.Process.GetCurrentProcess().Id));
Writer = new StreamWriter(new FileStream(filepath, FileMode.Create));
Writer.AutoFlush = true;
}
catch (Exception) {
//No fallback logging possible
Writer = null;
}
}
}
public static void Write(string message) {
WriteLine(message);
}
public static void Write(string format, object arg0) {
WriteLine(string.Format(format, arg0));
}
public static void Write(string format, object arg0, object arg1) {
WriteLine(string.Format(format, arg0, arg1));
}
public static void Write(string format, params object[] args) {
WriteLine(string.Format(format, args));
}
public static void WriteDetails(string caption, string format, params object[] args) {
WriteLines(caption, string.Format(format, args));
}
public static void WriteException(string message, Exception exception) {
if (exception != null) {
WriteLines(message, exception.ToString());
}
else {
WriteLines(message, "(No exception data.)");
}
}
private static void WriteLine(string message) {
var s = string.Format("{0,-8:HH:mm:ss} {1}", DateTime.Now, message);
AddToQueue(s);
if (Writer != null) {
Writer.WriteLine(s);
}
}
private static void WriteLines(params string[] messages) {
if (messages.Length <= 0)
return;
var sb = new StringBuilder();
sb.AppendFormat("{0,-8:HH:mm:ss} {1}", DateTime.Now, messages[0]);
for (int i = 1; i < messages.Length; ++i) {
sb.AppendLine();
sb.AppendFormat(" {0}", messages[i]);
}
AddToQueue(sb.ToString());
if (Writer != null) {
Writer.WriteLine(sb.ToString());
}
}
const int MaxQueueCapacity = 30;
private static Queue<string> _entriesQueue = new Queue<string>(MaxQueueCapacity);
private static void AddToQueue(string entry){
_entriesQueue.Enqueue(entry);
while(_entriesQueue.Count > MaxQueueCapacity){
_entriesQueue.Dequeue();
}
}
public static IEnumerable<string> Queue {
get {
return _entriesQueue;
}
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace OnTopReplica {
static class Log {
const string LogFileName = "lastrun.log.txt";
const string ConflictLogFileName = "run-{0}.log.txt";
private readonly static StreamWriter Writer;
static Log() {
try {
var filepath = Path.Combine(AppPaths.PrivateRoamingFolderPath, LogFileName);
Writer = new StreamWriter(new FileStream(filepath, FileMode.Create));
Writer.AutoFlush = true;
}
catch (Exception) {
try {
var filepath = Path.Combine(AppPaths.PrivateRoamingFolderPath, string.Format(ConflictLogFileName, System.Diagnostics.Process.GetCurrentProcess().Id));
Writer = new StreamWriter(new FileStream(filepath, FileMode.Create));
Writer.AutoFlush = true;
}
catch (Exception) {
//No fallback logging possible
Writer = null;
}
}
}
public static void Write(string message) {
WriteLine(message);
}
public static void Write(string format, object arg0) {
WriteLine(string.Format(format, arg0));
}
public static void Write(string format, object arg0, object arg1) {
WriteLine(string.Format(format, arg0, arg1));
}
public static void Write(string format, params object[] args) {
WriteLine(string.Format(format, args));
}
public static void WriteDetails(string caption, string format, params object[] args) {
WriteLines(caption, string.Format(format, args));
}
public static void WriteException(string message, Exception exception) {
if (exception != null) {
WriteLines(message, exception.ToString());
}
else {
WriteLines(message, "(No exception data.)");
}
}
private static void WriteLine(string message) {
var s = string.Format("{0,-8:HH:mm:ss} {1}", DateTime.Now, message);
AddToQueue(s);
if (Writer != null) {
Writer.WriteLine(s);
}
}
private static void WriteLines(params string[] messages) {
if (messages.Length <= 0)
return;
var sb = new StringBuilder();
sb.AppendFormat("{0,-8:HH:mm:ss} {1}", DateTime.Now, messages[0]);
for (int i = 1; i < messages.Length; ++i) {
sb.AppendLine();
sb.AppendFormat(" {0}", messages[i]);
}
AddToQueue(sb.ToString());
if (Writer != null) {
Writer.WriteLine(sb.ToString());
}
}
const int MaxQueueCapacity = 30;
private static Queue<string> _entriesQueue = new Queue<string>(MaxQueueCapacity);
private static void AddToQueue(string entry){
_entriesQueue.Enqueue(entry);
while(_entriesQueue.Count > MaxQueueCapacity){
_entriesQueue.Dequeue();
}
}
public static IEnumerable<string> Queue {
get {
return _entriesQueue;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,461 +1,461 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using OnTopReplica.Native;
using OnTopReplica.Properties;
using OnTopReplica.StartupOptions;
using OnTopReplica.Update;
using OnTopReplica.WindowSeekers;
using WindowsFormsAero.Dwm;
using WindowsFormsAero.TaskDialog;
namespace OnTopReplica {
partial class MainForm : AspectRatioForm {
//GUI elements
ThumbnailPanel _thumbnailPanel;
//Managers
readonly MessagePumpManager _msgPumpManager = new MessagePumpManager();
WindowListMenuManager _windowListManager;
public FullscreenFormManager FullscreenManager { get; private set; }
Options _startupOptions;
public MainForm(Options startupOptions) {
_startupOptions = startupOptions;
FullscreenManager = new FullscreenFormManager(this);
_quickRegionDrawingHandler = new ThumbnailPanel.RegionDrawnHandler(HandleQuickRegionDrawn);
//WinForms init pass
InitializeComponent();
//Store default values
DefaultNonClickTransparencyKey = this.TransparencyKey;
DefaultBorderStyle = this.FormBorderStyle;
//Thumbnail panel
_thumbnailPanel = new ThumbnailPanel {
Location = Point.Empty,
Dock = DockStyle.Fill
};
_thumbnailPanel.CloneClick += new EventHandler<CloneClickEventArgs>(Thumbnail_CloneClick);
Controls.Add(_thumbnailPanel);
//Set native renderer on context menus
Asztal.Szótár.NativeToolStripRenderer.SetToolStripRenderer(
menuContext, menuWindows, menuOpacity, menuResize, menuFullscreenContext
);
//Set to Key event preview
this.KeyPreview = true;
Log.Write("Main form constructed");
}
#region Event override
protected override void OnHandleCreated(EventArgs e){
base.OnHandleCreated(e);
//Window init
KeepAspectRatio = false;
GlassMargins = new Padding(-1);
//Managers
_msgPumpManager.Initialize(this);
_windowListManager = new WindowListMenuManager(this, menuWindows);
_windowListManager.ParentMenus = new System.Windows.Forms.ContextMenuStrip[] {
menuContext, menuFullscreenContext
};
//Platform specific form initialization
Program.Platform.PostHandleFormInit(this);
}
protected override void OnShown(EventArgs e) {
Log.Write("Main form shown");
base.OnShown(e);
//Apply startup options
_startupOptions.Apply(this);
}
protected override void OnClosing(CancelEventArgs e) {
Log.Write("Main form closing");
base.OnClosing(e);
_msgPumpManager.Dispose();
Program.Platform.CloseForm(this);
}
protected override void OnClosed(EventArgs e) {
Log.Write("Main form closed");
base.OnClosed(e);
}
protected override void OnMove(EventArgs e) {
base.OnMove(e);
AdjustSidePanelLocation();
}
protected override void OnResizeEnd(EventArgs e) {
base.OnResizeEnd(e);
RefreshScreenLock();
}
protected override void OnResizing(EventArgs e) {
//Update aspect ratio from thumbnail while resizing (but do not refresh, resizing does that anyway)
if (_thumbnailPanel.IsShowingThumbnail) {
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, false);
}
}
protected override void OnActivated(EventArgs e) {
base.OnActivated(e);
//Deactivate click-through if form is reactivated
if (ClickThroughEnabled) {
ClickThroughEnabled = false;
}
Program.Platform.RestoreForm(this);
}
protected override void OnDeactivate(EventArgs e) {
base.OnDeactivate(e);
//HACK: sometimes, even if TopMost is true, the window loses its "always on top" status.
// This is a fix attempt that probably won't work...
if (!FullscreenManager.IsFullscreen) { //fullscreen mode doesn't use TopMost
TopMost = false;
TopMost = true;
}
}
protected override void OnMouseWheel(MouseEventArgs e) {
base.OnMouseWheel(e);
if (!FullscreenManager.IsFullscreen) {
if (_thumbnailPanel.IsShowingThumbnail) {
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, false);
}
int change = (int)(e.Delta / 6.0); //assumes a mouse wheel "tick" is in the 80-120 range
AdjustSize(change);
RefreshScreenLock();
}
}
protected override void OnMouseDoubleClick(MouseEventArgs e) {
base.OnMouseDoubleClick(e);
//This is handled by the WM_NCLBUTTONDBLCLK msg handler usually (because the GlassForm translates
//clicks on client to clicks on caption). But if fullscreen mode disables GlassForm dragging, we need
//this auxiliary handler to switch mode.
FullscreenManager.Toggle();
}
protected override void OnMouseClick(MouseEventArgs e) {
base.OnMouseClick(e);
//Same story as above (OnMouseDoubleClick)
if (e.Button == System.Windows.Forms.MouseButtons.Right) {
OpenContextMenu(null);
}
}
private ThumbnailPanel.RegionDrawnHandler _quickRegionDrawingHandler;
protected override void WndProc(ref Message m) {
if (_msgPumpManager != null) {
if (_msgPumpManager.PumpMessage(ref m)) {
return;
}
}
switch (m.Msg) {
case WM.NCRBUTTONUP:
//Open context menu if right button clicked on caption (i.e. all of the window area because of glass)
if (m.WParam.ToInt32() == HT.CAPTION) {
OpenContextMenu(null);
m.Result = IntPtr.Zero;
return;
}
break;
case WM.NCLBUTTONDOWN:
if ((ModifierKeys & Keys.Control) == Keys.Control &&
ThumbnailPanel.IsShowingThumbnail &&
!ThumbnailPanel.DrawMouseRegions) {
ThumbnailPanel.EnableMouseRegionsDrawingWithMouseDown();
ThumbnailPanel.RegionDrawn += _quickRegionDrawingHandler;
m.Result = IntPtr.Zero;
return;
}
break;
case WM.NCLBUTTONDBLCLK:
//Toggle fullscreen mode if double click on caption (whole glass area)
if (m.WParam.ToInt32() == HT.CAPTION) {
FullscreenManager.Toggle();
m.Result = IntPtr.Zero;
return;
}
break;
case WM.NCHITTEST:
//Make transparent to hit-testing if in click through mode
if (ClickThroughEnabled) {
m.Result = (IntPtr)HT.TRANSPARENT;
RefreshClickThroughComeBack();
return;
}
break;
}
base.WndProc(ref m);
}
private void HandleQuickRegionDrawn(object sender, ThumbnailRegion region) {
//Reset region drawing state
ThumbnailPanel.DrawMouseRegions = false;
ThumbnailPanel.RegionDrawn -= _quickRegionDrawingHandler;
SelectedThumbnailRegion = region;
}
#endregion
#region Keyboard event handling
protected override void OnKeyUp(KeyEventArgs e) {
base.OnKeyUp(e);
//ALT
if (e.Modifiers == Keys.Alt) {
if (e.KeyCode == Keys.Enter) {
e.Handled = true;
FullscreenManager.Toggle();
}
else if (e.KeyCode == Keys.D1 || e.KeyCode == Keys.NumPad1) {
FitToThumbnail(0.25);
}
else if (e.KeyCode == Keys.D2 || e.KeyCode == Keys.NumPad2) {
FitToThumbnail(0.5);
}
else if (e.KeyCode == Keys.D3 || e.KeyCode == Keys.NumPad3 ||
e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0) {
FitToThumbnail(1.0);
}
else if (e.KeyCode == Keys.D4 || e.KeyCode == Keys.NumPad4) {
FitToThumbnail(2.0);
}
}
//F11 Fullscreen switch
else if (e.KeyCode == Keys.F11) {
e.Handled = true;
FullscreenManager.Toggle();
}
//ESCAPE
else if (e.KeyCode == Keys.Escape) {
//Disable click-through
if (ClickThroughEnabled) {
ClickThroughEnabled = false;
}
//Toggle fullscreen
else if (FullscreenManager.IsFullscreen) {
FullscreenManager.SwitchBack();
}
//Disable click forwarding
else if (ClickForwardingEnabled) {
ClickForwardingEnabled = false;
}
}
}
#endregion
#region Thumbnail operation
/// <summary>
/// Sets a new thumbnail.
/// </summary>
/// <param name="handle">Handle to the window to clone.</param>
/// <param name="region">Region of the window to clone or null.</param>
public void SetThumbnail(WindowHandle handle, ThumbnailRegion region) {
try {
Log.Write("Cloning window HWND {0} of class {1}", handle.Handle, handle.Class);
CurrentThumbnailWindowHandle = handle;
_thumbnailPanel.SetThumbnailHandle(handle, region);
//Set aspect ratio (this will resize the form), do not refresh if in fullscreen
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, !FullscreenManager.IsFullscreen);
}
catch (Exception ex) {
Log.WriteException("Unable to set new thumbnail", ex);
ThumbnailError(ex, false, Strings.ErrorUnableToCreateThumbnail);
_thumbnailPanel.UnsetThumbnail();
}
}
/// <summary>
/// Enables group mode on a list of window handles.
/// </summary>
/// <param name="handles">List of window handles.</param>
public void SetThumbnailGroup(IList<WindowHandle> handles) {
if (handles.Count == 0)
return;
//At last one thumbnail
SetThumbnail(handles[0], null);
//Handle if no real group
if (handles.Count == 1)
return;
CurrentThumbnailWindowHandle = null;
_msgPumpManager.Get<MessagePumpProcessors.GroupSwitchManager>().EnableGroupMode(handles);
}
/// <summary>
/// Disables the cloned thumbnail.
/// </summary>
public void UnsetThumbnail() {
//Unset handle
CurrentThumbnailWindowHandle = null;
_thumbnailPanel.UnsetThumbnail();
//Disable aspect ratio
KeepAspectRatio = false;
}
/// <summary>
/// Gets or sets the region displayed of the current thumbnail.
/// </summary>
public ThumbnailRegion SelectedThumbnailRegion {
get {
if (!_thumbnailPanel.IsShowingThumbnail || !_thumbnailPanel.ConstrainToRegion)
return null;
return _thumbnailPanel.SelectedRegion;
}
set {
if (!_thumbnailPanel.IsShowingThumbnail)
return;
_thumbnailPanel.SelectedRegion = value;
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, true);
FixPositionAndSize();
}
}
const int FixMargin = 10;
/// <summary>
/// Fixes the form's position and size, ensuring it is fully displayed in the current screen.
/// </summary>
private void FixPositionAndSize() {
var screen = Screen.FromControl(this);
if (Width > screen.WorkingArea.Width) {
Width = screen.WorkingArea.Width - FixMargin;
}
if (Height > screen.WorkingArea.Height) {
Height = screen.WorkingArea.Height - FixMargin;
}
if (Location.X + Width > screen.WorkingArea.Right) {
Location = new Point(screen.WorkingArea.Right - Width - FixMargin, Location.Y);
}
if (Location.Y + Height > screen.WorkingArea.Bottom) {
Location = new Point(Location.X, screen.WorkingArea.Bottom - Height - FixMargin);
}
}
private void ThumbnailError(Exception ex, bool suppress, string title) {
if (!suppress) {
ShowErrorDialog(title, Strings.ErrorGenericThumbnailHandleError, ex.Message);
}
UnsetThumbnail();
}
/// <summary>Automatically sizes the window in order to accomodate the thumbnail p times.</summary>
/// <param name="p">Scale of the thumbnail to consider.</param>
private void FitToThumbnail(double p) {
try {
Size originalSize = _thumbnailPanel.ThumbnailPixelSize;
Size fittedSize = new Size((int)(originalSize.Width * p), (int)(originalSize.Height * p));
ClientSize = fittedSize;
RefreshScreenLock();
}
catch (Exception ex) {
ThumbnailError(ex, false, Strings.ErrorUnableToFit);
}
}
#endregion
#region Accessors
/// <summary>
/// Gets the form's thumbnail panel.
/// </summary>
public ThumbnailPanel ThumbnailPanel {
get {
return _thumbnailPanel;
}
}
/// <summary>
/// Gets the form's message pump manager.
/// </summary>
public MessagePumpManager MessagePumpManager {
get {
return _msgPumpManager;
}
}
/// <summary>
/// Gets the form's window list drop down menu.
/// </summary>
public ContextMenuStrip MenuWindows {
get {
return menuWindows;
}
}
/// <summary>
/// Retrieves the window handle of the currently cloned thumbnail.
/// </summary>
public WindowHandle CurrentThumbnailWindowHandle {
get;
private set;
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using OnTopReplica.Native;
using OnTopReplica.Properties;
using OnTopReplica.StartupOptions;
using OnTopReplica.Update;
using OnTopReplica.WindowSeekers;
using WindowsFormsAero.Dwm;
using WindowsFormsAero.TaskDialog;
namespace OnTopReplica {
partial class MainForm : AspectRatioForm {
//GUI elements
ThumbnailPanel _thumbnailPanel;
//Managers
readonly MessagePumpManager _msgPumpManager = new MessagePumpManager();
WindowListMenuManager _windowListManager;
public FullscreenFormManager FullscreenManager { get; private set; }
Options _startupOptions;
public MainForm(Options startupOptions) {
_startupOptions = startupOptions;
FullscreenManager = new FullscreenFormManager(this);
_quickRegionDrawingHandler = new ThumbnailPanel.RegionDrawnHandler(HandleQuickRegionDrawn);
//WinForms init pass
InitializeComponent();
//Store default values
DefaultNonClickTransparencyKey = this.TransparencyKey;
DefaultBorderStyle = this.FormBorderStyle;
//Thumbnail panel
_thumbnailPanel = new ThumbnailPanel {
Location = Point.Empty,
Dock = DockStyle.Fill
};
_thumbnailPanel.CloneClick += new EventHandler<CloneClickEventArgs>(Thumbnail_CloneClick);
Controls.Add(_thumbnailPanel);
//Set native renderer on context menus
Asztal.Szótár.NativeToolStripRenderer.SetToolStripRenderer(
menuContext, menuWindows, menuOpacity, menuResize, menuFullscreenContext
);
//Set to Key event preview
this.KeyPreview = true;
Log.Write("Main form constructed");
}
#region Event override
protected override void OnHandleCreated(EventArgs e){
base.OnHandleCreated(e);
//Window init
KeepAspectRatio = false;
GlassMargins = new Padding(-1);
//Managers
_msgPumpManager.Initialize(this);
_windowListManager = new WindowListMenuManager(this, menuWindows);
_windowListManager.ParentMenus = new System.Windows.Forms.ContextMenuStrip[] {
menuContext, menuFullscreenContext
};
//Platform specific form initialization
Program.Platform.PostHandleFormInit(this);
}
protected override void OnShown(EventArgs e) {
Log.Write("Main form shown");
base.OnShown(e);
//Apply startup options
_startupOptions.Apply(this);
}
protected override void OnClosing(CancelEventArgs e) {
Log.Write("Main form closing");
base.OnClosing(e);
_msgPumpManager.Dispose();
Program.Platform.CloseForm(this);
}
protected override void OnClosed(EventArgs e) {
Log.Write("Main form closed");
base.OnClosed(e);
}
protected override void OnMove(EventArgs e) {
base.OnMove(e);
AdjustSidePanelLocation();
}
protected override void OnResizeEnd(EventArgs e) {
base.OnResizeEnd(e);
RefreshScreenLock();
}
protected override void OnResizing(EventArgs e) {
//Update aspect ratio from thumbnail while resizing (but do not refresh, resizing does that anyway)
if (_thumbnailPanel.IsShowingThumbnail) {
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, false);
}
}
protected override void OnActivated(EventArgs e) {
base.OnActivated(e);
//Deactivate click-through if form is reactivated
if (ClickThroughEnabled) {
ClickThroughEnabled = false;
}
Program.Platform.RestoreForm(this);
}
protected override void OnDeactivate(EventArgs e) {
base.OnDeactivate(e);
//HACK: sometimes, even if TopMost is true, the window loses its "always on top" status.
// This is a fix attempt that probably won't work...
if (!FullscreenManager.IsFullscreen) { //fullscreen mode doesn't use TopMost
TopMost = false;
TopMost = true;
}
}
protected override void OnMouseWheel(MouseEventArgs e) {
base.OnMouseWheel(e);
if (!FullscreenManager.IsFullscreen) {
if (_thumbnailPanel.IsShowingThumbnail) {
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, false);
}
int change = (int)(e.Delta / 6.0); //assumes a mouse wheel "tick" is in the 80-120 range
AdjustSize(change);
RefreshScreenLock();
}
}
protected override void OnMouseDoubleClick(MouseEventArgs e) {
base.OnMouseDoubleClick(e);
//This is handled by the WM_NCLBUTTONDBLCLK msg handler usually (because the GlassForm translates
//clicks on client to clicks on caption). But if fullscreen mode disables GlassForm dragging, we need
//this auxiliary handler to switch mode.
FullscreenManager.Toggle();
}
protected override void OnMouseClick(MouseEventArgs e) {
base.OnMouseClick(e);
//Same story as above (OnMouseDoubleClick)
if (e.Button == System.Windows.Forms.MouseButtons.Right) {
OpenContextMenu(null);
}
}
private ThumbnailPanel.RegionDrawnHandler _quickRegionDrawingHandler;
protected override void WndProc(ref Message m) {
if (_msgPumpManager != null) {
if (_msgPumpManager.PumpMessage(ref m)) {
return;
}
}
switch (m.Msg) {
case WM.NCRBUTTONUP:
//Open context menu if right button clicked on caption (i.e. all of the window area because of glass)
if (m.WParam.ToInt32() == HT.CAPTION) {
OpenContextMenu(null);
m.Result = IntPtr.Zero;
return;
}
break;
case WM.NCLBUTTONDOWN:
if ((ModifierKeys & Keys.Control) == Keys.Control &&
ThumbnailPanel.IsShowingThumbnail &&
!ThumbnailPanel.DrawMouseRegions) {
ThumbnailPanel.EnableMouseRegionsDrawingWithMouseDown();
ThumbnailPanel.RegionDrawn += _quickRegionDrawingHandler;
m.Result = IntPtr.Zero;
return;
}
break;
case WM.NCLBUTTONDBLCLK:
//Toggle fullscreen mode if double click on caption (whole glass area)
if (m.WParam.ToInt32() == HT.CAPTION) {
FullscreenManager.Toggle();
m.Result = IntPtr.Zero;
return;
}
break;
case WM.NCHITTEST:
//Make transparent to hit-testing if in click through mode
if (ClickThroughEnabled) {
m.Result = (IntPtr)HT.TRANSPARENT;
RefreshClickThroughComeBack();
return;
}
break;
}
base.WndProc(ref m);
}
private void HandleQuickRegionDrawn(object sender, ThumbnailRegion region) {
//Reset region drawing state
ThumbnailPanel.DrawMouseRegions = false;
ThumbnailPanel.RegionDrawn -= _quickRegionDrawingHandler;
SelectedThumbnailRegion = region;
}
#endregion
#region Keyboard event handling
protected override void OnKeyUp(KeyEventArgs e) {
base.OnKeyUp(e);
//ALT
if (e.Modifiers == Keys.Alt) {
if (e.KeyCode == Keys.Enter) {
e.Handled = true;
FullscreenManager.Toggle();
}
else if (e.KeyCode == Keys.D1 || e.KeyCode == Keys.NumPad1) {
FitToThumbnail(0.25);
}
else if (e.KeyCode == Keys.D2 || e.KeyCode == Keys.NumPad2) {
FitToThumbnail(0.5);
}
else if (e.KeyCode == Keys.D3 || e.KeyCode == Keys.NumPad3 ||
e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0) {
FitToThumbnail(1.0);
}
else if (e.KeyCode == Keys.D4 || e.KeyCode == Keys.NumPad4) {
FitToThumbnail(2.0);
}
}
//F11 Fullscreen switch
else if (e.KeyCode == Keys.F11) {
e.Handled = true;
FullscreenManager.Toggle();
}
//ESCAPE
else if (e.KeyCode == Keys.Escape) {
//Disable click-through
if (ClickThroughEnabled) {
ClickThroughEnabled = false;
}
//Toggle fullscreen
else if (FullscreenManager.IsFullscreen) {
FullscreenManager.SwitchBack();
}
//Disable click forwarding
else if (ClickForwardingEnabled) {
ClickForwardingEnabled = false;
}
}
}
#endregion
#region Thumbnail operation
/// <summary>
/// Sets a new thumbnail.
/// </summary>
/// <param name="handle">Handle to the window to clone.</param>
/// <param name="region">Region of the window to clone or null.</param>
public void SetThumbnail(WindowHandle handle, ThumbnailRegion region) {
try {
Log.Write("Cloning window HWND {0} of class {1}", handle.Handle, handle.Class);
CurrentThumbnailWindowHandle = handle;
_thumbnailPanel.SetThumbnailHandle(handle, region);
//Set aspect ratio (this will resize the form), do not refresh if in fullscreen
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, !FullscreenManager.IsFullscreen);
}
catch (Exception ex) {
Log.WriteException("Unable to set new thumbnail", ex);
ThumbnailError(ex, false, Strings.ErrorUnableToCreateThumbnail);
_thumbnailPanel.UnsetThumbnail();
}
}
/// <summary>
/// Enables group mode on a list of window handles.
/// </summary>
/// <param name="handles">List of window handles.</param>
public void SetThumbnailGroup(IList<WindowHandle> handles) {
if (handles.Count == 0)
return;
//At last one thumbnail
SetThumbnail(handles[0], null);
//Handle if no real group
if (handles.Count == 1)
return;
CurrentThumbnailWindowHandle = null;
_msgPumpManager.Get<MessagePumpProcessors.GroupSwitchManager>().EnableGroupMode(handles);
}
/// <summary>
/// Disables the cloned thumbnail.
/// </summary>
public void UnsetThumbnail() {
//Unset handle
CurrentThumbnailWindowHandle = null;
_thumbnailPanel.UnsetThumbnail();
//Disable aspect ratio
KeepAspectRatio = false;
}
/// <summary>
/// Gets or sets the region displayed of the current thumbnail.
/// </summary>
public ThumbnailRegion SelectedThumbnailRegion {
get {
if (!_thumbnailPanel.IsShowingThumbnail || !_thumbnailPanel.ConstrainToRegion)
return null;
return _thumbnailPanel.SelectedRegion;
}
set {
if (!_thumbnailPanel.IsShowingThumbnail)
return;
_thumbnailPanel.SelectedRegion = value;
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, true);
FixPositionAndSize();
}
}
const int FixMargin = 10;
/// <summary>
/// Fixes the form's position and size, ensuring it is fully displayed in the current screen.
/// </summary>
private void FixPositionAndSize() {
var screen = Screen.FromControl(this);
if (Width > screen.WorkingArea.Width) {
Width = screen.WorkingArea.Width - FixMargin;
}
if (Height > screen.WorkingArea.Height) {
Height = screen.WorkingArea.Height - FixMargin;
}
if (Location.X + Width > screen.WorkingArea.Right) {
Location = new Point(screen.WorkingArea.Right - Width - FixMargin, Location.Y);
}
if (Location.Y + Height > screen.WorkingArea.Bottom) {
Location = new Point(Location.X, screen.WorkingArea.Bottom - Height - FixMargin);
}
}
private void ThumbnailError(Exception ex, bool suppress, string title) {
if (!suppress) {
ShowErrorDialog(title, Strings.ErrorGenericThumbnailHandleError, ex.Message);
}
UnsetThumbnail();
}
/// <summary>Automatically sizes the window in order to accomodate the thumbnail p times.</summary>
/// <param name="p">Scale of the thumbnail to consider.</param>
private void FitToThumbnail(double p) {
try {
Size originalSize = _thumbnailPanel.ThumbnailPixelSize;
Size fittedSize = new Size((int)(originalSize.Width * p), (int)(originalSize.Height * p));
ClientSize = fittedSize;
RefreshScreenLock();
}
catch (Exception ex) {
ThumbnailError(ex, false, Strings.ErrorUnableToFit);
}
}
#endregion
#region Accessors
/// <summary>
/// Gets the form's thumbnail panel.
/// </summary>
public ThumbnailPanel ThumbnailPanel {
get {
return _thumbnailPanel;
}
}
/// <summary>
/// Gets the form's message pump manager.
/// </summary>
public MessagePumpManager MessagePumpManager {
get {
return _msgPumpManager;
}
}
/// <summary>
/// Gets the form's window list drop down menu.
/// </summary>
public ContextMenuStrip MenuWindows {
get {
return menuWindows;
}
}
/// <summary>
/// Retrieves the window handle of the currently cloned thumbnail.
/// </summary>
public WindowHandle CurrentThumbnailWindowHandle {
get;
private set;
}
#endregion
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,93 +1,93 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace OnTopReplica {
partial class MainForm {
//SidePanel _currentSidePanel = null;
SidePanelContainer _sidePanelContainer = null;
/// <summary>
/// Opens a new side panel.
/// </summary>
/// <param name="panel">The side panel to embed.</param>
public void SetSidePanel(SidePanel panel) {
if (IsSidePanelOpen) {
CloseSidePanel();
}
_sidePanelContainer = new SidePanelContainer(this);
_sidePanelContainer.SetSidePanel(panel);
_sidePanelContainer.Location = ComputeSidePanelLocation(_sidePanelContainer);
_sidePanelContainer.Show(this);
}
/// <summary>
/// Closes the current side panel.
/// </summary>
public void CloseSidePanel() {
if (_sidePanelContainer == null || _sidePanelContainer.IsDisposed) {
_sidePanelContainer = null;
return;
}
_sidePanelContainer.Hide();
_sidePanelContainer.FreeSidePanel();
}
/// <summary>
/// Gets whether a side panel is currently shown.
/// </summary>
public bool IsSidePanelOpen {
get {
if (_sidePanelContainer == null)
return false;
if (_sidePanelContainer.IsDisposed) {
_sidePanelContainer = null;
return false;
}
return _sidePanelContainer.Visible;
}
}
/// <summary>
/// Moves the side panel based on the main form's current location.
/// </summary>
protected void AdjustSidePanelLocation() {
if (!IsSidePanelOpen)
return;
_sidePanelContainer.Location = ComputeSidePanelLocation(_sidePanelContainer);
}
/// <summary>
/// Computes the target location of a side panel form that ensures it is visible on the current
/// screen that contains the main form.
/// </summary>
private Point ComputeSidePanelLocation(Form sidePanel) {
//Check if moving the panel on the form's right would put it off-screen
var screen = Screen.FromControl(this);
if (Location.X + Width + sidePanel.Width > screen.WorkingArea.Right) {
return new Point(Location.X - sidePanel.Width, Location.Y);
}
else {
return new Point(Location.X + Width, Location.Y);
}
}
void SidePanel_RequestClosing(object sender, EventArgs e) {
CloseSidePanel();
}
void Thumbnail_CloneClick(object sender, CloneClickEventArgs e) {
Win32Helper.InjectFakeMouseClick(CurrentThumbnailWindowHandle.Handle, e);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace OnTopReplica {
partial class MainForm {
//SidePanel _currentSidePanel = null;
SidePanelContainer _sidePanelContainer = null;
/// <summary>
/// Opens a new side panel.
/// </summary>
/// <param name="panel">The side panel to embed.</param>
public void SetSidePanel(SidePanel panel) {
if (IsSidePanelOpen) {
CloseSidePanel();
}
_sidePanelContainer = new SidePanelContainer(this);
_sidePanelContainer.SetSidePanel(panel);
_sidePanelContainer.Location = ComputeSidePanelLocation(_sidePanelContainer);
_sidePanelContainer.Show(this);
}
/// <summary>
/// Closes the current side panel.
/// </summary>
public void CloseSidePanel() {
if (_sidePanelContainer == null || _sidePanelContainer.IsDisposed) {
_sidePanelContainer = null;
return;
}
_sidePanelContainer.Hide();
_sidePanelContainer.FreeSidePanel();
}
/// <summary>
/// Gets whether a side panel is currently shown.
/// </summary>
public bool IsSidePanelOpen {
get {
if (_sidePanelContainer == null)
return false;
if (_sidePanelContainer.IsDisposed) {
_sidePanelContainer = null;
return false;
}
return _sidePanelContainer.Visible;
}
}
/// <summary>
/// Moves the side panel based on the main form's current location.
/// </summary>
protected void AdjustSidePanelLocation() {
if (!IsSidePanelOpen)
return;
_sidePanelContainer.Location = ComputeSidePanelLocation(_sidePanelContainer);
}
/// <summary>
/// Computes the target location of a side panel form that ensures it is visible on the current
/// screen that contains the main form.
/// </summary>
private Point ComputeSidePanelLocation(Form sidePanel) {
//Check if moving the panel on the form's right would put it off-screen
var screen = Screen.FromControl(this);
if (Location.X + Width + sidePanel.Width > screen.WorkingArea.Right) {
return new Point(Location.X - sidePanel.Width, Location.Y);
}
else {
return new Point(Location.X + Width, Location.Y);
}
}
void SidePanel_RequestClosing(object sender, EventArgs e) {
CloseSidePanel();
}
void Thumbnail_CloneClick(object sender, CloneClickEventArgs e) {
Win32Helper.InjectFakeMouseClick(CurrentThumbnailWindowHandle.Handle, e);
}
}
}

View file

@ -1,167 +1,167 @@
using OnTopReplica.Native;
using OnTopReplica.Properties;
using System;
using System.Drawing;
using System.Windows.Forms;
using WindowsFormsAero.TaskDialog;
namespace OnTopReplica {
//Contains some feature implementations of MainForm
partial class MainForm {
#region Click forwarding
public bool ClickForwardingEnabled {
get {
return _thumbnailPanel.ReportThumbnailClicks;
}
set {
if (value && Settings.Default.FirstTimeClickForwarding) {
TaskDialog dlg = new TaskDialog(Strings.InfoClickForwarding, Strings.InfoClickForwardingTitle, Strings.InfoClickForwardingContent) {
CommonButtons = CommonButton.Yes | CommonButton.No
};
if (dlg.Show(this).CommonButton == CommonButtonResult.No)
return;
Settings.Default.FirstTimeClickForwarding = false;
}
_thumbnailPanel.ReportThumbnailClicks = value;
}
}
#endregion
#region Click-through
bool _clickThrough = false;
readonly Color DefaultNonClickTransparencyKey;
public bool ClickThroughEnabled {
get {
return _clickThrough;
}
set {
TransparencyKey = (value) ? Color.Black : DefaultNonClickTransparencyKey;
if (value) {
//Re-force as top most (always helps in some cases)
TopMost = false;
this.Activate();
TopMost = true;
}
_clickThrough = value;
}
}
//Must NOT be equal to any other valid opacity value
const double ClickThroughHoverOpacity = 0.6;
Timer _clickThroughComeBackTimer = null;
long _clickThroughComeBackTicks;
const int ClickThroughComeBackTimerInterval = 1000;
/// <summary>
/// When the mouse hovers over a fully opaque click-through form,
/// this fades the form to semi-transparency
/// and starts a timeout to get back to full opacity.
/// </summary>
private void RefreshClickThroughComeBack() {
if (this.Opacity == 1.0) {
this.Opacity = ClickThroughHoverOpacity;
}
if (_clickThroughComeBackTimer == null) {
_clickThroughComeBackTimer = new Timer();
_clickThroughComeBackTimer.Tick += _clickThroughComeBackTimer_Tick;
_clickThroughComeBackTimer.Interval = ClickThroughComeBackTimerInterval;
}
_clickThroughComeBackTicks = DateTime.UtcNow.Ticks;
_clickThroughComeBackTimer.Start();
}
void _clickThroughComeBackTimer_Tick(object sender, EventArgs e) {
var diff = DateTime.UtcNow.Subtract(new DateTime(_clickThroughComeBackTicks));
if (diff.TotalSeconds > 2) {
var mousePointer = WindowMethods.GetCursorPos();
if (!this.ContainsMousePointer(mousePointer)) {
if (this.Opacity == ClickThroughHoverOpacity) {
this.Opacity = 1.0;
}
_clickThroughComeBackTimer.Stop();
}
}
}
#endregion
#region Chrome
readonly FormBorderStyle DefaultBorderStyle; // = FormBorderStyle.Sizable; // FormBorderStyle.SizableToolWindow;
public bool IsChromeVisible {
get {
return (FormBorderStyle == DefaultBorderStyle);
}
set {
//Cancel hiding chrome if no thumbnail is shown
if (!value && !_thumbnailPanel.IsShowingThumbnail)
return;
if (!value) {
Location = new Point {
X = Location.X + SystemInformation.FrameBorderSize.Width,
Y = Location.Y + SystemInformation.FrameBorderSize.Height
};
FormBorderStyle = FormBorderStyle.None;
}
else if(value) {
Location = new Point {
X = Location.X - SystemInformation.FrameBorderSize.Width,
Y = Location.Y - SystemInformation.FrameBorderSize.Height
};
FormBorderStyle = DefaultBorderStyle;
}
Program.Platform.OnFormStateChange(this);
Invalidate();
}
}
#endregion
#region Position lock
ScreenPosition? _positionLock = null;
/// <summary>
/// Gets or sets the screen position where the window is currently locked in.
/// </summary>
public ScreenPosition? PositionLock {
get {
return _positionLock;
}
set {
if (value != null)
this.SetScreenPosition(value.Value);
_positionLock = value;
}
}
/// <summary>
/// Refreshes window position if in lock mode.
/// </summary>
private void RefreshScreenLock() {
//If locked in position, move accordingly
if (PositionLock.HasValue) {
this.SetScreenPosition(PositionLock.Value);
}
}
#endregion
}
}
using OnTopReplica.Native;
using OnTopReplica.Properties;
using System;
using System.Drawing;
using System.Windows.Forms;
using WindowsFormsAero.TaskDialog;
namespace OnTopReplica {
//Contains some feature implementations of MainForm
partial class MainForm {
#region Click forwarding
public bool ClickForwardingEnabled {
get {
return _thumbnailPanel.ReportThumbnailClicks;
}
set {
if (value && Settings.Default.FirstTimeClickForwarding) {
TaskDialog dlg = new TaskDialog(Strings.InfoClickForwarding, Strings.InfoClickForwardingTitle, Strings.InfoClickForwardingContent) {
CommonButtons = CommonButton.Yes | CommonButton.No
};
if (dlg.Show(this).CommonButton == CommonButtonResult.No)
return;
Settings.Default.FirstTimeClickForwarding = false;
}
_thumbnailPanel.ReportThumbnailClicks = value;
}
}
#endregion
#region Click-through
bool _clickThrough = false;
readonly Color DefaultNonClickTransparencyKey;
public bool ClickThroughEnabled {
get {
return _clickThrough;
}
set {
TransparencyKey = (value) ? Color.Black : DefaultNonClickTransparencyKey;
if (value) {
//Re-force as top most (always helps in some cases)
TopMost = false;
this.Activate();
TopMost = true;
}
_clickThrough = value;
}
}
//Must NOT be equal to any other valid opacity value
const double ClickThroughHoverOpacity = 0.6;
Timer _clickThroughComeBackTimer = null;
long _clickThroughComeBackTicks;
const int ClickThroughComeBackTimerInterval = 1000;
/// <summary>
/// When the mouse hovers over a fully opaque click-through form,
/// this fades the form to semi-transparency
/// and starts a timeout to get back to full opacity.
/// </summary>
private void RefreshClickThroughComeBack() {
if (this.Opacity == 1.0) {
this.Opacity = ClickThroughHoverOpacity;
}
if (_clickThroughComeBackTimer == null) {
_clickThroughComeBackTimer = new Timer();
_clickThroughComeBackTimer.Tick += _clickThroughComeBackTimer_Tick;
_clickThroughComeBackTimer.Interval = ClickThroughComeBackTimerInterval;
}
_clickThroughComeBackTicks = DateTime.UtcNow.Ticks;
_clickThroughComeBackTimer.Start();
}
void _clickThroughComeBackTimer_Tick(object sender, EventArgs e) {
var diff = DateTime.UtcNow.Subtract(new DateTime(_clickThroughComeBackTicks));
if (diff.TotalSeconds > 2) {
var mousePointer = WindowMethods.GetCursorPos();
if (!this.ContainsMousePointer(mousePointer)) {
if (this.Opacity == ClickThroughHoverOpacity) {
this.Opacity = 1.0;
}
_clickThroughComeBackTimer.Stop();
}
}
}
#endregion
#region Chrome
readonly FormBorderStyle DefaultBorderStyle; // = FormBorderStyle.Sizable; // FormBorderStyle.SizableToolWindow;
public bool IsChromeVisible {
get {
return (FormBorderStyle == DefaultBorderStyle);
}
set {
//Cancel hiding chrome if no thumbnail is shown
if (!value && !_thumbnailPanel.IsShowingThumbnail)
return;
if (!value) {
Location = new Point {
X = Location.X + SystemInformation.FrameBorderSize.Width,
Y = Location.Y + SystemInformation.FrameBorderSize.Height
};
FormBorderStyle = FormBorderStyle.None;
}
else if(value) {
Location = new Point {
X = Location.X - SystemInformation.FrameBorderSize.Width,
Y = Location.Y - SystemInformation.FrameBorderSize.Height
};
FormBorderStyle = DefaultBorderStyle;
}
Program.Platform.OnFormStateChange(this);
Invalidate();
}
}
#endregion
#region Position lock
ScreenPosition? _positionLock = null;
/// <summary>
/// Gets or sets the screen position where the window is currently locked in.
/// </summary>
public ScreenPosition? PositionLock {
get {
return _positionLock;
}
set {
if (value != null)
this.SetScreenPosition(value.Value);
_positionLock = value;
}
}
/// <summary>
/// Refreshes window position if in lock mode.
/// </summary>
private void RefreshScreenLock() {
//If locked in position, move accordingly
if (PositionLock.HasValue) {
this.SetScreenPosition(PositionLock.Value);
}
}
#endregion
}
}

View file

@ -1,117 +1,117 @@
using System.Drawing;
using System.Windows.Forms;
using WindowsFormsAero.TaskDialog;
namespace OnTopReplica {
partial class MainForm {
/// <summary>
/// Opens the context menu.
/// </summary>
/// <param name="position">Optional position of the mouse, relative to which the menu is shown.</param>
public void OpenContextMenu(Point? position) {
Point menuPosition = MousePosition;
if (position.HasValue)
menuPosition = position.Value;
if (FullscreenManager.IsFullscreen) {
menuFullscreenContext.Show(menuPosition);
}
else {
menuContext.Show(menuPosition);
}
}
/// <summary>
/// Gets the window's vertical chrome size.
/// </summary>
public int ChromeBorderVertical {
get {
if (IsChromeVisible)
return SystemInformation.FrameBorderSize.Height;
else
return 0;
}
}
/// <summary>
/// Gets the window's horizontal chrome size.
/// </summary>
public int ChromeBorderHorizontal {
get {
if (IsChromeVisible)
return SystemInformation.FrameBorderSize.Width;
else
return 0;
}
}
/// <summary>
/// Displays an error task dialog.
/// </summary>
/// <param name="mainInstruction">Main instruction of the error dialog.</param>
/// <param name="explanation">Detailed informations about the error.</param>
/// <param name="errorMessage">Expanded error codes/messages.</param>
private void ShowErrorDialog(string mainInstruction, string explanation, string errorMessage) {
TaskDialog dlg = new TaskDialog(mainInstruction, Strings.ErrorGenericTitle, explanation) {
CommonIcon = CommonIcon.Stop,
IsExpanded = false
};
if (!string.IsNullOrEmpty(errorMessage)) {
dlg.ExpandedInformation = Strings.ErrorGenericInfoText + errorMessage;
dlg.ExpandedControlText = Strings.ErrorGenericInfoButton;
}
dlg.Show(this);
}
/// <summary>
/// Ensures that the main form is visible (either closing the fullscreen mode or reactivating from task icon).
/// </summary>
public void EnsureMainFormVisible() {
//Reset special modes
FullscreenManager.SwitchBack();
ClickThroughEnabled = false;
//Restore main form in a platform-dependent method
Program.Platform.RestoreForm(this);
}
/// <summary>
/// Opens a confirmation dialog to confirm whether to reset the main form or not.
/// </summary>
public void ResetMainFormWithConfirmation() {
var dlg = new TaskDialog(Strings.AskReset, Strings.AskResetTitle, Strings.AskResetContent);
dlg.UseCommandLinks = true;
dlg.CustomButtons = new CustomButton[] {
new CustomButton(CommonButtonResult.OK, Strings.AskResetButtonOk),
new CustomButton(CommonButtonResult.Cancel, Strings.ButtonCancel)
};
dlg.CommonIcon = CommonIcon.Information;
if (dlg.Show(this).CommonButton == CommonButtonResult.OK) {
ResetMainForm();
}
}
/// <summary>
/// Resets the main form to its initial state.
/// </summary>
public void ResetMainForm() {
//Reset form settings
UnsetThumbnail();
CloseSidePanel();
//Reset location and size (edge of the screen, min size)
Point nuLoc = Screen.PrimaryScreen.WorkingArea.Location;
nuLoc.Offset(40, 40);
Location = nuLoc;
Size = new Size(240, 220);
this.Show();
this.Activate();
}
}
}
using System.Drawing;
using System.Windows.Forms;
using WindowsFormsAero.TaskDialog;
namespace OnTopReplica {
partial class MainForm {
/// <summary>
/// Opens the context menu.
/// </summary>
/// <param name="position">Optional position of the mouse, relative to which the menu is shown.</param>
public void OpenContextMenu(Point? position) {
Point menuPosition = MousePosition;
if (position.HasValue)
menuPosition = position.Value;
if (FullscreenManager.IsFullscreen) {
menuFullscreenContext.Show(menuPosition);
}
else {
menuContext.Show(menuPosition);
}
}
/// <summary>
/// Gets the window's vertical chrome size.
/// </summary>
public int ChromeBorderVertical {
get {
if (IsChromeVisible)
return SystemInformation.FrameBorderSize.Height;
else
return 0;
}
}
/// <summary>
/// Gets the window's horizontal chrome size.
/// </summary>
public int ChromeBorderHorizontal {
get {
if (IsChromeVisible)
return SystemInformation.FrameBorderSize.Width;
else
return 0;
}
}
/// <summary>
/// Displays an error task dialog.
/// </summary>
/// <param name="mainInstruction">Main instruction of the error dialog.</param>
/// <param name="explanation">Detailed informations about the error.</param>
/// <param name="errorMessage">Expanded error codes/messages.</param>
private void ShowErrorDialog(string mainInstruction, string explanation, string errorMessage) {
TaskDialog dlg = new TaskDialog(mainInstruction, Strings.ErrorGenericTitle, explanation) {
CommonIcon = CommonIcon.Stop,
IsExpanded = false
};
if (!string.IsNullOrEmpty(errorMessage)) {
dlg.ExpandedInformation = Strings.ErrorGenericInfoText + errorMessage;
dlg.ExpandedControlText = Strings.ErrorGenericInfoButton;
}
dlg.Show(this);
}
/// <summary>
/// Ensures that the main form is visible (either closing the fullscreen mode or reactivating from task icon).
/// </summary>
public void EnsureMainFormVisible() {
//Reset special modes
FullscreenManager.SwitchBack();
ClickThroughEnabled = false;
//Restore main form in a platform-dependent method
Program.Platform.RestoreForm(this);
}
/// <summary>
/// Opens a confirmation dialog to confirm whether to reset the main form or not.
/// </summary>
public void ResetMainFormWithConfirmation() {
var dlg = new TaskDialog(Strings.AskReset, Strings.AskResetTitle, Strings.AskResetContent);
dlg.UseCommandLinks = true;
dlg.CustomButtons = new CustomButton[] {
new CustomButton(CommonButtonResult.OK, Strings.AskResetButtonOk),
new CustomButton(CommonButtonResult.Cancel, Strings.ButtonCancel)
};
dlg.CommonIcon = CommonIcon.Information;
if (dlg.Show(this).CommonButton == CommonButtonResult.OK) {
ResetMainForm();
}
}
/// <summary>
/// Resets the main form to its initial state.
/// </summary>
public void ResetMainForm() {
//Reset form settings
UnsetThumbnail();
CloseSidePanel();
//Reset location and size (edge of the screen, min size)
Point nuLoc = Screen.PrimaryScreen.WorkingArea.Location;
nuLoc.Offset(40, 40);
Location = nuLoc;
Size = new Size(240, 220);
this.Show();
this.Activate();
}
}
}

View file

@ -1,202 +1,202 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using OnTopReplica.Properties;
using WindowsFormsAero.TaskDialog;
using OnTopReplica.SidePanels;
namespace OnTopReplica {
partial class MainForm {
private void Menu_opening(object sender, CancelEventArgs e) {
//Cancel if currently in "fullscreen" mode or a side panel is open
if (FullscreenManager.IsFullscreen || IsSidePanelOpen) {
e.Cancel = true;
return;
}
bool showing = _thumbnailPanel.IsShowingThumbnail;
selectRegionToolStripMenuItem.Enabled = showing;
switchToWindowToolStripMenuItem.Enabled = showing;
resizeToolStripMenuItem.Enabled = showing;
chromeToolStripMenuItem.Checked = IsChromeVisible;
clickForwardingToolStripMenuItem.Checked = ClickForwardingEnabled;
chromeToolStripMenuItem.Enabled = showing;
clickThroughToolStripMenuItem.Enabled = showing;
clickForwardingToolStripMenuItem.Enabled = showing;
}
private void Menu_Switch_click(object sender, EventArgs e) {
if (CurrentThumbnailWindowHandle == null)
return;
Program.Platform.HideForm(this);
Native.WindowManagerMethods.SetForegroundWindow(CurrentThumbnailWindowHandle.Handle);
}
private void Menu_Advanced_opening(object sender, EventArgs e) {
restoreLastClonedWindowToolStripMenuItem.Checked = Settings.Default.RestoreLastWindow;
}
private void Menu_GroupSwitchMode_click(object sender, EventArgs e) {
SetSidePanel(new SidePanels.GroupSwitchPanel());
}
private void Menu_RestoreLastWindow_click(object sender, EventArgs e) {
Settings.Default.RestoreLastWindow = !Settings.Default.RestoreLastWindow;
}
private void Menu_ClickForwarding_click(object sender, EventArgs e) {
ClickForwardingEnabled = !ClickForwardingEnabled;
}
private void Menu_ClickThrough_click(object sender, EventArgs e) {
ClickThroughEnabled = true;
}
private void Menu_Opacity_opening(object sender, CancelEventArgs e) {
ToolStripMenuItem[] items = {
toolStripMenuItem1,
toolStripMenuItem2,
toolStripMenuItem3,
toolStripMenuItem4
};
foreach (ToolStripMenuItem i in items) {
if (((double)i.Tag) == this.Opacity)
i.Checked = true;
else
i.Checked = false;
}
}
private void Menu_Opacity_click(object sender, EventArgs e) {
ToolStripMenuItem tsi = (ToolStripMenuItem)sender;
if (this.Visible) {
//Target opacity is stored in the item's tag
this.Opacity = (double)tsi.Tag;
Program.Platform.OnFormStateChange(this);
}
}
private void Menu_Region_click(object sender, EventArgs e) {
SetSidePanel(new OnTopReplica.SidePanels.RegionPanel());
}
private void Menu_Resize_opening(object sender, CancelEventArgs e) {
if (!_thumbnailPanel.IsShowingThumbnail)
e.Cancel = true;
restorePositionAndSizeToolStripMenuItem.Checked = Settings.Default.RestoreSizeAndPosition;
}
private void Menu_Resize_Double(object sender, EventArgs e) {
FitToThumbnail(2.0);
}
private void Menu_Resize_FitToWindow(object sender, EventArgs e) {
FitToThumbnail(1.0);
}
private void Menu_Resize_Half(object sender, EventArgs e) {
FitToThumbnail(0.5);
}
private void Menu_Resize_Quarter(object sender, EventArgs e) {
FitToThumbnail(0.25);
}
private void Menu_Resize_Fullscreen(object sender, EventArgs e) {
FullscreenManager.SwitchFullscreen();
}
private void Menu_Resize_RecallPosition_click(object sender, EventArgs e) {
Settings.Default.RestoreSizeAndPosition = !Settings.Default.RestoreSizeAndPosition;
}
private void Menu_Position_Opening(object sender, EventArgs e) {
disabledToolStripMenuItem.Checked = (PositionLock == null);
topLeftToolStripMenuItem.Checked = (PositionLock == ScreenPosition.TopLeft);
topRightToolStripMenuItem.Checked = (PositionLock == ScreenPosition.TopRight);
centerToolStripMenuItem.Checked = (PositionLock == ScreenPosition.Center);
bottomLeftToolStripMenuItem.Checked = (PositionLock == ScreenPosition.BottomLeft);
bottomRightToolStripMenuItem.Checked = (PositionLock == ScreenPosition.BottomRight);
}
private void Menu_Position_Disable(object sender, EventArgs e) {
PositionLock = null;
}
private void Menu_Position_TopLeft(object sender, EventArgs e) {
PositionLock = ScreenPosition.TopLeft;
}
private void Menu_Position_TopRight(object sender, EventArgs e) {
PositionLock = ScreenPosition.TopRight;
}
private void Menu_Position_Center(object sender, EventArgs e) {
PositionLock = ScreenPosition.Center;
}
private void Menu_Position_BottomLeft(object sender, EventArgs e) {
PositionLock = ScreenPosition.BottomLeft;
}
private void Menu_Position_BottomRight(object sender, EventArgs e) {
PositionLock = ScreenPosition.BottomRight;
}
private void Menu_Reduce_click(object sender, EventArgs e) {
//Hide form in a platform specific way
Program.Platform.HideForm(this);
}
private void Menu_Chrome_click(object sender, EventArgs e) {
IsChromeVisible = !IsChromeVisible;
}
private void Menu_Settings_click(object sender, EventArgs e) {
this.SetSidePanel(new OptionsPanel());
}
private void Menu_About_click(object sender, EventArgs e) {
this.SetSidePanel(new AboutPanel());
}
private void Menu_Close_click(object sender, EventArgs e) {
this.Close();
}
private void Menu_Fullscreen_ExitFullscreen_click(object sender, EventArgs e) {
FullscreenManager.SwitchBack();
}
private void Menu_Fullscreen_Mode_opening(object sender, EventArgs e) {
var mode = Settings.Default.GetFullscreenMode();
menuModeStandardToolStripMenuItem.Checked = (mode == FullscreenMode.Standard);
menuModeFullscreenToolStripMenuItem.Checked = (mode == FullscreenMode.Fullscreen);
menuModeAllScreensToolStripMenuItem.Checked = (mode == FullscreenMode.AllScreens);
}
private void Menu_Fullscreen_Mode_Standard_click(object sender, EventArgs e) {
Settings.Default.SetFullscreenMode(FullscreenMode.Standard);
FullscreenManager.SwitchFullscreen(FullscreenMode.Standard);
}
private void Menu_Fullscreen_Mode_Fullscreen_click(object sender, EventArgs e) {
Settings.Default.SetFullscreenMode(FullscreenMode.Fullscreen);
FullscreenManager.SwitchFullscreen(FullscreenMode.Fullscreen);
}
private void Menu_Fullscreen_Mode_AllScreens_click(object sender, EventArgs e) {
Settings.Default.SetFullscreenMode(FullscreenMode.AllScreens);
FullscreenManager.SwitchFullscreen(FullscreenMode.AllScreens);
}
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using OnTopReplica.Properties;
using WindowsFormsAero.TaskDialog;
using OnTopReplica.SidePanels;
namespace OnTopReplica {
partial class MainForm {
private void Menu_opening(object sender, CancelEventArgs e) {
//Cancel if currently in "fullscreen" mode or a side panel is open
if (FullscreenManager.IsFullscreen || IsSidePanelOpen) {
e.Cancel = true;
return;
}
bool showing = _thumbnailPanel.IsShowingThumbnail;
selectRegionToolStripMenuItem.Enabled = showing;
switchToWindowToolStripMenuItem.Enabled = showing;
resizeToolStripMenuItem.Enabled = showing;
chromeToolStripMenuItem.Checked = IsChromeVisible;
clickForwardingToolStripMenuItem.Checked = ClickForwardingEnabled;
chromeToolStripMenuItem.Enabled = showing;
clickThroughToolStripMenuItem.Enabled = showing;
clickForwardingToolStripMenuItem.Enabled = showing;
}
private void Menu_Switch_click(object sender, EventArgs e) {
if (CurrentThumbnailWindowHandle == null)
return;
Program.Platform.HideForm(this);
Native.WindowManagerMethods.SetForegroundWindow(CurrentThumbnailWindowHandle.Handle);
}
private void Menu_Advanced_opening(object sender, EventArgs e) {
restoreLastClonedWindowToolStripMenuItem.Checked = Settings.Default.RestoreLastWindow;
}
private void Menu_GroupSwitchMode_click(object sender, EventArgs e) {
SetSidePanel(new SidePanels.GroupSwitchPanel());
}
private void Menu_RestoreLastWindow_click(object sender, EventArgs e) {
Settings.Default.RestoreLastWindow = !Settings.Default.RestoreLastWindow;
}
private void Menu_ClickForwarding_click(object sender, EventArgs e) {
ClickForwardingEnabled = !ClickForwardingEnabled;
}
private void Menu_ClickThrough_click(object sender, EventArgs e) {
ClickThroughEnabled = true;
}
private void Menu_Opacity_opening(object sender, CancelEventArgs e) {
ToolStripMenuItem[] items = {
toolStripMenuItem1,
toolStripMenuItem2,
toolStripMenuItem3,
toolStripMenuItem4
};
foreach (ToolStripMenuItem i in items) {
if (((double)i.Tag) == this.Opacity)
i.Checked = true;
else
i.Checked = false;
}
}
private void Menu_Opacity_click(object sender, EventArgs e) {
ToolStripMenuItem tsi = (ToolStripMenuItem)sender;
if (this.Visible) {
//Target opacity is stored in the item's tag
this.Opacity = (double)tsi.Tag;
Program.Platform.OnFormStateChange(this);
}
}
private void Menu_Region_click(object sender, EventArgs e) {
SetSidePanel(new OnTopReplica.SidePanels.RegionPanel());
}
private void Menu_Resize_opening(object sender, CancelEventArgs e) {
if (!_thumbnailPanel.IsShowingThumbnail)
e.Cancel = true;
restorePositionAndSizeToolStripMenuItem.Checked = Settings.Default.RestoreSizeAndPosition;
}
private void Menu_Resize_Double(object sender, EventArgs e) {
FitToThumbnail(2.0);
}
private void Menu_Resize_FitToWindow(object sender, EventArgs e) {
FitToThumbnail(1.0);
}
private void Menu_Resize_Half(object sender, EventArgs e) {
FitToThumbnail(0.5);
}
private void Menu_Resize_Quarter(object sender, EventArgs e) {
FitToThumbnail(0.25);
}
private void Menu_Resize_Fullscreen(object sender, EventArgs e) {
FullscreenManager.SwitchFullscreen();
}
private void Menu_Resize_RecallPosition_click(object sender, EventArgs e) {
Settings.Default.RestoreSizeAndPosition = !Settings.Default.RestoreSizeAndPosition;
}
private void Menu_Position_Opening(object sender, EventArgs e) {
disabledToolStripMenuItem.Checked = (PositionLock == null);
topLeftToolStripMenuItem.Checked = (PositionLock == ScreenPosition.TopLeft);
topRightToolStripMenuItem.Checked = (PositionLock == ScreenPosition.TopRight);
centerToolStripMenuItem.Checked = (PositionLock == ScreenPosition.Center);
bottomLeftToolStripMenuItem.Checked = (PositionLock == ScreenPosition.BottomLeft);
bottomRightToolStripMenuItem.Checked = (PositionLock == ScreenPosition.BottomRight);
}
private void Menu_Position_Disable(object sender, EventArgs e) {
PositionLock = null;
}
private void Menu_Position_TopLeft(object sender, EventArgs e) {
PositionLock = ScreenPosition.TopLeft;
}
private void Menu_Position_TopRight(object sender, EventArgs e) {
PositionLock = ScreenPosition.TopRight;
}
private void Menu_Position_Center(object sender, EventArgs e) {
PositionLock = ScreenPosition.Center;
}
private void Menu_Position_BottomLeft(object sender, EventArgs e) {
PositionLock = ScreenPosition.BottomLeft;
}
private void Menu_Position_BottomRight(object sender, EventArgs e) {
PositionLock = ScreenPosition.BottomRight;
}
private void Menu_Reduce_click(object sender, EventArgs e) {
//Hide form in a platform specific way
Program.Platform.HideForm(this);
}
private void Menu_Chrome_click(object sender, EventArgs e) {
IsChromeVisible = !IsChromeVisible;
}
private void Menu_Settings_click(object sender, EventArgs e) {
this.SetSidePanel(new OptionsPanel());
}
private void Menu_About_click(object sender, EventArgs e) {
this.SetSidePanel(new AboutPanel());
}
private void Menu_Close_click(object sender, EventArgs e) {
this.Close();
}
private void Menu_Fullscreen_ExitFullscreen_click(object sender, EventArgs e) {
FullscreenManager.SwitchBack();
}
private void Menu_Fullscreen_Mode_opening(object sender, EventArgs e) {
var mode = Settings.Default.GetFullscreenMode();
menuModeStandardToolStripMenuItem.Checked = (mode == FullscreenMode.Standard);
menuModeFullscreenToolStripMenuItem.Checked = (mode == FullscreenMode.Fullscreen);
menuModeAllScreensToolStripMenuItem.Checked = (mode == FullscreenMode.AllScreens);
}
private void Menu_Fullscreen_Mode_Standard_click(object sender, EventArgs e) {
Settings.Default.SetFullscreenMode(FullscreenMode.Standard);
FullscreenManager.SwitchFullscreen(FullscreenMode.Standard);
}
private void Menu_Fullscreen_Mode_Fullscreen_click(object sender, EventArgs e) {
Settings.Default.SetFullscreenMode(FullscreenMode.Fullscreen);
FullscreenManager.SwitchFullscreen(FullscreenMode.Fullscreen);
}
private void Menu_Fullscreen_Mode_AllScreens_click(object sender, EventArgs e) {
Settings.Default.SetFullscreenMode(FullscreenMode.AllScreens);
FullscreenManager.SwitchFullscreen(FullscreenMode.AllScreens);
}
}
}

View file

@ -1,85 +1,85 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using OnTopReplica.MessagePumpProcessors;
using OnTopReplica.Native;
namespace OnTopReplica {
class MessagePumpManager : IDisposable {
Dictionary<Type, IMessagePumpProcessor> _processors = new Dictionary<Type, IMessagePumpProcessor>();
public MainForm Form { get; private set; }
private void Register(IMessagePumpProcessor processor, MainForm form) {
_processors[processor.GetType()] = processor;
processor.Initialize(form);
Log.Write("Registered message pump processor {0}", processor.GetType());
}
/// <summary>
/// Instantiates all message pump processors and registers them on the main form.
/// </summary>
/// <param name="form"></param>
public void Initialize(MainForm form) {
Form = form;
//Register window shell hook
if (!HookMethods.RegisterShellHookWindow(form.Handle)) {
Log.Write("Failed to register shell hook window");
}
else {
Log.Write("Shell hook window registered successfully");
}
//Register message pump processors
Register(new WindowKeeper(), form);
Register(new HotKeyManager(), form);
Register(new GroupSwitchManager(), form);
Register(new FlashCloner(), form);
}
/// <summary>
/// Run the registered message pump processors.
/// </summary>
/// <param name="msg">Message to process.</param>
/// <returns>True if the message has been handled internally.</returns>
public bool PumpMessage(ref Message msg) {
foreach (var processor in _processors.Values) {
if (processor.Process(ref msg))
return true;
}
return false;
}
/// <summary>
/// Get the instance of a registered message pump processor.
/// Throws if instance not found.
/// </summary>
public T Get<T>() {
return (T)_processors[typeof(T)];
}
#region IDisposable Members
public void Dispose() {
if (!HookMethods.DeregisterShellHookWindow(Form.Handle)) {
Log.Write("Failed to deregister shell hook window");
}
else {
Log.Write("Deregistered shell hook window successfully");
}
foreach (var processor in _processors.Values) {
processor.Dispose();
}
_processors.Clear();
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using OnTopReplica.MessagePumpProcessors;
using OnTopReplica.Native;
namespace OnTopReplica {
class MessagePumpManager : IDisposable {
Dictionary<Type, IMessagePumpProcessor> _processors = new Dictionary<Type, IMessagePumpProcessor>();
public MainForm Form { get; private set; }
private void Register(IMessagePumpProcessor processor, MainForm form) {
_processors[processor.GetType()] = processor;
processor.Initialize(form);
Log.Write("Registered message pump processor {0}", processor.GetType());
}
/// <summary>
/// Instantiates all message pump processors and registers them on the main form.
/// </summary>
/// <param name="form"></param>
public void Initialize(MainForm form) {
Form = form;
//Register window shell hook
if (!HookMethods.RegisterShellHookWindow(form.Handle)) {
Log.Write("Failed to register shell hook window");
}
else {
Log.Write("Shell hook window registered successfully");
}
//Register message pump processors
Register(new WindowKeeper(), form);
Register(new HotKeyManager(), form);
Register(new GroupSwitchManager(), form);
Register(new FlashCloner(), form);
}
/// <summary>
/// Run the registered message pump processors.
/// </summary>
/// <param name="msg">Message to process.</param>
/// <returns>True if the message has been handled internally.</returns>
public bool PumpMessage(ref Message msg) {
foreach (var processor in _processors.Values) {
if (processor.Process(ref msg))
return true;
}
return false;
}
/// <summary>
/// Get the instance of a registered message pump processor.
/// Throws if instance not found.
/// </summary>
public T Get<T>() {
return (T)_processors[typeof(T)];
}
#region IDisposable Members
public void Dispose() {
if (!HookMethods.DeregisterShellHookWindow(Form.Handle)) {
Log.Write("Failed to deregister shell hook window");
}
else {
Log.Write("Deregistered shell hook window successfully");
}
foreach (var processor in _processors.Values) {
processor.Dispose();
}
_processors.Clear();
}
#endregion
}
}

View file

@ -1,39 +1,39 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica.MessagePumpProcessors {
abstract class BaseMessagePumpProcessor : IMessagePumpProcessor {
protected MainForm Form { get; private set; }
#region IMessagePumpProcessor Members
public virtual void Initialize(MainForm form) {
Form = form;
}
public abstract bool Process(ref Message msg);
#endregion
protected abstract void Shutdown();
bool _isDisposed = false;
#region IDisposable Members
public void Dispose() {
if (_isDisposed)
return;
Shutdown();
_isDisposed = true;
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica.MessagePumpProcessors {
abstract class BaseMessagePumpProcessor : IMessagePumpProcessor {
protected MainForm Form { get; private set; }
#region IMessagePumpProcessor Members
public virtual void Initialize(MainForm form) {
Form = form;
}
public abstract bool Process(ref Message msg);
#endregion
protected abstract void Shutdown();
bool _isDisposed = false;
#region IDisposable Members
public void Dispose() {
if (_isDisposed)
return;
Shutdown();
_isDisposed = true;
}
#endregion
}
}

View file

@ -1,35 +1,35 @@
using OnTopReplica.Native;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnTopReplica.MessagePumpProcessors {
/// <summary>
/// Automatically clones windows that are flashing.
/// </summary>
class FlashCloner : BaseMessagePumpProcessor {
public override bool Process(ref System.Windows.Forms.Message msg) {
if (false &&
msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == HookMethods.HSHELL_FLASH) {
IntPtr flashHandle = msg.LParam;
Form.SetThumbnail(new WindowHandle(flashHandle), null);
}
}
return false;
}
protected override void Shutdown() {
}
}
}
using OnTopReplica.Native;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OnTopReplica.MessagePumpProcessors {
/// <summary>
/// Automatically clones windows that are flashing.
/// </summary>
class FlashCloner : BaseMessagePumpProcessor {
public override bool Process(ref System.Windows.Forms.Message msg) {
if (false &&
msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == HookMethods.HSHELL_FLASH) {
IntPtr flashHandle = msg.LParam;
Form.SetThumbnail(new WindowHandle(flashHandle), null);
}
}
return false;
}
protected override void Shutdown() {
}
}
}

View file

@ -1,133 +1,133 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica.MessagePumpProcessors {
class GroupSwitchManager : BaseMessagePumpProcessor {
bool _active = false;
List<WindowHandleWrapper> _lruHandles;
/// <summary>
/// Enables group switch mode.
/// </summary>
/// <param name="handles">List of window handles to track.</param>
public void EnableGroupMode(IList<WindowHandle> handles) {
if (handles == null || handles.Count == 0)
return;
//Okey dokey, will now track handles
TrackHandles(handles);
_active = true;
}
/// <summary>
/// Initializes the LRU sorted list of window handles.
/// </summary>
private void TrackHandles(IList<WindowHandle> handles) {
_lruHandles = new List<WindowHandleWrapper>(handles.Count);
var now = DateTime.Now;
foreach(var h in handles){
_lruHandles.Add(new WindowHandleWrapper {
WindowHandle = h,
LastTimeUsed = now
});
}
}
/// <summary>
/// Disables group switch mode.
/// </summary>
public void Disable() {
if (!_active)
return;
_lruHandles = null;
_active = false;
}
/// <summary>
/// Processes the message pump.
/// </summary>
public override bool Process(ref Message msg) {
if (_active && msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == HookMethods.HSHELL_WINDOWACTIVATED ||
hookCode == HookMethods.HSHELL_RUDEAPPACTIVATED) {
IntPtr activeHandle = msg.LParam;
HandleForegroundWindowChange(activeHandle);
}
}
return false;
}
private void HandleForegroundWindowChange(IntPtr activeWindow) {
//Seek window in tracked handles
WindowHandleWrapper activated = null;
foreach (var i in _lruHandles) {
if (i.WindowHandle.Handle == activeWindow)
activated = i;
}
if (activated == null) {
//New foreground window is not tracked
return;
}
//Update tracked handle
activated.LastTimeUsed = DateTime.Now;
_lruHandles.Sort(new LruDateTimeComparer());
//Get least recently used
var next = _lruHandles[0];
Log.Write("Switched to tracked window: switching to {0} (last use: {1})", next.WindowHandle.Title, next.LastTimeUsed);
Form.SetThumbnail(next.WindowHandle, null);
}
protected override void Shutdown() {
Disable();
}
/// <summary>
/// Gets whether the group switch manager ia active.
/// </summary>
public bool IsActive {
get {
return _active;
}
}
#region List sorting stuff
class WindowHandleWrapper {
public WindowHandle WindowHandle { get; set; }
public DateTime LastTimeUsed { get; set; }
}
class LruDateTimeComparer : IComparer<WindowHandleWrapper> {
#region IComparer<WindowHandleWrapper> Members
public int Compare(WindowHandleWrapper x, WindowHandleWrapper y) {
return x.LastTimeUsed.CompareTo(y.LastTimeUsed);
}
#endregion
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica.MessagePumpProcessors {
class GroupSwitchManager : BaseMessagePumpProcessor {
bool _active = false;
List<WindowHandleWrapper> _lruHandles;
/// <summary>
/// Enables group switch mode.
/// </summary>
/// <param name="handles">List of window handles to track.</param>
public void EnableGroupMode(IList<WindowHandle> handles) {
if (handles == null || handles.Count == 0)
return;
//Okey dokey, will now track handles
TrackHandles(handles);
_active = true;
}
/// <summary>
/// Initializes the LRU sorted list of window handles.
/// </summary>
private void TrackHandles(IList<WindowHandle> handles) {
_lruHandles = new List<WindowHandleWrapper>(handles.Count);
var now = DateTime.Now;
foreach(var h in handles){
_lruHandles.Add(new WindowHandleWrapper {
WindowHandle = h,
LastTimeUsed = now
});
}
}
/// <summary>
/// Disables group switch mode.
/// </summary>
public void Disable() {
if (!_active)
return;
_lruHandles = null;
_active = false;
}
/// <summary>
/// Processes the message pump.
/// </summary>
public override bool Process(ref Message msg) {
if (_active && msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == HookMethods.HSHELL_WINDOWACTIVATED ||
hookCode == HookMethods.HSHELL_RUDEAPPACTIVATED) {
IntPtr activeHandle = msg.LParam;
HandleForegroundWindowChange(activeHandle);
}
}
return false;
}
private void HandleForegroundWindowChange(IntPtr activeWindow) {
//Seek window in tracked handles
WindowHandleWrapper activated = null;
foreach (var i in _lruHandles) {
if (i.WindowHandle.Handle == activeWindow)
activated = i;
}
if (activated == null) {
//New foreground window is not tracked
return;
}
//Update tracked handle
activated.LastTimeUsed = DateTime.Now;
_lruHandles.Sort(new LruDateTimeComparer());
//Get least recently used
var next = _lruHandles[0];
Log.Write("Switched to tracked window: switching to {0} (last use: {1})", next.WindowHandle.Title, next.LastTimeUsed);
Form.SetThumbnail(next.WindowHandle, null);
}
protected override void Shutdown() {
Disable();
}
/// <summary>
/// Gets whether the group switch manager ia active.
/// </summary>
public bool IsActive {
get {
return _active;
}
}
#region List sorting stuff
class WindowHandleWrapper {
public WindowHandle WindowHandle { get; set; }
public DateTime LastTimeUsed { get; set; }
}
class LruDateTimeComparer : IComparer<WindowHandleWrapper> {
#region IComparer<WindowHandleWrapper> Members
public int Compare(WindowHandleWrapper x, WindowHandleWrapper y) {
return x.LastTimeUsed.CompareTo(y.LastTimeUsed);
}
#endregion
}
#endregion
}
}

View file

@ -1,167 +1,167 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OnTopReplica.Native;
using OnTopReplica.Properties;
namespace OnTopReplica.MessagePumpProcessors {
/// <summary>
/// HotKey registration helper.
/// </summary>
class HotKeyManager : BaseMessagePumpProcessor {
public HotKeyManager() {
Enabled = true;
}
delegate void HotKeyHandler();
/// <summary>
/// Wraps hot key handler registration data.
/// </summary>
private class HotKeyHandlerRegistration : IDisposable {
private HotKeyHandlerRegistration() {
}
private HotKeyHandlerRegistration(IntPtr hwnd, int key, HotKeyHandler handler) {
if (hwnd == IntPtr.Zero)
throw new ArgumentException();
if (handler == null)
throw new ArgumentNullException();
_hwnd = hwnd;
RegistrationKey = key;
Handler = handler;
}
static int _lastUsedKey = 0;
/// <summary>
/// Registers a new hotkey and returns a handle to the registration.
/// </summary>
/// <returns>Returns null on failure.</returns>
public static HotKeyHandlerRegistration Register(Form owner, int keyCode, int modifiers, HotKeyHandler handler) {
var key = ++_lastUsedKey;
if (!HotKeyMethods.RegisterHotKey(owner.Handle, key, modifiers, keyCode)) {
Log.Write("Failed to create hotkey on key {0} with modifiers {1}", keyCode, modifiers);
return null;
}
return new HotKeyHandlerRegistration(owner.Handle, key, handler);
}
IntPtr _hwnd;
public int RegistrationKey { get; private set; }
public HotKeyHandler Handler { get; private set; }
public void Dispose() {
if (!HotKeyMethods.UnregisterHotKey(_hwnd, RegistrationKey)) {
Log.Write("Failed to unregister hotkey #{0}", RegistrationKey);
}
}
}
Dictionary<int, HotKeyHandlerRegistration> _handlers = new Dictionary<int, HotKeyHandlerRegistration>();
public override void Initialize(MainForm form) {
base.Initialize(form);
RefreshHotkeys();
}
public override bool Process(ref Message msg) {
if (Enabled && msg.Msg == HotKeyMethods.WM_HOTKEY) {
int keyId = msg.WParam.ToInt32();
if (!_handlers.ContainsKey(keyId))
return false;
_handlers[keyId].Handler.Invoke();
}
return false;
}
public bool Enabled { get; set; }
/// <summary>
/// Refreshes registered hotkeys from Settings.
/// </summary>
/// <remarks>
/// Application settings contain hotkey registration strings that are used
/// automatically by this registration process.
/// </remarks>
public void RefreshHotkeys() {
ClearHandlers();
RegisterHandler(Settings.Default.HotKeyCloneCurrent, HotKeyCloneHandler);
RegisterHandler(Settings.Default.HotKeyShowHide, HotKeyShowHideHandler);
}
private void RegisterHandler(string spec, HotKeyHandler handler) {
if (string.IsNullOrEmpty(spec))
return; //this can happen and is allowed => simply don't register
if (handler == null)
throw new ArgumentNullException();
int modifiers = 0, keyCode = 0;
try {
HotKeyMethods.TranslateStringToKeyValues(spec, out modifiers, out keyCode);
}
catch (ArgumentException) {
//TODO: swallowed exception
return;
}
var reg = HotKeyHandlerRegistration.Register(Form, keyCode, modifiers, handler);
if(reg != null)
_handlers.Add(reg.RegistrationKey, reg);
}
private void ClearHandlers() {
foreach (var hotkey in _handlers) {
hotkey.Value.Dispose();
}
_handlers.Clear();
}
protected override void Shutdown() {
ClearHandlers();
}
#region Hotkey callbacks
/// <summary>
/// Handles "show/hide" hotkey. Ensures the form is in restored state and switches
/// between shown and hidden states.
/// </summary>
void HotKeyShowHideHandler() {
Form.FullscreenManager.SwitchBack();
if (!Program.Platform.IsHidden(Form)) {
Program.Platform.HideForm(Form);
}
else {
Form.EnsureMainFormVisible();
}
}
/// <summary>
/// Handles the "clone current" hotkey.
/// </summary>
void HotKeyCloneHandler() {
var handle = Win32Helper.GetCurrentForegroundWindow();
if (handle.Handle == Form.Handle)
return;
Form.SetThumbnail(handle, null);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OnTopReplica.Native;
using OnTopReplica.Properties;
namespace OnTopReplica.MessagePumpProcessors {
/// <summary>
/// HotKey registration helper.
/// </summary>
class HotKeyManager : BaseMessagePumpProcessor {
public HotKeyManager() {
Enabled = true;
}
delegate void HotKeyHandler();
/// <summary>
/// Wraps hot key handler registration data.
/// </summary>
private class HotKeyHandlerRegistration : IDisposable {
private HotKeyHandlerRegistration() {
}
private HotKeyHandlerRegistration(IntPtr hwnd, int key, HotKeyHandler handler) {
if (hwnd == IntPtr.Zero)
throw new ArgumentException();
if (handler == null)
throw new ArgumentNullException();
_hwnd = hwnd;
RegistrationKey = key;
Handler = handler;
}
static int _lastUsedKey = 0;
/// <summary>
/// Registers a new hotkey and returns a handle to the registration.
/// </summary>
/// <returns>Returns null on failure.</returns>
public static HotKeyHandlerRegistration Register(Form owner, int keyCode, int modifiers, HotKeyHandler handler) {
var key = ++_lastUsedKey;
if (!HotKeyMethods.RegisterHotKey(owner.Handle, key, modifiers, keyCode)) {
Log.Write("Failed to create hotkey on key {0} with modifiers {1}", keyCode, modifiers);
return null;
}
return new HotKeyHandlerRegistration(owner.Handle, key, handler);
}
IntPtr _hwnd;
public int RegistrationKey { get; private set; }
public HotKeyHandler Handler { get; private set; }
public void Dispose() {
if (!HotKeyMethods.UnregisterHotKey(_hwnd, RegistrationKey)) {
Log.Write("Failed to unregister hotkey #{0}", RegistrationKey);
}
}
}
Dictionary<int, HotKeyHandlerRegistration> _handlers = new Dictionary<int, HotKeyHandlerRegistration>();
public override void Initialize(MainForm form) {
base.Initialize(form);
RefreshHotkeys();
}
public override bool Process(ref Message msg) {
if (Enabled && msg.Msg == HotKeyMethods.WM_HOTKEY) {
int keyId = msg.WParam.ToInt32();
if (!_handlers.ContainsKey(keyId))
return false;
_handlers[keyId].Handler.Invoke();
}
return false;
}
public bool Enabled { get; set; }
/// <summary>
/// Refreshes registered hotkeys from Settings.
/// </summary>
/// <remarks>
/// Application settings contain hotkey registration strings that are used
/// automatically by this registration process.
/// </remarks>
public void RefreshHotkeys() {
ClearHandlers();
RegisterHandler(Settings.Default.HotKeyCloneCurrent, HotKeyCloneHandler);
RegisterHandler(Settings.Default.HotKeyShowHide, HotKeyShowHideHandler);
}
private void RegisterHandler(string spec, HotKeyHandler handler) {
if (string.IsNullOrEmpty(spec))
return; //this can happen and is allowed => simply don't register
if (handler == null)
throw new ArgumentNullException();
int modifiers = 0, keyCode = 0;
try {
HotKeyMethods.TranslateStringToKeyValues(spec, out modifiers, out keyCode);
}
catch (ArgumentException) {
//TODO: swallowed exception
return;
}
var reg = HotKeyHandlerRegistration.Register(Form, keyCode, modifiers, handler);
if(reg != null)
_handlers.Add(reg.RegistrationKey, reg);
}
private void ClearHandlers() {
foreach (var hotkey in _handlers) {
hotkey.Value.Dispose();
}
_handlers.Clear();
}
protected override void Shutdown() {
ClearHandlers();
}
#region Hotkey callbacks
/// <summary>
/// Handles "show/hide" hotkey. Ensures the form is in restored state and switches
/// between shown and hidden states.
/// </summary>
void HotKeyShowHideHandler() {
Form.FullscreenManager.SwitchBack();
if (!Program.Platform.IsHidden(Form)) {
Program.Platform.HideForm(Form);
}
else {
Form.EnsureMainFormVisible();
}
}
/// <summary>
/// Handles the "clone current" hotkey.
/// </summary>
void HotKeyCloneHandler() {
var handle = Win32Helper.GetCurrentForegroundWindow();
if (handle.Handle == Form.Handle)
return;
Form.SetThumbnail(handle, null);
}
#endregion
}
}

View file

@ -1,34 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica.MessagePumpProcessors {
#if DEBUG
/// <summary>
/// Basic shell message interceptor to use for debugging.
/// </summary>
class ShellInterceptProcessor : BaseMessagePumpProcessor {
public override bool Process(ref Message msg) {
if (msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
Log.Write("Hook msg #{0}: {1}", hookCode, msg.LParam);
}
return false;
}
protected override void Shutdown() {
}
}
#endif
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica.MessagePumpProcessors {
#if DEBUG
/// <summary>
/// Basic shell message interceptor to use for debugging.
/// </summary>
class ShellInterceptProcessor : BaseMessagePumpProcessor {
public override bool Process(ref Message msg) {
if (msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
Log.Write("Hook msg #{0}: {1}", hookCode, msg.LParam);
}
return false;
}
protected override void Shutdown() {
}
}
#endif
}

View file

@ -1,40 +1,40 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica.MessagePumpProcessors {
/// <summary>
/// Listens for shell events and closes the thumbnail if a cloned window is destroyed.
/// </summary>
class WindowKeeper : BaseMessagePumpProcessor {
public override bool Process(ref Message msg) {
if (Form.CurrentThumbnailWindowHandle != null &&
msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == HookMethods.HSHELL_WINDOWDESTROYED) {
//Check whether the destroyed window is the one we were cloning
IntPtr destroyedHandle = msg.LParam;
if (destroyedHandle == Form.CurrentThumbnailWindowHandle.Handle) {
//Disable group switch mode, since a window of the group has been destroyed
Form.MessagePumpManager.Get<GroupSwitchManager>().Disable();
//Disable cloning
Form.UnsetThumbnail();
}
}
}
return false;
}
protected override void Shutdown() {
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OnTopReplica.Native;
namespace OnTopReplica.MessagePumpProcessors {
/// <summary>
/// Listens for shell events and closes the thumbnail if a cloned window is destroyed.
/// </summary>
class WindowKeeper : BaseMessagePumpProcessor {
public override bool Process(ref Message msg) {
if (Form.CurrentThumbnailWindowHandle != null &&
msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == HookMethods.HSHELL_WINDOWDESTROYED) {
//Check whether the destroyed window is the one we were cloning
IntPtr destroyedHandle = msg.LParam;
if (destroyedHandle == Form.CurrentThumbnailWindowHandle.Handle) {
//Disable group switch mode, since a window of the group has been destroyed
Form.MessagePumpManager.Get<GroupSwitchManager>().Disable();
//Disable cloning
Form.UnsetThumbnail();
}
}
}
return false;
}
protected override void Shutdown() {
}
}
}

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