├── .editorconfig
├── .gitattributes
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.yaml
│ ├── config.yml
│ └── feature_request.yaml
└── workflows
│ └── build-and-package.yml
├── .gitignore
├── Images
└── Guides
│ ├── Snipaste_2019-10-12_22-46-37.png
│ ├── Snipaste_2019-10-12_22-49-11.png
│ ├── Snipaste_2019-10-13_12-42-40.png
│ ├── Snipaste_2019-10-13_15-51-33.png
│ ├── Snipaste_2019-10-13_16-01-09.png
│ ├── Snipaste_2019-10-19_15-28-58.png
│ ├── Snipaste_2019-10-20_23-36-44.png
│ └── Snipaste_2021-03-05_22-26-31.png
├── LICENSE
├── Privacy.md
├── README.md
├── TextReader.sln
├── TextReader
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── LargeTile.scale-100.png
│ ├── LargeTile.scale-125.png
│ ├── LargeTile.scale-150.png
│ ├── LargeTile.scale-200.png
│ ├── LargeTile.scale-400.png
│ ├── SmallTile.scale-100.png
│ ├── SmallTile.scale-125.png
│ ├── SmallTile.scale-150.png
│ ├── SmallTile.scale-200.png
│ ├── SmallTile.scale-400.png
│ ├── SplashScreen.scale-100.png
│ ├── SplashScreen.scale-125.png
│ ├── SplashScreen.scale-150.png
│ ├── SplashScreen.scale-200.png
│ ├── SplashScreen.scale-400.png
│ ├── Square150x150Logo.scale-100.png
│ ├── Square150x150Logo.scale-125.png
│ ├── Square150x150Logo.scale-150.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-400.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png
│ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png
│ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ ├── Square44x44Logo.altform-unplated_targetsize-256.png
│ ├── Square44x44Logo.altform-unplated_targetsize-32.png
│ ├── Square44x44Logo.altform-unplated_targetsize-48.png
│ ├── Square44x44Logo.scale-100.png
│ ├── Square44x44Logo.scale-125.png
│ ├── Square44x44Logo.scale-150.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.scale-400.png
│ ├── Square44x44Logo.targetsize-16.png
│ ├── Square44x44Logo.targetsize-24.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── Square44x44Logo.targetsize-256.png
│ ├── Square44x44Logo.targetsize-32.png
│ ├── Square44x44Logo.targetsize-48.png
│ ├── StoreLogo.scale-100.png
│ ├── StoreLogo.scale-125.png
│ ├── StoreLogo.scale-150.png
│ ├── StoreLogo.scale-200.png
│ ├── StoreLogo.scale-400.png
│ ├── Wide310x150Logo.scale-100.png
│ ├── Wide310x150Logo.scale-125.png
│ ├── Wide310x150Logo.scale-150.png
│ ├── Wide310x150Logo.scale-200.png
│ └── Wide310x150Logo.scale-400.png
├── Common
│ ├── CustomBrushResource.cs
│ ├── DefaultInterpolatedStringHandler.cs
│ ├── ExceptionHandling.cs
│ ├── SettingsPaneRegister.cs
│ └── ThreadSwitcher.cs
├── Controls
│ ├── AboutFlyout.xaml
│ ├── AboutFlyout.xaml.cs
│ ├── ApplicationLogo
│ │ ├── ApplicationLogo.cs
│ │ └── ApplicationLogo.xaml
│ ├── ImageCropper
│ │ ├── BitmapFileFormat.cs
│ │ ├── CropShape.cs
│ │ ├── ImageCropper.Animations.cs
│ │ ├── ImageCropper.Constants.cs
│ │ ├── ImageCropper.Events.cs
│ │ ├── ImageCropper.Helpers.cs
│ │ ├── ImageCropper.Logic.cs
│ │ ├── ImageCropper.Properties.cs
│ │ ├── ImageCropper.cs
│ │ ├── ImageCropper.xaml
│ │ ├── ImageCropperThumb.cs
│ │ ├── ImageCropperThumb.xaml
│ │ ├── ThumbPlacement.cs
│ │ └── ThumbPosition.cs
│ └── TwoPaneView
│ │ ├── DisplayRegionHelper.cs
│ │ ├── DisplayRegionHelperInfo.cs
│ │ ├── TwoPaneView.Enum.cs
│ │ ├── TwoPaneView.Properties.cs
│ │ ├── TwoPaneView.cs
│ │ └── TwoPaneView.xaml
├── Extensions
│ ├── DependencyObjectExtensions.cs
│ ├── FrameworkElement
│ │ └── FrameworkElementExtensions.Mouse.cs
│ ├── PointExtensions.cs
│ ├── Predicates
│ │ ├── Interfaces
│ │ │ └── IPredicate{T}.cs
│ │ ├── PredicateByAny{T}.cs
│ │ ├── PredicateByFunc{T,TState}.cs
│ │ ├── PredicateByFunc{T}.cs
│ │ ├── PredicateByName.cs
│ │ └── PredicateByType.cs
│ ├── RectExtensions.cs
│ └── SizeExtensions.cs
├── Helpers
│ ├── Converters
│ │ ├── BoolNegationConverter.cs
│ │ ├── BoolToObjectConverter.cs
│ │ ├── BoolToVisibilityConverter.cs
│ │ ├── ConverterTools.cs
│ │ ├── EmptyObjectToBoolConverter.cs
│ │ ├── EmptyObjectToObjectConverter.cs
│ │ ├── EmptyObjectToVisibilityConverter.cs
│ │ ├── EmptyStringToObjectConverter.cs
│ │ ├── IsEqualToBoolConverter.cs
│ │ ├── IsEqualToObjectConverter.cs
│ │ └── StringVisibilityConverter.cs
│ ├── DispatcherHelper.cs
│ ├── SettingsHelper.cs
│ ├── ThemeHelper.cs
│ ├── UIElementHelper.cs
│ ├── UIHelper.cs
│ └── WindowHelper.cs
├── Media
│ ├── BackdropBlurBrush.cs
│ ├── BackdropMicaBrush.cs
│ └── BackgroundSource.cs
├── Package.appxmanifest
├── Pages
│ ├── MainPage.xaml
│ └── MainPage.xaml.cs
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── Strings
│ ├── en-US
│ │ ├── AboutFlyout.resw
│ │ ├── MainPage.resw
│ │ ├── Resources.resw
│ │ └── SettingsPane.resw
│ └── zh-CN
│ │ ├── AboutFlyout.resw
│ │ ├── MainPage.resw
│ │ ├── Resources.resw
│ │ └── SettingsPane.resw
├── Styles
│ └── Brushes
│ │ ├── ThemeResources.21H2.xaml
│ │ ├── ThemeResources.RS1.xaml
│ │ ├── ThemeResources.RS2.xaml
│ │ └── ThemeResources.RS3.xaml
├── TextReader.csproj
├── Themes
│ ├── Color.xaml
│ └── Generic.xaml
├── ViewModels
│ └── MainViewModel.cs
└── favicon.ico
└── logo.png
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # CS0618: 类型或成员已过时
4 | dotnet_diagnostic.CS0618.severity = none
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: wherewhere
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: ['afdian.com/@wherewhere']
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yaml:
--------------------------------------------------------------------------------
1 | name: Bug report
2 | description: Create a report to help us improve
3 | title: "Bug title"
4 | labels: [bug]
5 | body:
6 | - type: textarea
7 | validations:
8 | required: true
9 | attributes:
10 | label: Describe the bug
11 | description: Please enter a short, clear description of the bug.
12 | - type: textarea
13 | validations:
14 | required: true
15 | attributes:
16 | label: Steps to reproduce the bug
17 | description: Please provide any required setup and steps to reproduce the behavior.
18 | placeholder: |
19 | 1. Go to '...'
20 | 2. Click on '....'
21 | - type: textarea
22 | attributes:
23 | label: Expected behavior
24 | description: Please provide a description of what you expected to happen
25 | - type: textarea
26 | attributes:
27 | label: Screenshots
28 | description: If applicable, add screenshots here to help explain your problem
29 | - type: dropdown
30 | validations:
31 | required: true
32 | attributes:
33 | label: App version
34 | description: Specify the version of Text Reader you're using.
35 | options:
36 | - "0.0.6"
37 | - "0.0.5"
38 | - "0.0.4"
39 | - "0.0.3"
40 | - "0.0.2"
41 | - "0.0.1"
42 | - "0.0.0"
43 | - type: dropdown
44 | validations:
45 | required: true
46 | attributes:
47 | label: Windows version
48 | description: Which Windows versions did you see the issue on?
49 | options:
50 | - "Insider Build (xxxxx)"
51 | - "Windows 11 version 22H2 (22621)"
52 | - "Windows 11 version 21H2 (22000)"
53 | - "Windows 10 version 21H2 (19044, November 2021 Update)"
54 | - "Windows 10 version 21H1 (19043, May 2021 Update)"
55 | - "Windows 10 version 20H2 (19042, October 2020 Update)"
56 | - "Windows 10 version 2004 (19041, May 2020 Update)"
57 | - "Windows 10 version 1909 (18363, November 2019 Update)"
58 | - "Windows 10 version 1903 (18362, May 2019 Update)"
59 | - "Windows 10 version 1809 (17763, October 2018 Update)"
60 | - "Windows 10 version 1803 (17134, April 2018 Update)"
61 | - "Windows 10 version 1709 (16299, Fall Creators Update)"
62 | - "Windows 10 version 1709 (15254, Fall Creators Update)"
63 | - "Windows 10 version 1703 (15063, Creators Update)"
64 | - "Windows 10 version 1607 (14393, Anniversary Update)"
65 | - "Windows 10 version 1511 (10586, Threshold 2)"
66 | - "Windows 10 version 1507 (10240, Threshold 1)"
67 | - type: dropdown
68 | validations:
69 | required: true
70 | attributes:
71 | label: Device
72 | description: Which Devices did you see the issue on?
73 | options:
74 | - "Desktop"
75 | - "Mobile"
76 | - "Xbox"
77 | - "Hololens"
78 | - "Hub"
79 | - "IOT"
80 | - type: textarea
81 | attributes:
82 | label: Additional context
83 | description: Enter any other applicable info here
84 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 | contact_links:
3 | - name: Question
4 | url: https://github.com/wherewhere/Text-Reader/discussions/new?category=q-a
5 | about: Ask a question
6 | - name: Discussion
7 | url: https://github.com/wherewhere/Text-Reader/discussions/new?category=general
8 | about: Start a discussion
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yaml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Suggest an idea for this project
3 | title: "Feature title"
4 | labels: [enhancement]
5 | body:
6 | - type: textarea
7 | validations:
8 | required: true
9 | attributes:
10 | label: Describe your feature request
11 | description: A clear and concise description of what the problem is.
12 | placeholder: I'm always frustrated when [...]
13 | - type: dropdown
14 | validations:
15 | required: true
16 | attributes:
17 | label: How important is this to you?
18 | options:
19 | - "Nice-to-have"
20 | - "Important"
21 | - "Critical"
22 | - type: textarea
23 | attributes:
24 | label: Describe the solution you'd like
25 | description: A clear and concise description of what you want to happen.
26 | - type: textarea
27 | attributes:
28 | label: Describe alternatives you've considered
29 | description: A clear and concise description of any alternative solutions or features you've considered.
30 | - type: textarea
31 | attributes:
32 | label: Additional context
33 | description: Add any other context or screenshots about the feature request here.
34 |
--------------------------------------------------------------------------------
/.github/workflows/build-and-package.yml:
--------------------------------------------------------------------------------
1 | name: build and package
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 | paths:
9 | - '.github/workflows/build-and-package.yml'
10 | - 'TextReader/**'
11 | workflow_dispatch:
12 |
13 | jobs:
14 | build-and-test:
15 |
16 | name: build-and-package
17 | runs-on: windows-latest
18 |
19 | env:
20 | Solution_Name: TextReader.sln
21 | Project_Directory: TextReader
22 | Signing_Certificate: TextReader_TemporaryKey.pfx
23 |
24 | steps:
25 | - name: Checkout
26 | uses: actions/checkout@v4
27 | with:
28 | fetch-depth: 0
29 |
30 | # Decode the base 64 encoded pfx and save the Signing_Certificate
31 | - name: Decode the pfx
32 | run: |
33 | $pfx_cert_byte = [System.Convert]::FromBase64String("$env:Certificate")
34 | $certificatePath = Join-Path -Path $env:Project_Directory -ChildPath $env:Signing_Certificate
35 | [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)
36 | env:
37 | Certificate: ${{ secrets.Base64_Encoded_Pfx }}
38 |
39 | # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
40 | - name: Setup MSBuild.exe
41 | uses: microsoft/setup-msbuild@v2
42 | with:
43 | msbuild-architecture: x64
44 |
45 | # Restore the application to populate the obj folder with RuntimeIdentifiers
46 | - name: Restore the application
47 | run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
48 | env:
49 | Configuration: Release
50 |
51 | # Create the app package by building and packaging the Windows Application Packaging project
52 | - name: Create the app package
53 | run: msbuild $env:Solution_Name `
54 | /p:LangVersion=latest `
55 | /p:AppxBundlePlatforms="$env:Appx_Bundle_Platforms" `
56 | /p:Configuration=$env:Configuration `
57 | /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode `
58 | /p:AppxBundle=$env:Appx_Bundle `
59 | /p:AppxPackageDir="$env:Appx_Package_Dir" `
60 | /p:AppxPackageSigningEnabled=true `
61 | /p:PackageCertificateThumbprint="$env:Thumbprint" `
62 | /p:PackageCertificateKeyFile=$env:Signing_Certificate `
63 | /p:PackageCertificatePassword="$env:Password"
64 | env:
65 | Appx_Bundle: Always
66 | Appx_Bundle_Platforms: x86|x64|ARM
67 | Appx_Package_Build_Mode: SideloadOnly
68 | Appx_Package_Dir: AppxPackages\
69 | Configuration: Release
70 | Thumbprint: 0CDF4A03E9BE9DD789894BB3C7AD3DEDECD9AB25
71 | Password: ${{ secrets.Password }}
72 |
73 | # Upload the MSIX package: https://github.com/marketplace/actions/upload-a-build-artifact
74 | - name: Upload build artifacts
75 | uses: actions/upload-artifact@v4
76 | with:
77 | name: MSIX Package
78 | path: TextReader/AppxPackages/**
79 |
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2019-10-12_22-46-37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2019-10-12_22-46-37.png
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2019-10-12_22-49-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2019-10-12_22-49-11.png
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2019-10-13_12-42-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2019-10-13_12-42-40.png
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2019-10-13_15-51-33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2019-10-13_15-51-33.png
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2019-10-13_16-01-09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2019-10-13_16-01-09.png
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2019-10-19_15-28-58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2019-10-19_15-28-58.png
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2019-10-20_23-36-44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2019-10-20_23-36-44.png
--------------------------------------------------------------------------------
/Images/Guides/Snipaste_2021-03-05_22-26-31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/Images/Guides/Snipaste_2021-03-05_22-26-31.png
--------------------------------------------------------------------------------
/Privacy.md:
--------------------------------------------------------------------------------
1 | # Text Reader 最终用户许可协议与隐私条款
2 |
3 | *版本 1.0 (2022.8.11)*
4 |
5 | 请您务必仔细阅读和理解 Text Reader 最终用户许可协议(以下简称「本协议」或「此协议」)与隐私条款。在开始之前,您需要决定是否同意本协议与隐私条款。除非您理解并接受此协议与隐私条款,否则此软件不得在您的任何终端上安装或使用。
6 |
7 | 您一旦同意此协议与隐私条款,就表明您同意接受本协议与隐私条款的所有约束。如您不同意此协议与隐私条款,您应当立即停止使用并卸载此软件。
8 |
9 | ## 您可以
10 |
11 | - 在一台个人所有的终端上安装、使用、运行本软件的一份副本。本软件仅供个人所有终端使用,不得用于法人或其他组织(包括但不限于政府机关、公司、企事业单位和其他组织,无论该组织是否为经济性组织,无论该组织的使用是否构成商业目的)所有终端。如若个人所有终端长期固定为法人或其他组织服务,则将被视为「法人或其他组织所有终端」。任何超出上述授权范围的使用均被视为非法复制的盗版行为,本软件作者保留权利要求相关责任人承担相应的法律责任,包括但不限于民事责任、行政责任、刑事责任。
12 | - 为了防止副本损坏而制作备份复制品。这些备份复制品不得通过任何方式提供给他人使用,且在您丧失该合法副本的所有权时,有义务将备份复制品销毁。
13 | - 为了把本软件用于实际的终端环境或者改进其功能、性能而进行必要的修改。但是,除本协议另有约定外,未经本软件作者书面同意,不得向第三方以任何形式提供修改后的软件。
14 | - 对本软件进行以学习目的的反向工程、反向编译、反汇编或其他获得本软件源代码、运行逻辑的行为。(显然,在 Github 获取本软件的全部源代码是一种更为明智的行为)
15 |
16 | ## 您保证
17 |
18 | - 不得出售、贩发出租或以其他方式传播本软件以获利。
19 | - 不得以任何方式商用本软件,包括但不限于使用本软件发送广告或出售、二次贩卖、发行、出租本软件。
20 | - 在本软件的所有副本上包含所有的版权标识与许可证。
21 |
22 | ## 权利的保留
23 |
24 | - 未明示授予的一切权利均为本软件作者所有。
25 | - 最终解释权归本软件作者所有。
26 |
27 | ## 本软件的著作权
28 |
29 | - 您不得去掉本软件上的任何版权标识,并应在其所有复制品上依照现有的表述方式标注其版权归属本软件作者。
30 | - 本软件(包括但不限于本软件中所含的任何代码、图像、动画、视频、音乐、文字和附加程序)、随附的印刷材料、宣传材料及任何副本的著作权,均由本软件作者拥有。
31 | - 您不可以从本软件中去掉版权声明,并保证为本软件的复制品(全部或部分)复制版权声明。
32 |
33 | ## 免责声明
34 |
35 | - 用户在下载或使用本软件时均被视为已经仔细阅读本协议并完全同意。凡以任何方式激活本软件,或以任何方式(包括但不限于直接、间接)使用本软件,均被视为自愿接受相关声明和用户许可的约束。
36 | - 本软件仅供用户做测试或娱乐使用,不得用于非法用途;一切自行用于其它用途的用户,不软件概不承担任何责任。
37 | - 用户使用本软件的过程中,如果侵犯了第三方知识产权或其他权利,责任由使用人本人承担,本软件对此不承担任何责任。
38 | - 用户明确并同意其使用本软件所存在的风险将完全由其本人承担,因其实用软件而产生的一切后果也由其本人承担,本软件对此不承担任何责任。
39 | - 除本软件注明的条款外,其它因不当使用本软件而导致的任何意外、疏忽、合约损坏、诽谤、版权或其他知识产权侵犯及其所造成的任何损失,本软件概不负责,亦不承担任何责任。
40 | - 对于因不可抗力、黑客攻击、通讯线路中断等本软件不能控制的原因或其他缺陷,导致用户不能正常使用本软件的,本软件不承担任何责任。
41 | - 本软件未涉及的问题请参见国家有关法律法规,当本声明与国家有关法律法规冲突时,以国家法律为准。
42 |
43 | ## 隐私保护政策与条款
44 |
45 | 首先感谢您使用本应用!本应用非常重视用户的隐私,将保护用户隐私视为基本原则并将其贯彻到底。
46 |
47 | ### 本应用会收集哪些信息?
48 |
49 | #### 我们的合作伙伴可能会收集你的一些数据
50 |
51 | 本应用使用了 Microsoft AppCenter 来统计或收集月活量、崩溃数据和用户信息等指标。具体会收集哪些信息请参阅:[《Microsoft Privacy Statement》](https://privacy.microsoft.com/en-us/privacystatement)。
52 |
53 | ### 本应用如何使用您的信息?
54 |
55 | - 向您提供服务。在我们提供服务时,用于身份验证、客户服务、安全防范、诈骗监测、存档和备份用途,确保我们向您提供的产品和服务的安全性。
56 | - 帮我们设计新服务,改善我们的现有服务。
57 | - 使我们更加了解您如何使用我们的服务,从而针对性地回应您的个性化需求。例如个性化的帮助服务和提示,或对您和其他用户做出其他方面的回应。
58 | - 软件认证和管理软件升级。
59 | - 让您参与有关我们产品和服务的调查。
60 |
61 | ### 本应用如何分享您的信息?
62 |
63 | 除以下情形外,未经您同意,我们不会与任何第三方分享您的个人信息:
64 |
65 | - 您授权或同意本应用披露的。
66 | - 遵守适用的法律法规。
67 | - 遵守法院命令或其他法律程序的规定。
68 | - 遵守适用的法律法规以维护社会公共利益。
69 | - 本软件各服务条款条款、许可协议及声明中的相关规定。
70 |
71 | ### 本应用任何保护您的隐私?
72 |
73 | 这款应用采用 TLS (传输层安全性协议) 技术来尽可能保证您的数据在与服务器通信的过程中不被第三方窃听或攻击。
74 |
75 | # **特别提醒**
76 | # **本软件始终是免费软件且授权非商业使用,如果你发现有人商用本软件或以此牟取利润,请拒绝并不遗余力地在一切平台举报投诉他!**
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Text Reader
4 | 一个基于 WinRT OCR 的文本提取器
5 |
6 | [](https://github.com/wherewhere/Text-Reader/actions/workflows/build-and-package.yml "Build Status")
7 |
8 | [](https://github.com/wherewhere/Text-Reader/blob/master/LICENSE "LICENSE")
9 | [](https://github.com/wherewhere/Text-Reader/issues "Issues")
10 | [](https://github.com/wherewhere/Text-Reader/stargazers "Stargazers")
11 |
12 | [](https://www.microsoft.com/store/apps/9P8NKQW6NCNC "Microsoft Store")
13 | [](https://github.com/wherewhere/Text-Reader/releases/latest "GitHub All Releases")
14 |
15 | ## 目录
16 | - [Text Reader](#text-reader)
17 | - [目录](#目录)
18 | - [支持的语言](#支持的语言)
19 | - [如何安装应用](#如何安装应用)
20 | - [最低需求](#最低需求)
21 | - [使用应用安装脚本安装应用](#使用应用安装脚本安装应用)
22 | - [使用应用安装程序安装应用](#使用应用安装程序安装应用)
23 | - [更新应用](#更新应用)
24 | - [使用到的模块](#使用到的模块)
25 |
26 | ## 支持的语言
27 | - 中文
28 | - English
29 |
30 | ## 如何安装应用
31 | ### 最低需求
32 | - Windows 10 Build 10240及以上
33 | - 设备需支持ARM/x86/x64
34 | - 至少20MB的空余储存空间(用于储存安装包与安装应用)
35 |
36 | ### 使用应用安装脚本安装应用
37 | - 下载并解压最新的[安装包`(UWP_x.x.x.0_Debug_Test.rar)`](https://github.com/wherewhere/Text-Reader/releases/latest)
38 | - 如果没有应用安装脚本,下载[`Install.ps1`](Install.ps1)到目标目录
39 | 
40 | - 右击`Install.ps1`,选择“使用PowerShell运行”
41 | - 应用安装脚本将会引导您完成此过程的剩余部分
42 |
43 | ### 使用应用安装程序安装应用
44 | - 下载并解压最新的[安装包`(UWP_x.x.x.0_Debug_Test.rar)`](https://github.com/wherewhere/Text-Reader/releases/latest)
45 | - [开启旁加载模式](https://www.windowscentral.com/how-enable-windows-10-sideload-apps-outside-store)
46 | - 如果您想开发UWP应用,您可以开启[开发人员模式](https://docs.microsoft.com/zh-cn/windows/uwp/get-started/enable-your-device-for-development),**对于大多数不需要做UWP开发的用户来说,开发人员模式是没有必要的**
47 | - 安装`Dependencies`文件夹下的适用于您的设备的所有依赖包
48 | 
49 | - 安装`*.cer`证书到`本地计算机`→`受信任的根证书颁发机构`
50 | - 这项操作需要用到管理员权限,如果您安装证书时没有用到该权限,则可能是因为您将证书安装到了错误的位置或者您使用的是超级管理员账户
51 | 
52 | 
53 | 
54 | - 双击`*.appxbundle`,单击安装,坐和放宽
55 | 
56 |
57 | ### 更新应用
58 | - 下载并解压最新的[安装包`(UWP_x.x.x.0_x86_x64_arm_Debug.appxbundle)`](https://github.com/wherewhere/Text-Reader/releases/latest)
59 | - 双击`*.appxbundle`,单击安装,坐和放宽
60 | 
61 |
62 | ## 使用到的模块
63 | - [Mica For UWP](https://github.com/wherewhere/Mica-For-UWP "Mica For UWP")
64 | - [Windows Community Toolkit](https://github.com/CommunityToolkit/WindowsCommunityToolkit "Windows Community Toolkit")
65 |
--------------------------------------------------------------------------------
/TextReader.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32728.150
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TextReader", "TextReader\TextReader.csproj", "{96371F70-FC14-4C9D-B639-AA123C9031C6}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|ARM64 = Debug|ARM64
12 | Debug|x64 = Debug|x64
13 | Debug|x86 = Debug|x86
14 | Release|ARM = Release|ARM
15 | Release|ARM64 = Release|ARM64
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|ARM.ActiveCfg = Debug|ARM
21 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|ARM.Build.0 = Debug|ARM
22 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|ARM.Deploy.0 = Debug|ARM
23 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|ARM64.ActiveCfg = Debug|ARM64
24 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|ARM64.Build.0 = Debug|ARM64
25 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|ARM64.Deploy.0 = Debug|ARM64
26 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|x64.ActiveCfg = Debug|x64
27 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|x64.Build.0 = Debug|x64
28 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|x64.Deploy.0 = Debug|x64
29 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|x86.ActiveCfg = Debug|x86
30 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|x86.Build.0 = Debug|x86
31 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Debug|x86.Deploy.0 = Debug|x86
32 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|ARM.ActiveCfg = Release|ARM
33 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|ARM.Build.0 = Release|ARM
34 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|ARM.Deploy.0 = Release|ARM
35 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|ARM64.ActiveCfg = Release|ARM64
36 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|ARM64.Build.0 = Release|ARM64
37 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|ARM64.Deploy.0 = Release|ARM64
38 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|x64.ActiveCfg = Release|x64
39 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|x64.Build.0 = Release|x64
40 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|x64.Deploy.0 = Release|x64
41 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|x86.ActiveCfg = Release|x86
42 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|x86.Build.0 = Release|x86
43 | {96371F70-FC14-4C9D-B639-AA123C9031C6}.Release|x86.Deploy.0 = Release|x86
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(ExtensibilityGlobals) = postSolution
49 | SolutionGuid = {A5F54529-1F0F-4F60-A7A7-8A6A3120F9F8}
50 | EndGlobalSection
51 | EndGlobal
52 |
--------------------------------------------------------------------------------
/TextReader/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Segoe Fluent Icons,Segoe MDL2 Assets,Segoe UI Symbol
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/TextReader/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TextReader.Common;
3 | using TextReader.Extensions;
4 | using TextReader.Helpers;
5 | using TextReader.Pages;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.ApplicationModel.Core;
9 | using Windows.Foundation.Metadata;
10 | using Windows.System.Profile;
11 | using Windows.UI.Xaml;
12 | using Windows.UI.Xaml.Controls;
13 | using Windows.UI.Xaml.Navigation;
14 |
15 | namespace TextReader
16 | {
17 | ///
18 | /// 提供特定于应用程序的行为,以补充默认的应用程序类。
19 | ///
20 | public sealed partial class App : Application
21 | {
22 | ///
23 | /// 初始化单一实例应用程序对象。这是执行的创作代码的第一行,
24 | /// 已执行,逻辑上等同于 main() 或 WinMain()。
25 | ///
26 | public App()
27 | {
28 | InitializeComponent();
29 | Suspending += OnSuspending;
30 | UnhandledException += Application_UnhandledException;
31 | #if NETCORE463
32 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
33 | #endif
34 | if (ApiInformation.IsEnumNamedValuePresent("Windows.UI.Xaml.FocusVisualKind", "Reveal") && AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Xbox")
35 | {
36 | FocusVisualKind = FocusVisualKind.Reveal;
37 | }
38 | }
39 |
40 | ///
41 | /// 在应用程序由最终用户正常启动时进行调用。
42 | /// 将在启动应用程序以打开特定文件等情况下使用。
43 | ///
44 | /// 有关启动请求和过程的详细信息。
45 | protected override void OnLaunched(LaunchActivatedEventArgs e)
46 | {
47 | EnsureWindow(e);
48 | }
49 |
50 | #region OnActivated
51 |
52 | protected override void OnActivated(IActivatedEventArgs e)
53 | {
54 | EnsureWindow(e);
55 | base.OnActivated(e);
56 | }
57 |
58 | protected override void OnCachedFileUpdaterActivated(CachedFileUpdaterActivatedEventArgs e)
59 | {
60 | EnsureWindow(e);
61 | base.OnCachedFileUpdaterActivated(e);
62 | }
63 |
64 | protected override void OnFileActivated(FileActivatedEventArgs e)
65 | {
66 | EnsureWindow(e);
67 | base.OnFileActivated(e);
68 | }
69 |
70 | protected override void OnFileOpenPickerActivated(FileOpenPickerActivatedEventArgs e)
71 | {
72 | EnsureWindow(e);
73 | base.OnFileOpenPickerActivated(e);
74 | }
75 |
76 | protected override void OnFileSavePickerActivated(FileSavePickerActivatedEventArgs e)
77 | {
78 | EnsureWindow(e);
79 | base.OnFileSavePickerActivated(e);
80 | }
81 |
82 | protected override void OnSearchActivated(SearchActivatedEventArgs e)
83 | {
84 | EnsureWindow(e);
85 | base.OnSearchActivated(e);
86 | }
87 |
88 | protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs e)
89 | {
90 | EnsureWindow(e);
91 | base.OnShareTargetActivated(e);
92 | }
93 |
94 | #endregion
95 |
96 | private void EnsureWindow(IActivatedEventArgs e)
97 | {
98 | if (!isLoaded)
99 | {
100 | RegisterExceptionHandlingSynchronizationContext();
101 | isLoaded = true;
102 | }
103 |
104 | Window window = Window.Current;
105 |
106 | // 不要在窗口已包含内容时重复应用程序初始化,
107 | // 只需确保窗口处于活动状态
108 | if (!(window.Content is Frame rootFrame))
109 | {
110 | CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
111 |
112 | // 创建要充当导航上下文的框架,并导航到第一页
113 | rootFrame = new Frame();
114 |
115 | rootFrame.NavigationFailed += OnNavigationFailed;
116 |
117 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
118 | {
119 | //TODO: 从之前挂起的应用程序加载状态
120 | }
121 |
122 | // 将框架放在当前窗口中
123 | window.Content = rootFrame;
124 |
125 | WindowHelper.TrackWindow(window);
126 | ThemeHelper.Initialize(window);
127 | }
128 |
129 | if (e is LaunchActivatedEventArgs args)
130 | {
131 | if (!args.PrelaunchActivated)
132 | {
133 | if (ApiInformation.IsMethodPresent("Windows.ApplicationModel.Core.CoreApplication", "EnablePrelaunch"))
134 | {
135 | CoreApplication.EnablePrelaunch(true);
136 | }
137 | }
138 | else { return; }
139 | }
140 |
141 | if (rootFrame.Content == null)
142 | {
143 | // 当导航堆栈尚未还原时,导航到第一页,
144 | // 并通过将所需信息作为导航参数传入来配置
145 | // 参数
146 | rootFrame.Navigate(typeof(MainPage), e);
147 | }
148 | else
149 | {
150 | rootFrame.FindDescendant()?.OpenActivatedEventArgs(e);
151 | }
152 |
153 | // 确保当前窗口处于活动状态
154 | window.Activate();
155 | }
156 |
157 | ///
158 | /// 导航到特定页失败时调用
159 | ///
160 | ///导航失败的框架
161 | ///有关导航失败的详细信息
162 | private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
163 | {
164 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
165 | }
166 |
167 | ///
168 | /// 在将要挂起应用程序执行时调用。 在不知道应用程序
169 | /// 无需知道应用程序会被终止还是会恢复,
170 | /// 并让内存内容保持不变。
171 | ///
172 | /// 挂起的请求的源。
173 | /// 有关挂起请求的详细信息。
174 | private void OnSuspending(object sender, SuspendingEventArgs e)
175 | {
176 | SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral();
177 | //TODO: 保存应用程序状态并停止任何后台活动
178 | deferral.Complete();
179 | }
180 |
181 | private void Application_UnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
182 | {
183 | SettingsHelper.LogManager.GetLogger("Unhandled Exception - Application").Error(e.Exception.ExceptionToMessage(), e.Exception);
184 | e.Handled = true;
185 | }
186 |
187 | #if NETCORE463
188 | private static void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
189 | {
190 | if (e.ExceptionObject is Exception Exception)
191 | {
192 | SettingsHelper.LogManager.GetLogger("Unhandled Exception - CurrentDomain").Error(Exception.ExceptionToMessage(), Exception);
193 | }
194 | }
195 | #endif
196 |
197 | ///
198 | /// Should be called from OnActivated and OnLaunched.
199 | ///
200 | private void RegisterExceptionHandlingSynchronizationContext()
201 | {
202 | ExceptionHandlingSynchronizationContext
203 | .Register()
204 | .UnhandledException += SynchronizationContext_UnhandledException;
205 | }
206 |
207 | private void SynchronizationContext_UnhandledException(object sender, Common.UnhandledExceptionEventArgs e)
208 | {
209 | SettingsHelper.LogManager.GetLogger("Unhandled Exception - SynchronizationContext").Error(e.Exception.ExceptionToMessage(), e.Exception);
210 | e.Handled = true;
211 | }
212 |
213 | private bool isLoaded;
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/TextReader/Assets/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/TextReader/Assets/LargeTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/LargeTile.scale-125.png
--------------------------------------------------------------------------------
/TextReader/Assets/LargeTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/LargeTile.scale-150.png
--------------------------------------------------------------------------------
/TextReader/Assets/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/TextReader/Assets/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/TextReader/Assets/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/TextReader/Assets/SmallTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SmallTile.scale-125.png
--------------------------------------------------------------------------------
/TextReader/Assets/SmallTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SmallTile.scale-150.png
--------------------------------------------------------------------------------
/TextReader/Assets/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/TextReader/Assets/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/TextReader/Assets/SplashScreen.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SplashScreen.scale-100.png
--------------------------------------------------------------------------------
/TextReader/Assets/SplashScreen.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SplashScreen.scale-125.png
--------------------------------------------------------------------------------
/TextReader/Assets/SplashScreen.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SplashScreen.scale-150.png
--------------------------------------------------------------------------------
/TextReader/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/TextReader/Assets/SplashScreen.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/SplashScreen.scale-400.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square150x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square150x150Logo.scale-125.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square150x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square150x150Logo.scale-150.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-32.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.scale-100.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.scale-125.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.scale-150.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.scale-400.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.targetsize-16.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.targetsize-24.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.targetsize-256.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.targetsize-32.png
--------------------------------------------------------------------------------
/TextReader/Assets/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/TextReader/Assets/StoreLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/StoreLogo.scale-100.png
--------------------------------------------------------------------------------
/TextReader/Assets/StoreLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/StoreLogo.scale-125.png
--------------------------------------------------------------------------------
/TextReader/Assets/StoreLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/StoreLogo.scale-150.png
--------------------------------------------------------------------------------
/TextReader/Assets/StoreLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/StoreLogo.scale-200.png
--------------------------------------------------------------------------------
/TextReader/Assets/StoreLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/StoreLogo.scale-400.png
--------------------------------------------------------------------------------
/TextReader/Assets/Wide310x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Wide310x150Logo.scale-100.png
--------------------------------------------------------------------------------
/TextReader/Assets/Wide310x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Wide310x150Logo.scale-125.png
--------------------------------------------------------------------------------
/TextReader/Assets/Wide310x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Wide310x150Logo.scale-150.png
--------------------------------------------------------------------------------
/TextReader/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/TextReader/Assets/Wide310x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wherewhere/Text-Reader/de63462d32d9858d31250ec01cc9158dac1bf51c/TextReader/Assets/Wide310x150Logo.scale-400.png
--------------------------------------------------------------------------------
/TextReader/Common/CustomBrushResource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Windows.Foundation.Metadata;
3 | using Windows.UI.Xaml;
4 |
5 | namespace TextReader.Common
6 | {
7 | public class CustomBrushResource : ResourceDictionary
8 | {
9 | public CustomBrushResource() => AddResource();
10 |
11 | private void AddResource()
12 | {
13 | if (ApiInformation.IsMethodPresent("Windows.UI.Composition.Compositor", "TryCreateBlurredWallpaperBackdropBrush"))
14 | {
15 | AddResourceDictionary("ms-appx:///Styles/Brushes/ThemeResources.21H2.xaml");
16 | }
17 | else if (ApiInformation.IsTypePresent("Windows.UI.Xaml.Media.AcrylicBrush"))
18 | {
19 | AddResourceDictionary("ms-appx:///Styles/Brushes/ThemeResources.RS3.xaml");
20 | }
21 | else if (ApiInformation.IsTypePresent("Windows.UI.Xaml.Media.XamlCompositionBrushBase"))
22 | {
23 | AddResourceDictionary("ms-appx:///Styles/Brushes/ThemeResources.RS2.xaml");
24 | }
25 | else
26 | {
27 | AddResourceDictionary("ms-appx:///Styles/Brushes/ThemeResources.RS1.xaml");
28 | }
29 |
30 | void AddResourceDictionary(string Source)
31 | {
32 | MergedDictionaries.Add(new ResourceDictionary { Source = new Uri(Source) });
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/TextReader/Common/SettingsPaneRegister.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TextReader.Helpers;
3 | using Windows.ApplicationModel.Resources;
4 | using Windows.Foundation.Metadata;
5 | using Windows.Storage;
6 | using Windows.System;
7 | using Windows.UI.ApplicationSettings;
8 | using Windows.UI.Core;
9 | using Windows.UI.Xaml;
10 |
11 | namespace TextReader.Common
12 | {
13 | public static class SettingsPaneRegister
14 | {
15 | public static bool IsSettingsPaneSupported { get; } = ApiInformation.IsTypePresent("Windows.UI.ApplicationSettings.SettingsPane");
16 |
17 | public static void Register(Window window)
18 | {
19 | try
20 | {
21 | if (IsSettingsPaneSupported)
22 | {
23 | SettingsPane searchPane = SettingsPane.GetForCurrentView();
24 | searchPane.CommandsRequested -= OnCommandsRequested;
25 | searchPane.CommandsRequested += OnCommandsRequested;
26 | window.Dispatcher.AcceleratorKeyActivated -= Dispatcher_AcceleratorKeyActivated;
27 | window.Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated;
28 | }
29 | }
30 | catch (Exception ex)
31 | {
32 | SettingsHelper.LogManager.GetLogger(nameof(SettingsPaneRegister)).Error(ex.ExceptionToMessage(), ex);
33 | }
34 | }
35 |
36 | public static void Unregister(Window window)
37 | {
38 | try
39 | {
40 | if (IsSettingsPaneSupported)
41 | {
42 | SettingsPane.GetForCurrentView().CommandsRequested -= OnCommandsRequested;
43 | window.Dispatcher.AcceleratorKeyActivated -= Dispatcher_AcceleratorKeyActivated;
44 | }
45 | }
46 | catch (Exception ex)
47 | {
48 | SettingsHelper.LogManager.GetLogger(nameof(SettingsPaneRegister)).Error(ex.ExceptionToMessage(), ex);
49 | }
50 | }
51 |
52 | private static void OnCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
53 | {
54 | ResourceLoader loader = ResourceLoader.GetForViewIndependentUse("SettingsPane");
55 | args.Request.ApplicationCommands.Add(
56 | new SettingsCommand(
57 | "Feedback",
58 | loader.GetString("Feedback"),
59 | handler => _ = Launcher.LaunchUriAsync(new Uri("https://github.com/wherewhere/Text-Reader/issues"))));
60 | args.Request.ApplicationCommands.Add(
61 | new SettingsCommand(
62 | "LogFolder",
63 | loader.GetString("LogFolder"),
64 | async handler => _ = Launcher.LaunchFolderAsync(await ApplicationData.Current.LocalFolder.CreateFolderAsync("MetroLogs", CreationCollisionOption.OpenIfExists))));
65 | args.Request.ApplicationCommands.Add(
66 | new SettingsCommand(
67 | "Repository",
68 | loader.GetString("Repository"),
69 | handler => _ = Launcher.LaunchUriAsync(new Uri("https://github.com/wherewhere/Text-Reader"))));
70 | args.Request.ApplicationCommands.Add(
71 | new SettingsCommand(
72 | "StoreReview",
73 | loader.GetString("StoreReview"),
74 | handler => _ = Launcher.LaunchUriAsync(new Uri("ms-windows-store://review/?ProductId=9P8NKQW6NCNC"))));
75 | }
76 |
77 | private static void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
78 | {
79 | if (args.EventType.HasFlag(CoreAcceleratorKeyEventType.KeyDown) || args.EventType.HasFlag(CoreAcceleratorKeyEventType.SystemKeyUp))
80 | {
81 | CoreWindow window = CoreWindow.GetForCurrentThread();
82 | CoreVirtualKeyStates ctrl = window.GetKeyState(VirtualKey.Control);
83 | if (ctrl.HasFlag(CoreVirtualKeyStates.Down))
84 | {
85 | CoreVirtualKeyStates shift = window.GetKeyState(VirtualKey.Shift);
86 | if (shift.HasFlag(CoreVirtualKeyStates.Down))
87 | {
88 | switch (args.VirtualKey)
89 | {
90 | case VirtualKey.X when IsSettingsPaneSupported:
91 | SettingsPane.Show();
92 | args.Handled = true;
93 | break;
94 | }
95 | }
96 | }
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/TextReader/Common/ThreadSwitcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 | using System.Threading;
5 | using Windows.System.Threading;
6 | using Windows.UI.Core;
7 | using ThreadPool = Windows.System.Threading.ThreadPool;
8 |
9 | namespace TextReader.Common
10 | {
11 | ///
12 | /// The interface of helper type for switch thread.
13 | ///
14 | public interface IThreadSwitcher : INotifyCompletion
15 | {
16 | ///
17 | /// Gets a value that indicates whether the asynchronous operation has completed.
18 | ///
19 | bool IsCompleted { get; }
20 |
21 | ///
22 | /// Ends the await on the completed task.
23 | ///
24 | void GetResult();
25 |
26 | ///
27 | /// Gets an awaiter used to await this .
28 | ///
29 | /// An awaiter instance.
30 | IThreadSwitcher GetAwaiter();
31 | }
32 |
33 | ///
34 | /// The interface of helper type for switch thread.
35 | ///
36 | /// The type of the result of .
37 | public interface IThreadSwitcher : IThreadSwitcher
38 | {
39 | ///
40 | /// Gets an awaiter used to await .
41 | ///
42 | /// A awaiter instance.
43 | new T GetAwaiter();
44 | }
45 |
46 | ///
47 | /// A helper type for switch thread by . This type is not intended to be used directly from your code.
48 | ///
49 | [EditorBrowsable(EditorBrowsableState.Never)]
50 | public readonly struct DispatcherThreadSwitcher : IThreadSwitcher
51 | {
52 | ///
53 | /// A whose foreground thread to switch execution to.
54 | ///
55 | private readonly CoreDispatcher dispatcher;
56 |
57 | ///
58 | /// Specifies the priority for event dispatch.
59 | ///
60 | private readonly CoreDispatcherPriority priority;
61 |
62 | ///
63 | /// Initializes a new instance of the struct.
64 | ///
65 | /// A whose foreground thread to switch execution to.
66 | /// Specifies the priority for event dispatch.
67 | public DispatcherThreadSwitcher(CoreDispatcher dispatcher, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
68 | {
69 | this.dispatcher = dispatcher;
70 | this.priority = priority;
71 | }
72 |
73 | ///
74 | public bool IsCompleted => dispatcher?.HasThreadAccess != false;
75 |
76 | ///
77 | public void GetResult() { }
78 |
79 | ///
80 | public DispatcherThreadSwitcher GetAwaiter() => this;
81 |
82 | ///
83 | IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;
84 |
85 | ///
86 | public void OnCompleted(Action continuation) => _ = dispatcher.RunAsync(priority, continuation.Invoke);
87 | }
88 |
89 | ///
90 | /// A helper type for switch thread by . This type is not intended to be used directly from your code.
91 | ///
92 | [EditorBrowsable(EditorBrowsableState.Never)]
93 | public readonly struct ThreadPoolThreadSwitcher : IThreadSwitcher
94 | {
95 | ///
96 | /// Specifies the priority for event dispatch.
97 | ///
98 | private readonly WorkItemPriority priority;
99 |
100 | ///
101 | /// Initializes a new instance of the struct.
102 | ///
103 | /// Specifies the priority for event dispatch.
104 | public ThreadPoolThreadSwitcher(WorkItemPriority priority = WorkItemPriority.Normal) => this.priority = priority;
105 |
106 | ///
107 | public bool IsCompleted => SynchronizationContext.Current == null;
108 |
109 | ///
110 | public void GetResult() { }
111 |
112 | ///
113 | public ThreadPoolThreadSwitcher GetAwaiter() => this;
114 |
115 | ///
116 | IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;
117 |
118 | ///
119 | public void OnCompleted(Action continuation) => _ = ThreadPool.RunAsync(_ => continuation(), priority);
120 | }
121 |
122 | ///
123 | /// The extensions for switching threads.
124 | ///
125 | public static class ThreadSwitcher
126 | {
127 | ///
128 | /// A helper function—for use within a coroutine—that you can to switch execution to a specific foreground thread.
129 | ///
130 | /// A whose foreground thread to switch execution to.
131 | /// Specifies the priority for event dispatch.
132 | /// An object that you can .
133 | public static DispatcherThreadSwitcher ResumeForegroundAsync(this CoreDispatcher dispatcher, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) => new DispatcherThreadSwitcher(dispatcher, priority);
134 |
135 | ///
136 | /// A helper function—for use within a coroutine—that returns control to the caller, and then immediately resumes execution on a thread pool thread.
137 | ///
138 | /// Specifies the priority for event dispatch.
139 | /// An object that you can .
140 | public static ThreadPoolThreadSwitcher ResumeBackgroundAsync(WorkItemPriority priority = WorkItemPriority.Normal) => new ThreadPoolThreadSwitcher(priority);
141 | }
142 | }
--------------------------------------------------------------------------------
/TextReader/Controls/AboutFlyout.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
32 |
37 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
55 |
59 |
60 |
65 |
69 |
70 |
79 |
80 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/TextReader/Controls/AboutFlyout.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Windows.ApplicationModel;
3 | using Windows.ApplicationModel.Resources;
4 | using Windows.Storage;
5 | using Windows.System;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Controls;
8 |
9 | //https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板
10 |
11 | namespace TextReader.Controls
12 | {
13 | public sealed partial class AboutFlyout : UserControl
14 | {
15 | // CSHARP_MIGRATION: TODO:
16 | // BUILD_YEAR was a C++/CX macro and may update the value from the pipeline
17 | private const string BUILD_YEAR = "2024";
18 |
19 | public AboutFlyout()
20 | {
21 | ResourceLoader _loader = ResourceLoader.GetForViewIndependentUse("AboutFlyout");
22 |
23 | InitializeComponent();
24 |
25 | SetVersionString();
26 |
27 | Header.Text = _loader.GetString("AboutButton/Content");
28 |
29 | string copyrightText = string.Format(_loader.GetString("AboutControlCopyright"), BUILD_YEAR);
30 | AboutControlCopyrightRun.Text = copyrightText;
31 |
32 | InitializeContributeTextBlock(_loader);
33 | }
34 |
35 | private void FeedbackButton_Click(object sender, RoutedEventArgs e)
36 | {
37 | _ = Launcher.LaunchUriAsync(new Uri("https://github.com/wherewhere/Text-Reader/issues/new"));
38 | }
39 |
40 | private async void AboutFlyoutLog_Click(object sender, RoutedEventArgs e)
41 | {
42 | _ = Launcher.LaunchFolderAsync(await ApplicationData.Current.LocalFolder.CreateFolderAsync("MetroLogs", CreationCollisionOption.OpenIfExists));
43 | }
44 |
45 | private void SetVersionString()
46 | {
47 | PackageVersion version = Package.Current.Id.Version;
48 | string appName = ResourceLoader.GetForViewIndependentUse().GetString("AppName") ?? "Text Reader";
49 | AboutFlyoutVersion.Text = appName + " " + version.Major + "." + version.Minor + "." + version.Build + "." + version.Revision;
50 | }
51 |
52 | private void InitializeContributeTextBlock(ResourceLoader _loader)
53 | {
54 | string appName = ResourceLoader.GetForViewIndependentUse().GetString("AppName") ?? "Text Reader";
55 | string contributeHyperlinkText = string.Format(_loader.GetString("AboutFlyoutContribute"), appName);
56 |
57 | // The resource string has the 'GitHub' hyperlink wrapped with '%HL%'.
58 | // Break the string and assign pieces appropriately.
59 | string delimiter = "%HL%";
60 | int delimiterLength = delimiter.Length;
61 |
62 | // Find the delimiters.
63 | int firstSplitPosition = contributeHyperlinkText.IndexOf(delimiter, 0);
64 | int secondSplitPosition = contributeHyperlinkText.IndexOf(delimiter, firstSplitPosition + 1);
65 | int hyperlinkTextLength = secondSplitPosition - (firstSplitPosition + delimiterLength);
66 |
67 | // Assign pieces.
68 | string contributeTextBeforeHyperlink = contributeHyperlinkText.Substring(0, firstSplitPosition);
69 | string contributeTextLink = contributeHyperlinkText.Substring(firstSplitPosition + delimiterLength, hyperlinkTextLength);
70 | string contributeTextAfterHyperlink = contributeHyperlinkText.Substring(secondSplitPosition + delimiterLength);
71 |
72 | ContributeRunBeforeLink.Text = contributeTextBeforeHyperlink;
73 | ContributeRunLink.Text = contributeTextLink;
74 | ContributeRunAfterLink.Text = contributeTextAfterHyperlink;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/TextReader/Controls/ApplicationLogo/ApplicationLogo.cs:
--------------------------------------------------------------------------------
1 | using Windows.UI.Xaml.Controls;
2 |
3 | namespace TextReader.Controls
4 | {
5 | public partial class ApplicationLogo : Control
6 | {
7 | ///
8 | /// Creates a new instance of the class.
9 | ///
10 | public ApplicationLogo() => DefaultStyleKey = typeof(ApplicationLogo);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/TextReader/Controls/ApplicationLogo/ApplicationLogo.xaml:
--------------------------------------------------------------------------------
1 |
2 |
76 |
77 |
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/BitmapFileFormat.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace TextReader.Controls
6 | {
7 | ///
8 | /// This denotes the format used when saving a bitmap to a file.
9 | ///
10 | public enum BitmapFileFormat
11 | {
12 | ///
13 | /// Indicates Windows Imaging Component's bitmap encoder.
14 | ///
15 | Bmp,
16 |
17 | ///
18 | /// Indicates Windows Imaging Component's PNG encoder.
19 | ///
20 | Png,
21 |
22 | ///
23 | /// Indicates Windows Imaging Component's bitmap JPEG encoder.
24 | ///
25 | Jpeg,
26 |
27 | ///
28 | /// Indicates Windows Imaging Component's TIFF encoder.
29 | ///
30 | Tiff,
31 |
32 | ///
33 | /// Indicates Windows Imaging Component's GIF encoder.
34 | ///
35 | Gif,
36 |
37 | ///
38 | /// Indicates Windows Imaging Component's JPEGXR encoder.
39 | ///
40 | JpegXR
41 | }
42 | }
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/CropShape.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace TextReader.Controls
6 | {
7 | ///
8 | /// Crop shape enumeration.
9 | /// Default is
10 | ///
11 | public enum CropShape
12 | {
13 | ///
14 | /// Use rectangular shape to crop image.
15 | ///
16 | Rectangular,
17 |
18 | ///
19 | /// Use circular shape to crop image.
20 | ///
21 | Circular
22 | }
23 | }
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/ImageCropper.Constants.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace TextReader.Controls
6 | {
7 | ///
8 | /// The control allows user to crop image freely.
9 | ///
10 | public partial class ImageCropper
11 | {
12 | ///
13 | /// Key of the root layout container.
14 | ///
15 | private const string LayoutGridName = "PART_LayoutGrid";
16 |
17 | ///
18 | /// Key of the Canvas that contains the image and ImageCropperThumbs.
19 | ///
20 | private const string ImageCanvasPartName = "PART_ImageCanvas";
21 |
22 | ///
23 | /// Key of the Image Control inside the ImageCropper Control.
24 | ///
25 | private const string SourceImagePartName = "PART_SourceImage";
26 |
27 | ///
28 | /// Key of the mask layer.
29 | ///
30 | private const string MaskAreaPathPartName = "PART_MaskAreaPath";
31 |
32 | ///
33 | /// Key of the ImageCropperThumb that on the top.
34 | ///
35 | private const string TopThumbPartName = "PART_TopThumb";
36 |
37 | ///
38 | /// Key of the ImageCropperThumb on the bottom.
39 | ///
40 | private const string BottomThumbPartName = "PART_BottomThumb";
41 |
42 | ///
43 | /// Key of the ImageCropperThumb on the left.
44 | ///
45 | private const string LeftThumbPartName = "PART_LeftThumb";
46 |
47 | ///
48 | /// Key of the ImageCropperThumb on the right.
49 | ///
50 | private const string RightThumbPartName = "PART_RightThumb";
51 |
52 | ///
53 | /// Key of the ImageCropperThumb that on the upper left.
54 | ///
55 | private const string UpperLeftThumbPartName = "PART_UpperLeftThumb";
56 |
57 | ///
58 | /// Key of the ImageCropperThumb that on the upper right.
59 | ///
60 | private const string UpperRightThumbPartName = "PART_UpperRightThumb";
61 |
62 | ///
63 | /// Key of the ImageCropperThumb that on the lower left.
64 | ///
65 | private const string LowerLeftThumbPartName = "PART_LowerLeftThumb";
66 |
67 | ///
68 | /// Key of the ImageCropperThumb that on the lower right.
69 | ///
70 | private const string LowerRightThumbPartName = "PART_LowerRightThumb";
71 | }
72 | }
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/ImageCropper.Events.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using TextReader.Extensions;
7 | using Windows.Foundation;
8 | using Windows.System;
9 | using Windows.UI.Core;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Input;
12 |
13 | namespace TextReader.Controls
14 | {
15 | ///
16 | /// The control allows user to crop image freely.
17 | ///
18 | public partial class ImageCropper
19 | {
20 | private void ImageCropperThumb_KeyDown(object sender, KeyRoutedEventArgs e)
21 | {
22 | bool changed = false;
23 | Point diffPos = default;
24 | if (e.Key == VirtualKey.Left)
25 | {
26 | diffPos.X--;
27 | CoreVirtualKeyStates upKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Up);
28 | CoreVirtualKeyStates downKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Down);
29 | if (upKeyState == CoreVirtualKeyStates.Down)
30 | {
31 | diffPos.Y--;
32 | }
33 |
34 | if (downKeyState == CoreVirtualKeyStates.Down)
35 | {
36 | diffPos.Y++;
37 | }
38 |
39 | changed = true;
40 | }
41 | else if (e.Key == VirtualKey.Right)
42 | {
43 | diffPos.X++;
44 | CoreVirtualKeyStates upKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Up);
45 | CoreVirtualKeyStates downKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Down);
46 | if (upKeyState == CoreVirtualKeyStates.Down)
47 | {
48 | diffPos.Y--;
49 | }
50 |
51 | if (downKeyState == CoreVirtualKeyStates.Down)
52 | {
53 | diffPos.Y++;
54 | }
55 |
56 | changed = true;
57 | }
58 | else if (e.Key == VirtualKey.Up)
59 | {
60 | diffPos.Y--;
61 | CoreVirtualKeyStates leftKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Left);
62 | CoreVirtualKeyStates rightKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Right);
63 | if (leftKeyState == CoreVirtualKeyStates.Down)
64 | {
65 | diffPos.X--;
66 | }
67 |
68 | if (rightKeyState == CoreVirtualKeyStates.Down)
69 | {
70 | diffPos.X++;
71 | }
72 |
73 | changed = true;
74 | }
75 | else if (e.Key == VirtualKey.Down)
76 | {
77 | diffPos.Y++;
78 | CoreVirtualKeyStates leftKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Left);
79 | CoreVirtualKeyStates rightKeyState = Window.Current.CoreWindow.GetAsyncKeyState(VirtualKey.Right);
80 | if (leftKeyState == CoreVirtualKeyStates.Down)
81 | {
82 | diffPos.X--;
83 | }
84 |
85 | if (rightKeyState == CoreVirtualKeyStates.Down)
86 | {
87 | diffPos.X++;
88 | }
89 |
90 | changed = true;
91 | }
92 |
93 | if (changed)
94 | {
95 | ImageCropperThumb imageCropperThumb = (ImageCropperThumb)sender;
96 | UpdateCroppedRect(imageCropperThumb.Position, diffPos);
97 | }
98 | }
99 |
100 | private void ImageCropperThumb_KeyUp(object sender, KeyRoutedEventArgs e)
101 | {
102 | Rect selectedRect = new Point(_startX, _startY).ToRect(new Point(_endX, _endY));
103 | Rect croppedRect = _inverseImageTransform.TransformBounds(selectedRect);
104 | if (croppedRect.Width > MinCropSize.Width && croppedRect.Height > MinCropSize.Height)
105 | {
106 | croppedRect.Intersect(_restrictedCropRect);
107 | _currentCroppedRect = croppedRect;
108 | }
109 |
110 | UpdateImageLayout(true);
111 | }
112 |
113 | private void ImageCropperThumb_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
114 | {
115 | Rect selectedRect = new Point(_startX, _startY).ToRect(new Point(_endX, _endY));
116 | Rect croppedRect = _inverseImageTransform.TransformBounds(selectedRect);
117 | if (croppedRect.Width > MinCropSize.Width && croppedRect.Height > MinCropSize.Height)
118 | {
119 | croppedRect.Intersect(_restrictedCropRect);
120 | _currentCroppedRect = croppedRect;
121 | }
122 |
123 | UpdateImageLayout(true);
124 | }
125 |
126 | private void ImageCropperThumb_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
127 | {
128 | ImageCropperThumb imageCropperThumb = (ImageCropperThumb)sender;
129 | Point currentPointerPosition = new Point(
130 | imageCropperThumb.X + e.Position.X + e.Delta.Translation.X - (imageCropperThumb.ActualWidth / 2),
131 | imageCropperThumb.Y + e.Position.Y + e.Delta.Translation.Y - (imageCropperThumb.ActualHeight / 2));
132 | Point safePosition = GetSafePoint(_restrictedSelectRect, currentPointerPosition);
133 | Point safeDiffPoint = new Point(safePosition.X - imageCropperThumb.X, safePosition.Y - imageCropperThumb.Y);
134 | UpdateCroppedRect(imageCropperThumb.Position, safeDiffPoint);
135 | }
136 |
137 | private void SourceImage_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
138 | {
139 | double offsetX = -e.Delta.Translation.X;
140 | double offsetY = -e.Delta.Translation.Y;
141 | offsetX = offsetX > 0
142 | ? Math.Min(offsetX, _restrictedSelectRect.X + _restrictedSelectRect.Width - _endX)
143 | : Math.Max(offsetX, _restrictedSelectRect.X - _startX);
144 |
145 | offsetY = offsetY > 0
146 | ? Math.Min(offsetY, _restrictedSelectRect.Y + _restrictedSelectRect.Height - _endY)
147 | : Math.Max(offsetY, _restrictedSelectRect.Y - _startY);
148 |
149 | Rect selectedRect = new Point(_startX, _startY).ToRect(new Point(_endX, _endY));
150 | selectedRect.X += offsetX;
151 | selectedRect.Y += offsetY;
152 | Rect croppedRect = _inverseImageTransform.TransformBounds(selectedRect);
153 | croppedRect.Intersect(_restrictedCropRect);
154 | _currentCroppedRect = croppedRect;
155 | UpdateImageLayout();
156 | }
157 |
158 | private void ImageCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
159 | {
160 | if (Source == null)
161 | {
162 | return;
163 | }
164 |
165 | UpdateImageLayout();
166 | UpdateMaskArea();
167 | }
168 | }
169 | }
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/ImageCropper.xaml:
--------------------------------------------------------------------------------
1 |
6 |
69 |
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/ImageCropperThumb.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using Windows.UI.Xaml;
6 | using Windows.UI.Xaml.Controls;
7 | using Windows.UI.Xaml.Input;
8 | using Windows.UI.Xaml.Media;
9 |
10 | namespace TextReader.Controls
11 | {
12 | ///
13 | /// The control is used for .
14 | ///
15 | public class ImageCropperThumb : Control
16 | {
17 | private readonly TranslateTransform _layoutTransform = new TranslateTransform();
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | public ImageCropperThumb()
23 | {
24 | DefaultStyleKey = typeof(ImageCropperThumb);
25 | RenderTransform = _layoutTransform;
26 | ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
27 | SizeChanged += ImageCropperThumb_SizeChanged;
28 | }
29 |
30 | private void ImageCropperThumb_SizeChanged(object sender, SizeChangedEventArgs e)
31 | {
32 | UpdatePosition();
33 | }
34 |
35 | internal ThumbPosition Position { get; set; }
36 |
37 | private void UpdatePosition()
38 | {
39 | if (_layoutTransform != null)
40 | {
41 | _layoutTransform.X = X - (this.ActualWidth / 2);
42 | _layoutTransform.Y = Y - (this.ActualHeight / 2);
43 | }
44 | }
45 |
46 | ///
47 | /// Gets or sets the X coordinate of the ImageCropperThumb.
48 | ///
49 | public double X
50 | {
51 | get { return (double)GetValue(XProperty); }
52 | set { SetValue(XProperty, value); }
53 | }
54 |
55 | private static void OnXChanged(
56 | DependencyObject d, DependencyPropertyChangedEventArgs e)
57 | {
58 | ImageCropperThumb target = (ImageCropperThumb)d;
59 | target.UpdatePosition();
60 | }
61 |
62 | ///
63 | /// Gets or sets the Y coordinate of the ImageCropperThumb.
64 | ///
65 | public double Y
66 | {
67 | get { return (double)GetValue(YProperty); }
68 | set { SetValue(YProperty, value); }
69 | }
70 |
71 | private static void OnYChanged(
72 | DependencyObject d, DependencyPropertyChangedEventArgs e)
73 | {
74 | ImageCropperThumb target = (ImageCropperThumb)d;
75 | target.UpdatePosition();
76 | }
77 |
78 | ///
79 | /// Identifies the dependency property.
80 | ///
81 | public static readonly DependencyProperty XProperty =
82 | DependencyProperty.Register(nameof(X), typeof(double), typeof(ImageCropperThumb), new PropertyMetadata(0d, OnXChanged));
83 |
84 | ///
85 | /// Identifies the dependency property.
86 | ///
87 | public static readonly DependencyProperty YProperty =
88 | DependencyProperty.Register(nameof(Y), typeof(double), typeof(ImageCropperThumb), new PropertyMetadata(0d, OnYChanged));
89 | }
90 | }
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/ImageCropperThumb.xaml:
--------------------------------------------------------------------------------
1 |
5 |
25 |
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/ThumbPlacement.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace TextReader.Controls
6 | {
7 | ///
8 | /// Thumb placement enumeration.
9 | /// Default is
10 | ///
11 | public enum ThumbPlacement
12 | {
13 | ///
14 | /// Shows the thumbs in all four corners, top, bottom, left and right.
15 | ///
16 | All,
17 |
18 | ///
19 | /// Shows the thumbs in all four corners.
20 | ///
21 | Corners
22 | }
23 | }
--------------------------------------------------------------------------------
/TextReader/Controls/ImageCropper/ThumbPosition.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace TextReader.Controls
6 | {
7 | ///
8 | /// Thumb position enumeration.
9 | ///
10 | internal enum ThumbPosition
11 | {
12 | Top,
13 | Bottom,
14 | Left,
15 | Right,
16 | UpperLeft,
17 | UpperRight,
18 | LowerLeft,
19 | LowerRight
20 | }
21 | }
--------------------------------------------------------------------------------
/TextReader/Controls/TwoPaneView/DisplayRegionHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using TextReader.Extensions;
3 | using TextReader.Helpers;
4 | using Windows.Foundation;
5 | using Windows.Foundation.Metadata;
6 | using Windows.UI.ViewManagement;
7 | using Windows.UI.WindowManagement;
8 | using Windows.UI.Xaml;
9 |
10 | namespace TextReader.Controls
11 | {
12 | public class DisplayRegionHelper
13 | {
14 | private static DisplayRegionHelper Instance;
15 |
16 | // TODO: Remove once ApplicationViewMode::Spanning is available in the SDK
17 | private const int c_ApplicationViewModeSpanning = 2;
18 |
19 | public static DisplayRegionHelper GetDisplayRegionHelperInstance()
20 | {
21 | if (Instance == null)
22 | {
23 | Instance = new DisplayRegionHelper();
24 | }
25 | return Instance;
26 | }
27 |
28 | public static DisplayRegionHelperInfo GetRegionInfo()
29 | {
30 | DisplayRegionHelper instance = GetDisplayRegionHelperInstance();
31 |
32 | DisplayRegionHelperInfo info = new DisplayRegionHelperInfo
33 | {
34 | Mode = TwoPaneViewMode.SinglePane
35 | };
36 |
37 | if (instance.m_simulateDisplayRegions)
38 | {
39 | // Create fake rectangles for test app
40 | if (instance.m_simulateMode == TwoPaneViewMode.Wide)
41 | {
42 | info.Regions[0] = m_simulateWide0;
43 | info.Regions[1] = m_simulateWide1;
44 | info.Mode = TwoPaneViewMode.Wide;
45 | }
46 | else if (instance.m_simulateMode == TwoPaneViewMode.Tall)
47 | {
48 | info.Regions[0] = m_simulateTall0;
49 | info.Regions[1] = m_simulateTall1;
50 | info.Mode = TwoPaneViewMode.Tall;
51 | }
52 | else
53 | {
54 | info.Regions[0] = m_simulateWide0;
55 | }
56 | }
57 | else if (ApiInformation.IsPropertyPresent("Windows.UI.ViewManagement.ApplicationView", "ViewMode"))
58 | {
59 | // ApplicationView::GetForCurrentView throws on failure; in that case we just won't do anything.
60 | ApplicationView view = null;
61 | try
62 | {
63 | view = ApplicationView.GetForCurrentView();
64 | }
65 | catch { }
66 |
67 | if (view != null && view.ViewMode == (ApplicationViewMode)c_ApplicationViewModeSpanning)
68 | {
69 | if (ApiInformation.IsPropertyPresent("Windows.UI.ViewManagement.ApplicationView", "GetDisplayRegions"))
70 | {
71 | IReadOnlyList rects = view.GetDisplayRegions();
72 |
73 | if (rects.Count == 2)
74 | {
75 | info.Regions[0] = rects[0].WorkAreaSize.ToRect(rects[0].WorkAreaOffset);
76 | info.Regions[1] = rects[1].WorkAreaSize.ToRect(rects[1].WorkAreaOffset);
77 |
78 | // Determine orientation. If neither of these are true, default to doing nothing.
79 | if (info.Regions[0].X < info.Regions[1].X && info.Regions[0].Y == info.Regions[1].Y)
80 | {
81 | // Double portrait
82 | info.Mode = TwoPaneViewMode.Wide;
83 | }
84 | else if (info.Regions[0].X == info.Regions[1].X && info.Regions[0].Y < info.Regions[1].Y)
85 | {
86 | // Double landscape
87 | info.Mode = TwoPaneViewMode.Tall;
88 | }
89 | }
90 | }
91 | }
92 | }
93 |
94 | return info;
95 | }
96 |
97 | /* static */
98 | public static UIElement WindowElement(UIElement element)
99 | {
100 | DisplayRegionHelper instance = GetDisplayRegionHelperInstance();
101 |
102 | if (instance.m_simulateDisplayRegions)
103 | {
104 | // Instead of returning the actual window, find the SimulatedWindow element
105 | UIElement window = null;
106 | UIElement xamlRoot = element.GetXAMLRoot();
107 |
108 | if (xamlRoot is FrameworkElement fe)
109 | {
110 | window = fe.FindDescendant("SimulatedWindow");
111 | }
112 |
113 | return window ?? xamlRoot;
114 | }
115 | else
116 | {
117 | return element.GetXAMLRoot();
118 | }
119 | }
120 |
121 | /* static */
122 | public static Rect WindowRect(UIElement element)
123 | {
124 | DisplayRegionHelper instance = GetDisplayRegionHelperInstance();
125 |
126 | if (instance.m_simulateDisplayRegions)
127 | {
128 | // Return the bounds of the simulated window
129 | FrameworkElement window = WindowElement(element) as FrameworkElement;
130 | Rect rc = new Rect(
131 | 0, 0,
132 | window.ActualWidth,
133 | window.ActualHeight);
134 | return rc;
135 | }
136 | else
137 | {
138 | return Window.Current.Bounds;
139 | }
140 | }
141 |
142 | /* static */
143 | public static bool SimulateDisplayRegions
144 | {
145 | get
146 | {
147 | DisplayRegionHelper instance = GetDisplayRegionHelperInstance();
148 | return instance.m_simulateDisplayRegions;
149 | }
150 | set
151 | {
152 | DisplayRegionHelper instance = GetDisplayRegionHelperInstance();
153 | instance.m_simulateDisplayRegions = value;
154 | }
155 | }
156 |
157 | /* static */
158 | public static TwoPaneViewMode SimulateMode
159 | {
160 | get
161 | {
162 | DisplayRegionHelper instance = GetDisplayRegionHelperInstance();
163 | return instance.m_simulateMode;
164 | }
165 | set
166 | {
167 | DisplayRegionHelper instance = GetDisplayRegionHelperInstance();
168 | instance.m_simulateMode = value;
169 | }
170 | }
171 |
172 | private bool m_simulateDisplayRegions = false;
173 | private TwoPaneViewMode m_simulateMode = TwoPaneViewMode.SinglePane;
174 | private static Rect m_simulateWide0 = new Rect(0, 0, 300, 400);
175 | private static Rect m_simulateWide1 = new Rect(312, 0, 300, 400);
176 | private static Rect m_simulateTall0 = new Rect(0, 0, 400, 300);
177 | private static Rect m_simulateTall1 = new Rect(0, 312, 400, 300);
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/TextReader/Controls/TwoPaneView/DisplayRegionHelperInfo.cs:
--------------------------------------------------------------------------------
1 | using Windows.Foundation;
2 |
3 | namespace TextReader.Controls
4 | {
5 | public class DisplayRegionHelperInfo
6 | {
7 | private const int c_maxRegions = 2;
8 |
9 | public TwoPaneViewMode Mode { get; set; }
10 | public Rect[] Regions { get; set; } = new Rect[c_maxRegions];
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/TextReader/Controls/TwoPaneView/TwoPaneView.Enum.cs:
--------------------------------------------------------------------------------
1 | namespace TextReader.Controls
2 | {
3 | public enum ViewMode
4 | {
5 | Pane1Only,
6 | Pane2Only,
7 | LeftRight,
8 | RightLeft,
9 | TopBottom,
10 | BottomTop,
11 | None
12 | }
13 |
14 | public enum TwoPaneViewPriority
15 | {
16 | Pane1 = 0,
17 | Pane2 = 1
18 | }
19 |
20 | public enum TwoPaneViewMode
21 | {
22 | SinglePane = 0,
23 | Wide = 1,
24 | Tall = 2
25 | }
26 |
27 | public enum TwoPaneViewWideModeConfiguration
28 | {
29 | SinglePane = 0,
30 | LeftRight = 1,
31 | RightLeft = 2
32 | }
33 |
34 | public enum TwoPaneViewTallModeConfiguration
35 | {
36 | SinglePane = 0,
37 | TopBottom = 1,
38 | BottomTop = 2
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/TextReader/Controls/TwoPaneView/TwoPaneView.xaml:
--------------------------------------------------------------------------------
1 |
5 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/TextReader/Extensions/FrameworkElement/FrameworkElementExtensions.Mouse.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using Windows.UI.Core;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Input;
10 |
11 | namespace TextReader.Extensions
12 | {
13 | ///
14 | public static partial class FrameworkElementExtensions
15 | {
16 | private static readonly object _cursorLock = new object();
17 | private static readonly CoreCursor _defaultCursor = new CoreCursor(CoreCursorType.Arrow, 1);
18 | private static readonly Dictionary _cursors =
19 | new Dictionary { { CoreCursorType.Arrow, _defaultCursor } };
20 |
21 | ///
22 | /// Dependency property for specifying the target to be shown
23 | /// over the target .
24 | ///
25 | public static readonly DependencyProperty CursorProperty =
26 | DependencyProperty.RegisterAttached("Cursor", typeof(CoreCursorType), typeof(FrameworkElementExtensions), new PropertyMetadata(CoreCursorType.Arrow, CursorChanged));
27 |
28 | ///
29 | /// Set the target .
30 | ///
31 | /// Object where the selector cursor type should be shown.
32 | /// Target cursor type value.
33 | public static void SetCursor(FrameworkElement element, CoreCursorType value)
34 | {
35 | element.SetValue(CursorProperty, value);
36 | }
37 |
38 | ///
39 | /// Get the current .
40 | ///
41 | /// Object where the selector cursor type should be shown.
42 | /// Cursor type set on target element.
43 | public static CoreCursorType GetCursor(FrameworkElement element)
44 | {
45 | return (CoreCursorType)element.GetValue(CursorProperty);
46 | }
47 |
48 | private static void CursorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
49 | {
50 | if (!(d is FrameworkElement element))
51 | {
52 | throw new NullReferenceException(nameof(element));
53 | }
54 |
55 | CoreCursorType value = (CoreCursorType)e.NewValue;
56 |
57 | // lock ensures CoreCursor creation and event handlers attachment/detachment is atomic
58 | lock (_cursorLock)
59 | {
60 | if (!_cursors.ContainsKey(value))
61 | {
62 | _cursors[value] = new CoreCursor(value, 1);
63 | }
64 |
65 | // make sure event handlers are not attached twice to element
66 | element.PointerEntered -= Element_PointerEntered;
67 | element.PointerEntered += Element_PointerEntered;
68 | element.PointerExited -= Element_PointerExited;
69 | element.PointerExited += Element_PointerExited;
70 | element.Unloaded -= ElementOnUnloaded;
71 | element.Unloaded += ElementOnUnloaded;
72 | }
73 | }
74 |
75 | private static void Element_PointerEntered(object sender, PointerRoutedEventArgs e)
76 | {
77 | CoreCursorType cursor = GetCursor((FrameworkElement)sender);
78 | Window.Current.CoreWindow.PointerCursor = _cursors[cursor];
79 | }
80 |
81 | private static void Element_PointerExited(object sender, PointerRoutedEventArgs e)
82 | {
83 | // when exiting change the cursor to the target Mouse.Cursor value of the new element
84 | CoreCursor cursor = sender != e.OriginalSource && e.OriginalSource is FrameworkElement newElement
85 | ? _cursors[GetCursor(newElement)]
86 | : _defaultCursor;
87 | Window.Current.CoreWindow.PointerCursor = cursor;
88 | }
89 |
90 | private static void ElementOnUnloaded(object sender, RoutedEventArgs routedEventArgs)
91 | {
92 | // when the element is programatically unloaded, reset the cursor back to default
93 | // this is necessary when click triggers immediate change in layout and PointerExited is not called
94 | Window.Current.CoreWindow.PointerCursor = _defaultCursor;
95 | }
96 | }
97 | }
--------------------------------------------------------------------------------
/TextReader/Extensions/PointExtensions.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Diagnostics.Contracts;
6 | using System.Runtime.CompilerServices;
7 | using Point = Windows.Foundation.Point;
8 | using Rect = Windows.Foundation.Rect;
9 | using Size = Windows.Foundation.Size;
10 |
11 | namespace TextReader.Extensions
12 | {
13 | ///
14 | /// Extensions for the type.
15 | ///
16 | public static class PointExtensions
17 | {
18 | ///
19 | /// Creates a new of the specified size, starting at a given point.
20 | ///
21 | /// The input value to convert.
22 | /// The width of the rectangle.
23 | /// The height of the rectangle.
24 | /// A value of the specified size, starting at the given point.
25 | [Pure]
26 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
27 | public static Rect ToRect(this Point point, double width, double height)
28 | {
29 | return new Rect(point.X, point.Y, width, height);
30 | }
31 |
32 | ///
33 | /// Creates a new ending at the specified point, starting at the given coordinates.
34 | ///
35 | /// The input value to convert.
36 | /// The ending position for the rectangle.
37 | /// A value between the two specified points.
38 | [Pure]
39 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
40 | public static Rect ToRect(this Point point, Point end)
41 | {
42 | return new Rect(point, end);
43 | }
44 |
45 | ///
46 | /// Creates a new of the specified size, starting at the given coordinates.
47 | ///
48 | /// The input value to convert.
49 | /// The size of the rectangle to create.
50 | /// A value of the specified size, starting at the given coordinates.
51 | [Pure]
52 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
53 | public static Rect ToRect(this Point point, Size size)
54 | {
55 | return new Rect(point, size);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/TextReader/Extensions/Predicates/Interfaces/IPredicate{T}.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace TextReader.Extensions.Predicates
6 | {
7 | ///
8 | /// An interface representing a predicate for items of a given type.
9 | ///
10 | /// The type of items to match.
11 | internal interface IPredicate
12 | where T : class
13 | {
14 | ///
15 | /// Performs a match with the current predicate over a target instance.
16 | ///
17 | /// The input element to match.
18 | /// Whether the match evaluation was successful.
19 | bool Match(T element);
20 | }
21 | }
--------------------------------------------------------------------------------
/TextReader/Extensions/Predicates/PredicateByAny{T}.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Runtime.CompilerServices;
6 |
7 | namespace TextReader.Extensions.Predicates
8 | {
9 | ///
10 | /// An type matching all instances of a given type.
11 | ///
12 | /// The type of items to match.
13 | internal readonly struct PredicateByAny : IPredicate
14 | where T : class
15 | {
16 | ///
17 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
18 | public bool Match(T element)
19 | {
20 | return true;
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/TextReader/Extensions/Predicates/PredicateByFunc{T,TState}.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Runtime.CompilerServices;
7 |
8 | namespace TextReader.Extensions.Predicates
9 | {
10 | ///
11 | /// An type matching items of a given type.
12 | ///
13 | /// The type of items to match.
14 | /// The type of state to use when matching items.
15 | internal readonly struct PredicateByFunc : IPredicate
16 | where T : class
17 | {
18 | ///
19 | /// The state to give as input to .
20 | ///
21 | private readonly TState state;
22 |
23 | ///
24 | /// The predicatee to use to match items.
25 | ///
26 | private readonly Func predicate;
27 |
28 | ///
29 | /// Initializes a new instance of the struct.
30 | ///
31 | /// The state to give as input to .
32 | /// The predicatee to use to match items.
33 | public PredicateByFunc(TState state, Func predicate)
34 | {
35 | this.state = state;
36 | this.predicate = predicate;
37 | }
38 |
39 | ///
40 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
41 | public bool Match(T element)
42 | {
43 | return predicate(element, state);
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/TextReader/Extensions/Predicates/PredicateByFunc{T}.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Runtime.CompilerServices;
7 |
8 | namespace TextReader.Extensions.Predicates
9 | {
10 | ///
11 | /// An type matching items of a given type.
12 | ///
13 | /// The type of items to match.
14 | internal readonly struct PredicateByFunc : IPredicate
15 | where T : class
16 | {
17 | ///
18 | /// The predicatee to use to match items.
19 | ///
20 | private readonly Func predicate;
21 |
22 | ///
23 | /// Initializes a new instance of the struct.
24 | ///
25 | /// The predicatee to use to match items.
26 | public PredicateByFunc(Func predicate)
27 | {
28 | this.predicate = predicate;
29 | }
30 |
31 | ///
32 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
33 | public bool Match(T element)
34 | {
35 | return predicate(element);
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/TextReader/Extensions/Predicates/PredicateByName.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Runtime.CompilerServices;
7 | using Windows.UI.Xaml;
8 |
9 | namespace TextReader.Extensions.Predicates
10 | {
11 | ///
12 | /// An type matching instances by name.
13 | ///
14 | internal readonly struct PredicateByName : IPredicate
15 | {
16 | ///
17 | /// The name of the element to look for.
18 | ///
19 | private readonly string name;
20 |
21 | ///
22 | /// The comparison type to use to match .
23 | ///
24 | private readonly StringComparison comparisonType;
25 |
26 | ///
27 | /// Initializes a new instance of the struct.
28 | ///
29 | /// The name of the element to look for.
30 | /// The comparison type to use to match .
31 | public PredicateByName(string name, StringComparison comparisonType)
32 | {
33 | this.name = name;
34 | this.comparisonType = comparisonType;
35 | }
36 |
37 | ///
38 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
39 | public bool Match(FrameworkElement element)
40 | {
41 | return element.Name.Equals(name, comparisonType);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/TextReader/Extensions/Predicates/PredicateByType.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Runtime.CompilerServices;
7 |
8 | namespace TextReader.Extensions.Predicates
9 | {
10 | ///
11 | /// An type matching items of a given type.
12 | ///
13 | internal readonly struct PredicateByType : IPredicate