├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.ko.md
├── README.md
├── README.zh-CN.md
└── src
├── ColorPicker.Forms
├── ColorPicker.Forms.csproj
├── Local
│ └── ViewModels
│ │ └── ColorPickerViewModel.cs
├── Properties
│ └── AssemblyInfo.cs
├── Themes
│ ├── Generic.xaml
│ └── Views
│ │ └── PaletteWindow.xaml
└── UI
│ └── Views
│ └── ColorPickerWindow.cs
├── ColorPicker.Main
├── ColorPicker.Main.csproj
├── Local
│ └── ViewModels
│ │ └── MainContentViewModel.cs
├── Properties
│ └── AssemblyInfo.cs
├── Themes
│ ├── Generic.xaml
│ ├── Units
│ │ ├── ColorBox.xaml
│ │ ├── PaletteBox.xaml
│ │ └── PaletteBoxItem.xaml
│ └── Views
│ │ └── MainContent.xaml
└── UI
│ ├── Units
│ ├── ColorBox.cs
│ ├── PaletteBox.cs
│ └── PaletteBoxItem.cs
│ └── Views
│ └── MainContent.cs
├── ColorPicker.Sliders
├── ColorPicker.Sliders.csproj
├── Properties
│ └── AssemblyInfo.cs
├── Themes
│ ├── Generic.xaml
│ └── Units
│ │ └── ColorSlider.xaml
└── UI
│ └── Units
│ └── ColorSlider.cs
├── ColorPicker.Support
├── ColorPicker.Support.csproj
├── Local
│ ├── Config
│ │ └── ColorConfig.cs
│ ├── Converters
│ │ ├── EqualsToBooleanConverter.cs
│ │ └── RgbToHexConverter.cs
│ ├── Helpers
│ │ └── PixelExtractWorker.cs
│ └── Models
│ │ ├── ColorStampModel.cs
│ │ ├── ColorStruct.cs
│ │ ├── ConfigModel.cs
│ │ ├── ConverterColor.cs
│ │ ├── ExtractedColorCollection.cs
│ │ └── ViewOptionModel.cs
├── Properties
│ └── AssemblyInfo.cs
├── Themes
│ └── Generic.xaml
└── UI
│ └── Units
│ └── GeometryIcon.cs
├── ColorPicker.sln
├── ColorPicker
├── App.cs
├── ColorPicker.csproj
├── Images
│ └── logo.ico
├── Properties
│ ├── AssemblyInfo.cs
│ ├── ViewModules.cs
│ └── WireDataContext.cs
└── Starter.cs
└── _ColorPicker
├── App.cs
├── ColorPicker.csproj
├── Local
├── Config
│ └── ColorConfig.cs
├── Converter
│ ├── EqualsToBooleanConverter.cs
│ └── RgbToHexConverter.cs
├── Data
│ ├── ColorStampModel.cs
│ ├── ColorStruct.cs
│ ├── ConfigModel.cs
│ ├── ConverterColor.cs
│ ├── ExtractedColorCollection.cs
│ └── ViewOptionModel.cs
├── ViewModel
│ └── MainViewModel.cs
└── Worker
│ ├── CaptureWorker.cs
│ └── PixelExtractWorker.cs
├── Properties
├── AssemblyInfo.cs
└── colorpicker.ico
├── Startup.cs
├── Themes
├── Generic.xaml
├── Units
│ ├── ColorSlider.xaml
│ ├── ExtractColorBox.xaml
│ ├── PaletteGridBox.xaml
│ └── PaletteGridBoxItem.xaml
└── Views
│ └── MainWindow.xaml
└── UI
├── Units
├── ColorSlider.cs
├── ExtractColorBox.cs
├── PaletteGridBox.cs
└── PaletteGridBoxItem.cs
└── Views
└── MainWindow.cs
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [jameslee214]
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 DevNcore
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.ko.md:
--------------------------------------------------------------------------------
1 | # ColorPicker [](README.md) [](README.zh-CN.md) [](README.ko.md)
2 |
3 | Windows에서 색상을 캡처하고 조작할 수 있는 개발자와 디자이너를 위한 실용적인 유틸리티
4 |
5 | [](https://opensource.org/licenses/MIT)
6 | [](https://dotnet.microsoft.com/download)
7 | [](https://github.com/jamesnet214/colorpicker/stargazers)
8 | [](https://github.com/jamesnet214/colorpicker/issues)
9 |
10 | ## 프로젝트 개요
11 | ColorPicker는 Windows 운영 체제용 유틸리티 프로그램으로, 사용자가 원하는 색상을 쉽게 캡처하거나 색상을 조합하여 Hex 값을 추출할 수 있게 해줍니다. 이는 간단한 프로그램부터 Photoshop, Illustrator, MS Office, Visual Studio와 같은 전문 소프트웨어에 이르기까지 다양한 애플리케이션에서 개발자와 디자이너가 자주 사용하는 도구입니다.
12 |
13 |
14 |
15 |
16 | ## 핵심 기술 및 구현 사항
17 | #### 1. 커스텀 컨트롤 개발
18 | - [x] 커스텀 ColorWheel 및 ColorSlider 컨트롤 구현
19 | - [x] WPF 렌더링 기술의 고급 활용
20 |
21 | #### 2. MVVM 아키텍처
22 | - [x] MVVM 패턴의 완전한 구현 및 데이터 바인딩 최적화
23 | - [x] RelayCommand 및 INotifyPropertyChanged 인터페이스의 효과적인 사용
24 |
25 | #### 3. 고급 WPF 기술
26 | - [x] 동적 UI 업데이트를 위한 Trigger 활용
27 | - [x] 가상화를 적용한 커스텀 ItemsControl 구현
28 | - [x] ControlTemplate 및 DataTemplate의 고급 사용법
29 |
30 | #### 4. 색상 조작
31 | - [x] 다양한 색상 공간(RGB, HSV, Hex) 간의 실시간 색상 변환
32 | - [x] 화면 색상 캡처 기능
33 |
34 | #### 5. 성능 최적화
35 | - [x] 색상 휠 및 슬라이더의 효율적인 렌더링
36 | - [x] 빠른 색상 변경에도 부드러운 UI 상호작용
37 |
38 | ## 기술 스택
39 | - .NET 8.0
40 | - WPF (Windows Presentation Foundation)
41 | - MVVM (Model-View-ViewModel) 패턴
42 |
43 | ## 시작하기
44 | ### 필요 조건
45 | - Visual Studio 2022 이상
46 | - .NET 8.0 SDK
47 |
48 | ### 설치 및 실행
49 | #### 1. 리포지토리 클론:
50 | ```
51 | git clone https://github.com/jamesnet214/colorpicker.git
52 | ```
53 | #### 2. 솔루션 열기
54 | - [x] Visual Studio
55 | - [x] Visual Studio Code
56 | - [x] Jetbrains Rider
57 |
58 |
59 |
60 |
61 |
62 | #### 3. 빌드 및 실행
63 | - [x] Windows 11 권장
64 |
65 | ## 사용 방법
66 | 1. ColorPicker 애플리케이션 실행
67 | 2. 색상 휠이나 슬라이더를 사용하여 색상 선택
68 | 3. 스포이트 도구를 사용하여 화면에서 색상 캡처
69 | 4. 선택한 색상의 Hex, RGB 또는 HSV 값 확인 및 복사
70 |
71 | ## 기여하기
72 | 프로젝트 개선에 기여하고 싶으시다면 Pull Request를 보내주세요. 모든 형태의 기여를 환영합니다!
73 |
74 | ## 라이선스
75 | 이 프로젝트는 MIT 라이선스 하에 배포됩니다. 자세한 내용은 [LICENSE](https://github.com/jamesnet214/colorpicker/blob/main/LICENSE) 파일을 참조하세요.
76 |
77 | ## 연락처
78 | - 웹사이트: https://jamesnet.dev
79 | - 이메일: james@jamesnet.dev, vickyqu115@hotmail.com
80 |
81 | ColorPicker로 색상 조작 기술을 탐험하고 여러분의 프로젝트에 적용해보세요!
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ColorPicker [](README.md) [](README.zh-CN.md) [](README.ko.md)
2 |
3 | A practical utility for developers and designers to capture and manipulate colors in Windows
4 |
5 | [](https://opensource.org/licenses/MIT)
6 | [](https://dotnet.microsoft.com/download)
7 | [](https://github.com/jamesnet214/colorpicker/stargazers)
8 | [](https://github.com/jamesnet214/colorpicker/issues)
9 |
10 | ## Project Overview
11 | ColorPicker is a utility program for the Windows operating system that allows users to easily capture desired colors or extract Hex values by combining colors. It's a tool frequently used by both developers and designers, found in applications ranging from simple programs to professional software like Photoshop, Illustrator, MS Office, and IDEs like Visual Studio.
12 |
13 |
14 |
15 |
16 | ## Key Technologies and Implementations
17 | #### 1. Custom Control Development
18 | - [x] Implementation of custom ColorWheel and ColorSlider controls
19 | - [x] Advanced use of WPF rendering techniques
20 |
21 | #### 2. MVVM Architecture
22 | - [x] Full implementation of MVVM pattern and data binding optimization
23 | - [x] Effective use of RelayCommand and INotifyPropertyChanged interface
24 |
25 | #### 3. Advanced WPF Techniques
26 | - [x] Utilization of Triggers for dynamic UI updates
27 | - [x] Implementation of custom ItemsControl with virtualization
28 | - [x] Advanced usage of ControlTemplate and DataTemplate
29 |
30 | #### 4. Color Manipulation
31 | - [x] Real-time color conversion between different color spaces (RGB, HSV, Hex)
32 | - [x] Screen color capture functionality
33 |
34 | #### 5. Performance Optimization
35 | - [x] Efficient rendering of color wheel and sliders
36 | - [x] Smooth UI interactions even with rapid color changes
37 |
38 | ## Technology Stack
39 | - .NET 8.0
40 | - WPF (Windows Presentation Foundation)
41 | - MVVM (Model-View-ViewModel) pattern
42 |
43 | ## Getting Started
44 | ### Prerequisites
45 | - Visual Studio 2022 or later
46 | - .NET 8.0 SDK
47 |
48 | ### Installation and Execution
49 | #### 1. Clone the repository:
50 | ```
51 | git clone https://github.com/jamesnet214/colorpicker.git
52 | ```
53 | #### 2. Open the solution
54 | - [x] Visual Studio
55 | - [x] Visual Studio Code
56 | - [x] Jetbrains Rider
57 |
58 |
59 |
60 |
61 |
62 | #### 3. Build and Run
63 | - [x] Windows 11 recommended
64 |
65 | ## Usage
66 | 1. Launch the ColorPicker application
67 | 2. Use the color wheel or sliders to select a color
68 | 3. Capture colors from your screen using the eyedropper tool
69 | 4. View and copy the Hex, RGB, or HSV values of the selected color
70 |
71 | ## Contributing
72 | If you'd like to contribute to improving the project, please send a Pull Request. All forms of contribution are welcome!
73 |
74 | ## License
75 | This project is distributed under the MIT license. For more details, please refer to the [LICENSE](https://github.com/jamesnet214/colorpicker/blob/main/LICENSE) file.
76 |
77 | ## Contact
78 | - Website: https://jamesnet.dev
79 | - Email: james@jamesnet.dev, vickyqu115@hotmail.com
80 |
81 | Explore color manipulation techniques and apply them to your projects with ColorPicker!
82 |
--------------------------------------------------------------------------------
/README.zh-CN.md:
--------------------------------------------------------------------------------
1 | # ColorPicker [](README.md) [](README.zh-CN.md) [](README.ko.md)
2 |
3 | 一个面向开发者和设计师的实用工具,用于在 Windows 系统中捕获和操作颜色
4 |
5 | [](https://opensource.org/licenses/MIT)
6 | [](https://dotnet.microsoft.com/download)
7 | [](https://github.com/jamesnet214/colorpicker/stargazers)
8 | [](https://github.com/jamesnet214/colorpicker/issues)
9 |
10 | ## 项目概览
11 |
12 | ColorPicker 是一个 Windows 操作系统上的实用程序,允许用户轻松捕获所需的颜色或通过组合颜色提取十六进制值。它是开发者和设计师经常使用的工具,从简单的程序到专业软件如 Photoshop、Illustrator、MS Office 以及像 Visual Studio 这样的 IDE 中都可以找到它的身影。
13 |
14 |
15 |
16 |
17 | ## 关键技术与实现
18 |
19 | #### 1. 自定义控件开发
20 | - [x] 实现自定义 ColorWheel 和 ColorSlider 控件
21 | - [x] WPF 渲染技术的高级应用
22 |
23 | #### 2. MVVM 架构
24 | - [x] 全面实现 MVVM 模式和数据绑定优化
25 | - [x] 有效使用 RelayCommand 和 INotifyPropertyChanged 接口
26 |
27 | #### 3. 高级 WPF 技术
28 | - [x] 利用 Triggers 实现动态 UI 更新
29 | - [x] 实现带虚拟化的自定义 ItemsControl
30 | - [x] ControlTemplate 和 DataTemplate 的高级使用
31 |
32 | #### 4. 颜色操作
33 | - [x] 不同颜色空间(RGB、HSV、Hex)之间的实时颜色转换
34 | - [x] 屏幕颜色捕获功能
35 |
36 | #### 5. 性能优化
37 | - [x] 高效渲染色轮和滑块
38 | - [x] 即使在快速颜色变化时也能保持流畅的 UI 交互
39 |
40 | ## 技术栈
41 | - .NET 8.0
42 | - WPF (Windows Presentation Foundation)
43 | - MVVM (Model-View-ViewModel) 模式
44 |
45 | ## 入门指南
46 |
47 | ### 前提条件
48 | - Visual Studio 2022 或更高版本
49 | - .NET 8.0 SDK
50 |
51 | ### 安装和执行
52 |
53 | #### 1. 克隆仓库:
54 | ```
55 | git clone https://github.com/jamesnet214/colorpicker.git
56 | ```
57 |
58 | #### 2. 打开解决方案
59 | - [x] Visual Studio
60 | - [x] Visual Studio Code
61 | - [x] Jetbrains Rider
62 |
63 |
64 |
65 |
66 |
67 | #### 3. 构建和运行
68 | - [x] 推荐 Windows 11
69 |
70 | ## 使用方法
71 | 1. 启动 ColorPicker 应用程序
72 | 2. 使用色轮或滑块选择颜色
73 | 3. 使用吸管工具从屏幕上捕获颜色
74 | 4. 查看并复制所选颜色的十六进制、RGB 或 HSV 值
75 |
76 | ## 贡献
77 | 如果您想为改进项目做出贡献,请发送 Pull Request。我们欢迎任何形式的贡献!
78 |
79 | ## 许可证
80 | 本项目采用 MIT 许可证分发。有关更多详细信息,请参阅 [LICENSE](https://github.com/jamesnet214/colorpicker/blob/main/LICENSE) 文件。
81 |
82 | ## 联系方式
83 | - 网站:https://jamesnet.dev
84 | - 电子邮件:james@jamesnet.dev, vickyqu115@hotmail.com
85 |
86 | 使用 ColorPicker 探索颜色操作技术,并将其应用到您的项目中!
87 |
--------------------------------------------------------------------------------
/src/ColorPicker.Forms/ColorPicker.Forms.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0-windows
5 | disable
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | $(DefaultXamlRuntime)
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/ColorPicker.Forms/Local/ViewModels/ColorPickerViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.Input;
2 | using Jamesnet.Wpf.Controls;
3 | using Jamesnet.Wpf.Mvvm;
4 | using Prism.Ioc;
5 | using Prism.Regions;
6 | using System;
7 | using System.Windows;
8 | using System.Windows.Input;
9 | using System.Windows.Media.Imaging;
10 |
11 | namespace ColorPicker.Forms.Local.ViewModels
12 | {
13 | public class ColorPickerViewModel : ObservableBase, IViewLoadable
14 | {
15 | private readonly IContainerProvider _containerProvider;
16 | private readonly IRegionManager _regionManager;
17 |
18 | public ColorPickerViewModel(IContainerProvider containerProvider, IRegionManager regionManager)
19 | {
20 | _containerProvider = containerProvider;
21 | _regionManager = regionManager;
22 | }
23 |
24 | public void OnLoaded(IViewable view)
25 | {
26 | IViewable mainContent = _containerProvider.Resolve("MainContent");
27 | IRegion mainRegion = _regionManager.Regions["MainRegion"];
28 |
29 | if (!mainRegion.Views.Contains(mainContent))
30 | {
31 | mainRegion.Add(mainContent);
32 | }
33 | mainRegion.Activate(mainContent);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ColorPicker.Forms/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Windows;
3 |
4 | [assembly: ThemeInfo(
5 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
6 | //(used if a resource is not found in the page,
7 | // or application resource dictionaries)
8 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
9 | //(used if a resource is not found in the page,
10 | // app, or any theme specific resource dictionaries)
11 | )]
12 |
--------------------------------------------------------------------------------
/src/ColorPicker.Forms/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/ColorPicker.Forms/Themes/Views/PaletteWindow.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
21 |
22 |
35 |
36 |
--------------------------------------------------------------------------------
/src/ColorPicker.Forms/UI/Views/ColorPickerWindow.cs:
--------------------------------------------------------------------------------
1 | using Jamesnet.Wpf.Controls;
2 | using System.Windows;
3 |
4 | namespace ColorPicker.Forms.UI.Views
5 | {
6 | public class PaletteWindow : DarkThemeWindow
7 | {
8 | static PaletteWindow()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(PaletteWindow), new FrameworkPropertyMetadata(typeof(PaletteWindow)));
11 | }
12 |
13 | public PaletteWindow()
14 | {
15 | Width = 500;
16 | Height = 400;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/ColorPicker.Main.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0-windows
5 | disable
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | $(DefaultXamlRuntime)
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/Local/ViewModels/MainContentViewModel.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Support.Local.Config;
2 | using ColorPicker.Support.Local.Models;
3 | using ColorPicker.Support.Local.Worker;
4 | using CommunityToolkit.Mvvm.ComponentModel;
5 | using CommunityToolkit.Mvvm.Input;
6 | using Jamesnet.Wpf.Controls;
7 | using System;
8 | using System.Windows;
9 | using System.Windows.Input;
10 | using System.Windows.Media.Imaging;
11 |
12 | namespace ColorPicker.Main.Local.ViewModels
13 | {
14 | public partial class MainContentViewModel : ObservableObject, IViewLoadable
15 | {
16 | private bool _isCaptureActivated;
17 | private readonly PixelExtractWorker _captureWorker;
18 |
19 | [ObservableProperty]
20 | private BitmapSource _captureImage;
21 |
22 | [ObservableProperty]
23 | private bool _isColorCapturing;
24 |
25 | [ObservableProperty]
26 | private string _currentColor;
27 |
28 | [ObservableProperty]
29 | private string _reverseColor;
30 |
31 | [ObservableProperty]
32 | private string _contrastColor;
33 |
34 | [ObservableProperty]
35 | private int _red;
36 |
37 | [ObservableProperty]
38 |
39 | private int _green;
40 |
41 | [ObservableProperty]
42 | private int _blue;
43 |
44 | [ObservableProperty]
45 | public int _alpha = 255;
46 |
47 | public ExtractedColorCollection ExtractedColorSet { get; set; }
48 |
49 | public MainContentViewModel()
50 | {
51 | ExtractedColorSet = new ExtractedColorCollection();
52 |
53 | _captureWorker = new PixelExtractWorker
54 | {
55 | StartExtract = ExtractColor,
56 | FinishExtract = () => IsColorCapturing = false
57 | };
58 |
59 | ColorStruct color = ConvertColor.Parse("#ffffffff");
60 |
61 | if (color.Blue < 128)
62 | {
63 | _ = color.SetAddBlue(128);
64 | for (int i = 0; i < 64; i++)
65 | {
66 | ExtractColor(color.SetAddBlue(-2));
67 | }
68 | }
69 | else
70 | {
71 | _ = color.SetAddBlue(-128);
72 | for (int i = 0; i < 64; i++)
73 | {
74 | ExtractColor(color.SetAddBlue(2));
75 | }
76 | }
77 | }
78 |
79 | public void OnLoaded(IViewable view)
80 | {
81 | FrameworkElement fe = (FrameworkElement)view;
82 | Window.GetWindow(fe).Closed += (s, e) =>
83 | {
84 | ColorConfig.SaveSpoidColor(CurrentColor);
85 | Window.GetWindow(fe).Close();
86 | };
87 | }
88 |
89 | [RelayCommand]
90 | private void ColorClick(ColorStampModel color)
91 | {
92 | if (color != null)
93 | {
94 | ExtractColor(new ColorStruct(color.Red, color.Green, color.Blue, (byte)255));
95 | }
96 | }
97 |
98 | [RelayCommand]
99 | private void Capture(object obj)
100 | {
101 | IsColorCapturing = true;
102 | _captureWorker.Begin();
103 | }
104 |
105 | [RelayCommand]
106 | private void Paste(object obj)
107 | {
108 | if (obj is "COPY")
109 | {
110 | System.Windows.Clipboard.SetText(CurrentColor);
111 | }
112 | }
113 |
114 | [RelayCommand]
115 | private void Minimize(object ui)
116 | {
117 | Window.GetWindow((UIElement)ui).WindowState = WindowState.Minimized;
118 | }
119 |
120 | private void ExtractColor(ColorStruct rgba)
121 | {
122 | _isCaptureActivated = true;
123 |
124 | CurrentColor = ConvertColor.Hex(rgba);
125 | ReverseColor = ConvertColor.ReverseHex(rgba);
126 | ContrastColor = ConvertColor.Contrast(rgba);
127 |
128 | Red = rgba.Red;
129 | Green = rgba.Green;
130 | Blue = rgba.Blue;
131 |
132 | ExtractedColorSet.Insert(rgba);
133 |
134 | _isCaptureActivated = false;
135 | }
136 |
137 | [RelayCommand]
138 | partial void OnBlueChanged(int value)
139 | {
140 | RgbChanged();
141 | }
142 |
143 | [RelayCommand]
144 | partial void OnRedChanged(int value)
145 | {
146 | RgbChanged();
147 | }
148 |
149 | [RelayCommand]
150 | partial void OnGreenChanged(int value)
151 | {
152 | RgbChanged();
153 | }
154 |
155 | private void RgbChanged()
156 | {
157 | if (!_isCaptureActivated)
158 | {
159 | ExtractColor(new ColorStruct(Red, Green, Blue, Alpha));
160 | }
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Windows;
3 |
4 | [assembly: ThemeInfo(
5 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
6 | //(used if a resource is not found in the page,
7 | // or application resource dictionaries)
8 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
9 | //(used if a resource is not found in the page,
10 | // app, or any theme specific resource dictionaries)
11 | )]
12 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/Themes/Units/ColorBox.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 | M6.92,19L5,17.08L13.06,9L15,10.94M20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L13.84,6.41L11.91,4.5L10.5,5.91L11.92,7.33L3,16.25V21H7.75L16.67,12.08L18.09,13.5L19.5,12.09L17.58,10.17L20.7,7.05C21.1,6.65 21.1,6 20.71,5.63Z
7 | M19,20H5V4H7V7H17V4H19M12,2A1,1 0 0,1 13,3A1,1 0 0,1 12,4A1,1 0 0,1 11,3A1,1 0 0,1 12,2M19,2H14.82C14.4,0.84 13.3,0 12,0C10.7,0 9.6,0.84 9.18,2H5A2,2 0 0,0 3,4V20A2,2 0 0,0 5,22H19A2,2 0 0,0 21,20V4A2,2 0 0,0 19,2Z
8 |
9 |
25 |
26 |
43 |
44 |
91 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/Themes/Units/PaletteBox.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
30 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/Themes/Units/PaletteBoxItem.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
21 |
22 |
31 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/Themes/Views/MainContent.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
12 |
15 |
16 |
20 |
21 |
25 |
26 |
30 |
31 |
51 |
52 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/UI/Units/ColorBox.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace ColorPicker.Main.UI.Units
5 | {
6 | public class ColorBox : Control
7 | {
8 | #region DefaultStyleKey
9 |
10 | static ColorBox()
11 | {
12 | DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorBox), new FrameworkPropertyMetadata(typeof(ColorBox)));
13 | }
14 | #endregion
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/UI/Units/PaletteBox.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Input;
4 |
5 | namespace ColorPicker.Main.UI.Units
6 | {
7 | public class PaletteBox : ListBox
8 | {
9 | static PaletteBox()
10 | {
11 | DefaultStyleKeyProperty.OverrideMetadata(typeof(PaletteBox), new FrameworkPropertyMetadata(typeof(PaletteBox)));
12 | }
13 |
14 | public static readonly DependencyProperty SelectionCommandProperty = DependencyProperty.Register("SelectionCommand", typeof(ICommand), typeof(PaletteBox));
15 |
16 | protected override DependencyObject GetContainerForItemOverride()
17 | {
18 | return new PaletteBoxItem();
19 | }
20 |
21 | protected override void OnSelectionChanged(SelectionChangedEventArgs e)
22 | {
23 | base.OnSelectionChanged(e);
24 | SelectionCommand?.Execute(SelectedItem);
25 | }
26 |
27 | public ICommand SelectionCommand
28 | {
29 | get { return (ICommand)this.GetValue(SelectionCommandProperty); }
30 | set { this.SetValue(SelectionCommandProperty, value); }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/UI/Units/PaletteBoxItem.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace ColorPicker.Main.UI.Units
5 | {
6 | public class PaletteBoxItem : ListBoxItem
7 | {
8 | static PaletteBoxItem()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(PaletteBoxItem), new FrameworkPropertyMetadata(typeof(PaletteBoxItem)));
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ColorPicker.Main/UI/Views/MainContent.cs:
--------------------------------------------------------------------------------
1 | using Jamesnet.Wpf.Controls;
2 | using System.Windows;
3 |
4 | namespace ColorPicker.Main.UI.Views
5 | {
6 | public class MainContent : JamesContent
7 | {
8 | static MainContent()
9 | {
10 | DefaultStyleKeyProperty.OverrideMetadata(typeof(MainContent), new FrameworkPropertyMetadata(typeof(MainContent)));
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ColorPicker.Sliders/ColorPicker.Sliders.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0-windows
5 | disable
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/ColorPicker.Sliders/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Windows;
3 |
4 | [assembly: ThemeInfo(
5 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
6 | //(used if a resource is not found in the page,
7 | // or application resource dictionaries)
8 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
9 | //(used if a resource is not found in the page,
10 | // app, or any theme specific resource dictionaries)
11 | )]
12 |
--------------------------------------------------------------------------------
/src/ColorPicker.Sliders/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/ColorPicker.Sliders/Themes/Units/ColorSlider.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
54 |
55 |
64 |
65 |
126 |
--------------------------------------------------------------------------------
/src/ColorPicker.Sliders/UI/Units/ColorSlider.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Controls.Primitives;
4 | using System.Windows.Input;
5 |
6 | namespace ColorPicker.Sliders.UI.Units
7 | {
8 | public class ColorSlider : Slider
9 | {
10 | static ColorSlider()
11 | {
12 | DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorSlider), new FrameworkPropertyMetadata(typeof(ColorSlider)));
13 | }
14 |
15 | public ColorSlider()
16 | {
17 | Loaded += ColorSlider_Loaded;
18 | }
19 |
20 | private void ColorSlider_Loaded(object sender, RoutedEventArgs e)
21 | {
22 | Thumb thumb = (this.Template.FindName("PART_Track", this) as Track).Thumb;
23 | thumb.MouseEnter += new MouseEventHandler(Thumb_MouseEnter);
24 | }
25 |
26 | private void Thumb_MouseEnter(object sender, MouseEventArgs e)
27 | {
28 | if (e.LeftButton == MouseButtonState.Pressed
29 | && e.MouseDevice.Captured == null)
30 | {
31 | MouseButtonEventArgs args = new(e.MouseDevice, e.Timestamp, MouseButton.Left);
32 | args.RoutedEvent = MouseLeftButtonDownEvent;
33 | (sender as Thumb).RaiseEvent(args);
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/ColorPicker.Support.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0-windows
5 | disable
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Config/ColorConfig.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Support.Local.Models;
2 | using System;
3 | using System.IO;
4 | using System.Linq;
5 |
6 | namespace ColorPicker.Support.Local.Config
7 | {
8 | public class ColorConfig
9 | {
10 | public static string WIN_PATH { get; }
11 | public static string SYS_PATH { get; }
12 | public static string CFG_PATH { get; }
13 | public static ConfigModel Config { get; private set; }
14 |
15 | static ColorConfig()
16 | {
17 | WIN_PATH = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
18 | SYS_PATH = string.Format(@"{0}\ColorPicker\System", WIN_PATH);
19 | CFG_PATH = string.Format(@"{0}\Config.yaml", SYS_PATH);
20 |
21 | LoadConfigFile();
22 | }
23 |
24 | private static void LoadConfigFile()
25 | {
26 | if (!Directory.Exists(SYS_PATH))
27 | {
28 | _ = Directory.CreateDirectory(SYS_PATH);
29 | }
30 |
31 | if (!File.Exists(CFG_PATH))
32 | {
33 | SaveConfig(new ConfigModel());
34 | }
35 |
36 | //IDeserializer deserializer = new DeserializerBuilder()
37 | // .WithNamingConvention(CamelCaseNamingConvention.Instance)
38 | // .Build();
39 |
40 | //Config = deserializer.Deserialize(File.ReadAllText(CFG_PATH));
41 | }
42 |
43 | public static void SaveSpoidColor(string color)
44 | {
45 | Config.SpoidColor = color;
46 | SaveConfig(Config);
47 | }
48 |
49 | public static ConfigModel LoadConfig()
50 | {
51 | return Config;
52 | }
53 |
54 | public static void SaveLocation(int x, int y, int width, int height)
55 | {
56 | if (Config.ViewOptions.FirstOrDefault() is ViewOptionModel view)
57 | {
58 | view.LocX = x;
59 | view.LocY = y;
60 | view.Width = width;
61 | view.Height = height;
62 | }
63 | else
64 | {
65 | Config.ViewOptions.Add(new ViewOptionModel { LocX = x, LocY = y, Width = width, Height = height });
66 | }
67 |
68 | SaveConfig(Config);
69 | }
70 |
71 | private static void SaveConfig(ConfigModel config)
72 | {
73 | //ISerializer serializer = new SerializerBuilder()
74 | // .WithNamingConvention(CamelCaseNamingConvention.Instance)
75 | // .Build();
76 |
77 | //string yaml = serializer.Serialize(config);
78 |
79 | //File.WriteAllText(CFG_PATH, yaml);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Converters/EqualsToBooleanConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 | using System.Windows.Markup;
5 |
6 | namespace ColorPicker.Support.Local.Converters
7 | {
8 | public class EqualsToBooleanConverter : MarkupExtension, IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | return value.Equals("Transparent");
13 | }
14 |
15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
16 | {
17 | throw new NotImplementedException();
18 | }
19 |
20 | public override object ProvideValue(IServiceProvider serviceProvider)
21 | {
22 | return this;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Converters/RgbToHexConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 | using System.Windows.Markup;
5 |
6 | namespace ColorPicker.Support.Local.Converters
7 | {
8 | public class RgbToHexConverter : MarkupExtension, IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | string hex = "";
13 | int color = int.Parse(value.ToString());
14 |
15 | switch (parameter)
16 | {
17 | case "R": hex = $"#FF{color:X2}0000"; break;
18 | case "G": hex = $"#FF00{color:X2}00"; break;
19 | case "B": hex = $"#FF0000{color:X2}"; break;
20 | default:
21 | break;
22 | }
23 |
24 | return hex;
25 | }
26 |
27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
28 | {
29 | throw new NotImplementedException();
30 | }
31 |
32 | public override object ProvideValue(IServiceProvider serviceProvider)
33 | {
34 | return this;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Helpers/PixelExtractWorker.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Support.Local.Models;
2 | using Gma.System.MouseKeyHook;
3 | using System;
4 | using System.Drawing;
5 | using System.Windows.Input;
6 |
7 | namespace ColorPicker.Support.Local.Worker
8 | {
9 | public class PixelExtractWorker
10 | {
11 | // 임시 버퍼의 graphic 타입
12 | private readonly Bitmap buffer = new(1, 1);
13 | private readonly Graphics buffer_graphics = null;
14 | private int count = 0;
15 | private IKeyboardMouseEvents globalMouseHook;
16 | public Action StartExtract = (p) => { };
17 | public Action FinishExtract = () => { };
18 |
19 | public PixelExtractWorker()
20 | {
21 | buffer_graphics = Graphics.FromImage(buffer);
22 | }
23 |
24 | public void Begin()
25 | {
26 | BeginCapture();
27 | }
28 |
29 | private void BeginCapture()
30 | {
31 | globalMouseHook = Hook.GlobalEvents();
32 | globalMouseHook.MouseMove += MainWindow_MouseMove;
33 | globalMouseHook.MouseDown += GlobalMouseHook_MouseDown;
34 | Mouse.OverrideCursor = Cursors.Cross;
35 | }
36 |
37 | private void GlobalMouseHook_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
38 | {
39 | CaptureFinished();
40 | FinishExtract();
41 | }
42 |
43 | private void CaptureFinished()
44 | {
45 | globalMouseHook.MouseMove -= MainWindow_MouseMove;
46 | globalMouseHook.MouseDown -= GlobalMouseHook_MouseDown;
47 | globalMouseHook.Dispose();
48 | Mouse.OverrideCursor = null;
49 | }
50 |
51 | private void MainWindow_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
52 | {
53 | SetView(e.X, e.Y);
54 | }
55 |
56 | private void SetView(int x, int y)
57 | {
58 | if (count > 3)
59 | {
60 | count = 0;
61 | ColorStruct color = new(ScreenColor(x, y));
62 | StartExtract(color);
63 | }
64 | else
65 | {
66 | count++;
67 | }
68 | }
69 |
70 | private Color ScreenColor(int x, int y)
71 | {
72 | // Mouse 위치의 색을 추출한다.
73 | buffer_graphics.CopyFromScreen(x, y, 0, 0, new Size(1, 1));
74 | // Pixel 값을 리턴한다.
75 | return buffer.GetPixel(0, 0);
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Models/ColorStampModel.cs:
--------------------------------------------------------------------------------
1 | namespace ColorPicker.Support.Local.Models
2 | {
3 | public class ColorStampModel
4 | {
5 |
6 | public string HexColor { get; set; }
7 | public byte Red { get; set; }
8 | public byte Green { get; set; }
9 | public byte Blue { get; set; }
10 |
11 | public ColorStampModel(ColorStruct rgba)
12 | {
13 | HexColor = ConvertColor.Hex(rgba);
14 | Red = rgba.Red;
15 | Green = rgba.Green;
16 | Blue = rgba.Blue;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Models/ColorStruct.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace ColorPicker.Support.Local.Models
4 | {
5 | public struct ColorStruct
6 | {
7 | public byte Red { get; set; }
8 | public byte Green { get; set; }
9 | public byte Blue { get; set; }
10 | public byte Alpha { get; set; }
11 |
12 | public ColorStruct(byte red, byte green, byte blue, byte alpha)
13 | {
14 | Red = red;
15 | Green = green;
16 | Blue = blue;
17 | Alpha = alpha;
18 | }
19 | public ColorStruct(int red, int green, int blue, int alpha)
20 | {
21 | Red = (byte)red;
22 | Green = (byte)green;
23 | Blue = (byte)blue;
24 | Alpha = (byte)alpha;
25 | }
26 |
27 | public ColorStruct(Color color)
28 | {
29 | Red = color.R;
30 | Green = color.G;
31 | Blue = color.B;
32 | Alpha = color.A;
33 | }
34 |
35 | public ColorStruct SetAddBlue(int value)
36 | {
37 | Blue = (byte)(Blue + value);
38 | return this;
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Models/ConfigModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace ColorPicker.Support.Local.Models
4 | {
5 | public class ConfigModel
6 | {
7 | public List ViewOptions { get; set; }
8 | public string SpoidColor { get; set; } = "#FFFFFFFF";
9 |
10 | public ConfigModel()
11 | {
12 | ViewOptions = new List();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Models/ConverterColor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 |
4 | namespace ColorPicker.Support.Local.Models
5 | {
6 | public static class ConvertColor
7 | {
8 | #region Parse
9 |
10 | public static ColorStruct Parse(string hex)
11 | {
12 | hex = hex.Replace("#", "");
13 | byte[] data = Enumerable.Range(0, hex.Length)
14 | .Where(x => x % 2 == 0)
15 | .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
16 | .ToArray();
17 |
18 | ColorStruct color = new ColorStruct
19 | {
20 | Red = data[1],
21 | Green = data[2],
22 | Blue = data[3],
23 | Alpha = data[0]
24 | };
25 | return color;
26 | }
27 | #endregion
28 |
29 | #region Hex
30 | public static string Hex(ColorStruct rgba)
31 | {
32 | string r = rgba.Red.ToString("X2");
33 | string g = rgba.Green.ToString("X2");
34 | string b = rgba.Blue.ToString("X2");
35 | string a = rgba.Alpha.ToString("X2");
36 |
37 | return $"#{a}{r}{g}{b}";
38 | }
39 | #endregion
40 |
41 | #region ReverseHex
42 |
43 | public static string ReverseHex(ColorStruct rgba)
44 | {
45 | byte max = 255;
46 |
47 | string xr = ((byte)(max - rgba.Red)).ToString("X2");
48 | string xg = ((byte)(max - rgba.Green)).ToString("X2");
49 | string xb = ((byte)(max - rgba.Blue)).ToString("X2");
50 | return $"#FF{xr}{xg}{xb}";
51 | }
52 | #endregion
53 |
54 | #region Contrast
55 |
56 | public static string Contrast(ColorStruct rgba, int standard = 142)
57 | {
58 | string reverse = "#FFFFFFFF";
59 | if (((rgba.Red * 0.299) + (rgba.Green * 0.587) + (rgba.Blue * 0.114)) > standard)
60 | {
61 | reverse = "#FF000000";
62 | }
63 | return reverse;
64 | }
65 | #endregion
66 | }
67 | }
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Models/ExtractedColorCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 | using System.Linq;
3 |
4 | namespace ColorPicker.Support.Local.Models
5 | {
6 | public class ExtractedColorCollection : ObservableCollection
7 | {
8 | public void Insert(ColorStruct rgba)
9 | {
10 | if (this.FirstOrDefault(x => x.HexColor == ConvertColor.Hex(rgba)) is null)
11 | {
12 | Insert(0, new ColorStampModel(rgba));
13 | }
14 | RemoveLast();
15 | }
16 |
17 | private void RemoveLast()
18 | {
19 | if (Count > 65)
20 | {
21 | RemoveAt(Count - 1);
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Local/Models/ViewOptionModel.cs:
--------------------------------------------------------------------------------
1 | namespace ColorPicker.Support.Local.Models
2 | {
3 | public class ViewOptionModel
4 | {
5 | public int LocX { get; set; }
6 | public int LocY { get; set; }
7 | public int Width { get; set; }
8 | public int Height { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Windows;
3 |
4 | [assembly: ThemeInfo(
5 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
6 | //(used if a resource is not found in the page,
7 | // or application resource dictionaries)
8 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
9 | //(used if a resource is not found in the page,
10 | // app, or any theme specific resource dictionaries)
11 | )]
12 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/Themes/Generic.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/ColorPicker.Support/UI/Units/GeometryIcon.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Media;
4 |
5 | namespace ColorPicker.Support.UI.Units
6 | {
7 | public class GeometryIcon : ContentControl
8 | {
9 | public static readonly DependencyProperty FillProperty = DependencyProperty.Register("Fill", typeof(Brush), typeof(GeometryIcon), new PropertyMetadata(null));
10 |
11 | public Brush Fill
12 | {
13 | get => (Brush)GetValue(FillProperty);
14 | set => SetValue(FillProperty, value);
15 | }
16 |
17 | static GeometryIcon()
18 | {
19 | DefaultStyleKeyProperty.OverrideMetadata(typeof(GeometryIcon), new FrameworkPropertyMetadata(typeof(GeometryIcon)));
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ColorPicker.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31612.314
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorPicker", "ColorPicker\ColorPicker.csproj", "{D962A1F7-E6AB-4624-852D-F6B07ECCAF87}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Partial", "Partial", "{7BA6EA92-D899-4C83-A4B7-D670A04A5570}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorPicker.Forms", "ColorPicker.Forms\ColorPicker.Forms.csproj", "{903FBAFE-34EF-490F-95B9-0AC150A95C88}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Studio", "Studio", "{446F929A-9DF5-4F59-9F54-183DAD5DE8EC}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorPicker.Main", "ColorPicker.Main\ColorPicker.Main.csproj", "{9A721525-829E-4B0B-8DAC-CF9FFDB060A9}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPicker.Support", "ColorPicker.Support\ColorPicker.Support.csproj", "{60949185-5CD5-4B5F-96D0-325491F9562B}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Based", "Based", "{083CFCCC-1169-43B8-B15E-80CBFAAEA461}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPicker.Sliders", "ColorPicker.Sliders\ColorPicker.Sliders.csproj", "{2D10A01C-DFD8-4666-B3ED-8DFD6F6F87B8}"
21 | EndProject
22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Controls", "Controls", "{0DBD1038-4777-4D5A-B550-CD1C78B48FE3}"
23 | EndProject
24 | Global
25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
26 | Debug|Any CPU = Debug|Any CPU
27 | Release|Any CPU = Release|Any CPU
28 | EndGlobalSection
29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
30 | {D962A1F7-E6AB-4624-852D-F6B07ECCAF87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {D962A1F7-E6AB-4624-852D-F6B07ECCAF87}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {D962A1F7-E6AB-4624-852D-F6B07ECCAF87}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {D962A1F7-E6AB-4624-852D-F6B07ECCAF87}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {903FBAFE-34EF-490F-95B9-0AC150A95C88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {903FBAFE-34EF-490F-95B9-0AC150A95C88}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {903FBAFE-34EF-490F-95B9-0AC150A95C88}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {903FBAFE-34EF-490F-95B9-0AC150A95C88}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {9A721525-829E-4B0B-8DAC-CF9FFDB060A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {9A721525-829E-4B0B-8DAC-CF9FFDB060A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {9A721525-829E-4B0B-8DAC-CF9FFDB060A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {9A721525-829E-4B0B-8DAC-CF9FFDB060A9}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {60949185-5CD5-4B5F-96D0-325491F9562B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {60949185-5CD5-4B5F-96D0-325491F9562B}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {60949185-5CD5-4B5F-96D0-325491F9562B}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {60949185-5CD5-4B5F-96D0-325491F9562B}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {2D10A01C-DFD8-4666-B3ED-8DFD6F6F87B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {2D10A01C-DFD8-4666-B3ED-8DFD6F6F87B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {2D10A01C-DFD8-4666-B3ED-8DFD6F6F87B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {2D10A01C-DFD8-4666-B3ED-8DFD6F6F87B8}.Release|Any CPU.Build.0 = Release|Any CPU
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | GlobalSection(NestedProjects) = preSolution
55 | {D962A1F7-E6AB-4624-852D-F6B07ECCAF87} = {446F929A-9DF5-4F59-9F54-183DAD5DE8EC}
56 | {903FBAFE-34EF-490F-95B9-0AC150A95C88} = {7BA6EA92-D899-4C83-A4B7-D670A04A5570}
57 | {9A721525-829E-4B0B-8DAC-CF9FFDB060A9} = {7BA6EA92-D899-4C83-A4B7-D670A04A5570}
58 | {60949185-5CD5-4B5F-96D0-325491F9562B} = {083CFCCC-1169-43B8-B15E-80CBFAAEA461}
59 | {2D10A01C-DFD8-4666-B3ED-8DFD6F6F87B8} = {0DBD1038-4777-4D5A-B550-CD1C78B48FE3}
60 | EndGlobalSection
61 | GlobalSection(ExtensibilityGlobals) = postSolution
62 | SolutionGuid = {1E74BECC-4B8C-41D3-94D6-CD4172657022}
63 | EndGlobalSection
64 | EndGlobal
65 |
--------------------------------------------------------------------------------
/src/ColorPicker/App.cs:
--------------------------------------------------------------------------------
1 |
2 | using ColorPicker.Forms.UI.Views;
3 | using Jamesnet.Wpf.Controls;
4 | using Prism.Ioc;
5 | using System.Windows;
6 | using Unity;
7 |
8 | namespace ColorPicker
9 | {
10 | public class App : JamesApplication
11 | {
12 | protected override Window CreateShell()
13 | {
14 | return Container.Resolve();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ColorPicker/ColorPicker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net8.0-windows
6 | enable
7 | true
8 | Images\logo.ico
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/ColorPicker/Images/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesnetGroup/colorpicker/45620cbda814da65777a9ebbbcd0cb39ac1b0690/src/ColorPicker/Images/logo.ico
--------------------------------------------------------------------------------
/src/ColorPicker/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/src/ColorPicker/Properties/ViewModules.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Forms.UI.Views;
2 | using ColorPicker.Main.UI.Views;
3 | using Jamesnet.Wpf.Controls;
4 | using Prism.Ioc;
5 | using Prism.Modularity;
6 | using Prism.Regions;
7 |
8 | namespace ColorPicker.Properties
9 | {
10 | internal class ViewModules : IModule
11 | {
12 | public void OnInitialized(IContainerProvider containerProvider)
13 | {
14 | }
15 |
16 | public void RegisterTypes(IContainerRegistry containerRegistry)
17 | {
18 | containerRegistry.RegisterSingleton("MainContent");
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/ColorPicker/Properties/WireDataContext.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Forms.Local.ViewModels;
2 | using ColorPicker.Forms.UI.Views;
3 | using ColorPicker.Main.Local.ViewModels;
4 | using ColorPicker.Main.UI.Views;
5 | using Jamesnet.Wpf.Global.Location;
6 |
7 | namespace ColorPicker.Properties
8 | {
9 | internal class WireDataContext : ViewModelLocationScenario
10 | {
11 | protected override void Match(ViewModelLocatorCollection items)
12 | {
13 | items.Register();
14 | items.Register();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ColorPicker/Starter.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Properties;
2 | using System;
3 |
4 | namespace ColorPicker
5 | {
6 | internal class Starter
7 | {
8 | [STAThread]
9 | private static void Main(string[] args)
10 | {
11 | _ = new App()
12 | .AddWireDataContext()
13 | .AddInversionModule()
14 | .Run();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/_ColorPicker/App.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.UI.Views;
2 | using System.Windows;
3 |
4 | namespace ColorPicker
5 | {
6 | public class App : Application
7 | {
8 | protected override void OnStartup(StartupEventArgs e)
9 | {
10 | base.OnStartup(e);
11 | var win = new MainWindow();
12 |
13 | win.ShowDialog();
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/_ColorPicker/ColorPicker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net6.0-windows
6 | enable
7 | true
8 | true
9 | Properties\colorpicker.ico
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | $(DefaultXamlRuntime)
33 | Designer
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Config/ColorConfig.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Local.Data;
2 | using System;
3 | using System.IO;
4 | using System.Linq;
5 |
6 | namespace ColorPicker.Local.Config
7 | {
8 | public class ColorConfig
9 | {
10 | public static string WIN_PATH { get; }
11 | public static string SYS_PATH { get; }
12 | public static string CFG_PATH { get; }
13 | public static ConfigModel Config { get; private set; }
14 |
15 | static ColorConfig()
16 | {
17 | WIN_PATH = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
18 | SYS_PATH = string.Format(@"{0}\ColorPicker\System", WIN_PATH);
19 | CFG_PATH = string.Format(@"{0}\Config.yaml", SYS_PATH);
20 |
21 | LoadConfigFile();
22 | }
23 |
24 | private static void LoadConfigFile()
25 | {
26 | if (!Directory.Exists(SYS_PATH))
27 | {
28 | _ = Directory.CreateDirectory(SYS_PATH);
29 | }
30 |
31 | if (!File.Exists(CFG_PATH))
32 | {
33 | SaveConfig(new ConfigModel());
34 | }
35 |
36 | //IDeserializer deserializer = new DeserializerBuilder()
37 | // .WithNamingConvention(CamelCaseNamingConvention.Instance)
38 | // .Build();
39 |
40 | //Config = deserializer.Deserialize(File.ReadAllText(CFG_PATH));
41 | }
42 |
43 | public static void SaveSpoidColor(string color)
44 | {
45 | Config.SpoidColor = color;
46 | SaveConfig(Config);
47 | }
48 |
49 | public static ConfigModel LoadConfig()
50 | {
51 | return Config;
52 | }
53 |
54 | public static void SaveLocation(int x, int y, int width, int height)
55 | {
56 | if (Config.ViewOptions.FirstOrDefault() is ViewOptionModel view)
57 | {
58 | view.LocX = x;
59 | view.LocY = y;
60 | view.Width = width;
61 | view.Height = height;
62 | }
63 | else
64 | {
65 | Config.ViewOptions.Add(new ViewOptionModel { LocX = x, LocY = y, Width = width, Height = height });
66 | }
67 |
68 | SaveConfig(Config);
69 | }
70 |
71 | private static void SaveConfig(ConfigModel config)
72 | {
73 | //ISerializer serializer = new SerializerBuilder()
74 | // .WithNamingConvention(CamelCaseNamingConvention.Instance)
75 | // .Build();
76 |
77 | //string yaml = serializer.Serialize(config);
78 |
79 | //File.WriteAllText(CFG_PATH, yaml);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Converter/EqualsToBooleanConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 | using System.Windows.Markup;
5 |
6 | namespace ColorPicker.Local.Converter
7 | {
8 | public class EqualsToBooleanConverter : MarkupExtension, IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | return value.Equals("Transparent");
13 | }
14 |
15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
16 | {
17 | throw new NotImplementedException();
18 | }
19 |
20 | public override object ProvideValue(IServiceProvider serviceProvider)
21 | {
22 | return this;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Converter/RgbToHexConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 | using System.Windows.Markup;
5 |
6 | namespace ColorPicker.Local.Converter
7 | {
8 | public class RgbToHexConverter : MarkupExtension, IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | string hex = "";
13 | int color = int.Parse(value.ToString());
14 |
15 | switch (parameter)
16 | {
17 | case "R": hex = $"#FF{color:X2}0000"; break;
18 | case "G": hex = $"#FF00{color:X2}00"; break;
19 | case "B": hex = $"#FF0000{color:X2}"; break;
20 | default:
21 | break;
22 | }
23 |
24 | return hex;
25 | }
26 |
27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
28 | {
29 | throw new NotImplementedException();
30 | }
31 |
32 | public override object ProvideValue(IServiceProvider serviceProvider)
33 | {
34 | return this;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Data/ColorStampModel.cs:
--------------------------------------------------------------------------------
1 | namespace ColorPicker.Local.Data
2 | {
3 | public class ColorStampModel
4 | {
5 |
6 | public string HexColor { get; set; }
7 | public byte Red { get; set; }
8 | public byte Green { get; set; }
9 | public byte Blue { get; set; }
10 |
11 | public ColorStampModel(ColorStruct rgba)
12 | {
13 | HexColor = ConvertColor.Hex(rgba);
14 | Red = rgba.Red;
15 | Green = rgba.Green;
16 | Blue = rgba.Blue;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Data/ColorStruct.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace ColorPicker.Local.Data
4 | {
5 | public struct ColorStruct
6 | {
7 | public byte Red { get; set; }
8 | public byte Green { get; set; }
9 | public byte Blue { get; set; }
10 | public byte Alpha { get; set; }
11 |
12 | public ColorStruct(byte red, byte green, byte blue, byte alpha)
13 | {
14 | Red = red;
15 | Green = green;
16 | Blue = blue;
17 | Alpha = alpha;
18 | }
19 | public ColorStruct(int red, int green, int blue, int alpha)
20 | {
21 | Red = (byte)red;
22 | Green = (byte)green;
23 | Blue = (byte)blue;
24 | Alpha = (byte)alpha;
25 | }
26 |
27 | public ColorStruct(Color color)
28 | {
29 | Red = color.R;
30 | Green = color.G;
31 | Blue = color.B;
32 | Alpha = color.A;
33 | }
34 |
35 | public ColorStruct SetAddBlue(int value)
36 | {
37 | Blue = (byte)(Blue + value);
38 | return this;
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Data/ConfigModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace ColorPicker.Local.Data
4 | {
5 | public class ConfigModel
6 | {
7 | public List ViewOptions { get; set; }
8 | public string SpoidColor { get; set; } = "#FFFFFFFF";
9 |
10 | public ConfigModel()
11 | {
12 | ViewOptions = new List();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Data/ConverterColor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 |
4 | namespace ColorPicker.Local.Data
5 | {
6 | public static class ConvertColor
7 | {
8 | #region Parse
9 |
10 | public static ColorStruct Parse(string hex)
11 | {
12 | hex = hex.Replace("#", "");
13 | byte[] data = Enumerable.Range(0, hex.Length)
14 | .Where(x => x % 2 == 0)
15 | .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
16 | .ToArray();
17 |
18 | ColorStruct color = new ColorStruct
19 | {
20 | Red = data[1],
21 | Green = data[2],
22 | Blue = data[3],
23 | Alpha = data[0]
24 | };
25 | return color;
26 | }
27 | #endregion
28 |
29 | #region Hex
30 | public static string Hex(ColorStruct rgba)
31 | {
32 | string r = rgba.Red.ToString("X2");
33 | string g = rgba.Green.ToString("X2");
34 | string b = rgba.Blue.ToString("X2");
35 | string a = rgba.Alpha.ToString("X2");
36 |
37 | return $"#{a}{r}{g}{b}";
38 | }
39 | #endregion
40 |
41 | #region ReverseHex
42 |
43 | public static string ReverseHex(ColorStruct rgba)
44 | {
45 | byte max = 255;
46 |
47 | string xr = ((byte)(max - rgba.Red)).ToString("X2");
48 | string xg = ((byte)(max - rgba.Green)).ToString("X2");
49 | string xb = ((byte)(max - rgba.Blue)).ToString("X2");
50 | return $"#FF{xr}{xg}{xb}";
51 | }
52 | #endregion
53 |
54 | #region Contrast
55 |
56 | public static string Contrast(ColorStruct rgba, int standard = 142)
57 | {
58 | string reverse = "#FFFFFFFF";
59 | if (((rgba.Red * 0.299) + (rgba.Green * 0.587) + (rgba.Blue * 0.114)) > standard)
60 | {
61 | reverse = "#FF000000";
62 | }
63 | return reverse;
64 | }
65 | #endregion
66 | }
67 | }
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Data/ExtractedColorCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Collections.ObjectModel;
3 |
4 | namespace ColorPicker.Local.Data
5 | {
6 | public class ExtractedColorCollection : ObservableCollection
7 | {
8 | internal void Insert(ColorStruct rgba)
9 | {
10 | if (this.FirstOrDefault(x => x.HexColor == ConvertColor.Hex(rgba)) is null)
11 | {
12 | Insert(0, new ColorStampModel(rgba));
13 | }
14 | RemoveLast();
15 | }
16 |
17 | private void RemoveLast()
18 | {
19 | if (Count > 65)
20 | {
21 | RemoveAt(Count - 1);
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/Data/ViewOptionModel.cs:
--------------------------------------------------------------------------------
1 | namespace ColorPicker.Local.Data
2 | {
3 | public class ViewOptionModel
4 | {
5 | public int LocX { get; set; }
6 | public int LocY { get; set; }
7 | public int Width { get; set; }
8 | public int Height { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/_ColorPicker/Local/ViewModel/MainViewModel.cs:
--------------------------------------------------------------------------------
1 | using ColorPicker.Local.Config;
2 | using ColorPicker.Local.Data;
3 | using ColorPicker.Local.Worker;
4 | using DevNcore.UI.Foundation.Mvvm;
5 | using System;
6 | using System.Windows;
7 | using System.Windows.Input;
8 | using System.Windows.Media.Imaging;
9 |
10 | namespace ColorPicker.Local.ViewModel
11 | {
12 | public class MainViewModel : ObservableObject
13 | {
14 | #region Variables
15 |
16 | private int _red;
17 | private int _green;
18 | private int _blue;
19 | private string _currentColor;
20 | private string _reverseColor;
21 | private string _contrastColor;
22 | private bool _isColorCapturing;
23 |
24 | private BitmapSource _captureImage;
25 |
26 | private bool IsCaptureActivated;
27 | private readonly PixelExtractWorker Capture;
28 | #endregion
29 |
30 | #region Commands
31 |
32 | public ICommand MinimizeCommand { get; set; }
33 | public ICommand PasteCommand { get; }
34 | public ICommand CaptureCommand { get; }
35 | public ICommand ColorClickCommand { get; }
36 | #endregion
37 |
38 | #region CaptureImage
39 |
40 | public BitmapSource CaptureImage
41 | {
42 | get => _captureImage;
43 | set { _captureImage = value; OnPropertyChanged(); }
44 | }
45 | #endregion
46 |
47 | #region IsColorCapturing
48 |
49 | public bool IsColorCapturing
50 | {
51 | get => _isColorCapturing;
52 | set { _isColorCapturing = value; OnPropertyChanged(); }
53 | }
54 | #endregion
55 |
56 | #region CurrentColor
57 |
58 | public string CurrentColor
59 | {
60 | get => _currentColor;
61 | set { _currentColor = value; OnPropertyChanged(); }
62 | }
63 | #endregion
64 |
65 | #region ReverseColor
66 |
67 | public string ReverseColor
68 | {
69 | get => _reverseColor;
70 | set { _reverseColor = value; OnPropertyChanged(); }
71 | }
72 | #endregion
73 |
74 | #region ContrastColor
75 |
76 | public string ContrastColor
77 | {
78 | get => _contrastColor;
79 | set { _contrastColor = value; OnPropertyChanged(); }
80 | }
81 | #endregion
82 |
83 | #region Red
84 |
85 | public int Red
86 | {
87 | get => _red;
88 | set { _red = value; OnPropertyChanged(); RgbChanged(); }
89 | }
90 | #endregion
91 |
92 | #region Green
93 |
94 | public int Green
95 | {
96 | get => _green;
97 | set { _green = value; OnPropertyChanged(); RgbChanged(); }
98 | }
99 | #endregion
100 |
101 | #region Blue
102 |
103 | public int Blue
104 | {
105 | get => _blue;
106 | set { _blue = value; OnPropertyChanged(); RgbChanged(); }
107 | }
108 | #endregion
109 |
110 | #region Alpha
111 | public int Alpha { get; set; } = 255;
112 | #endregion
113 |
114 | #region ExtractedColorSet
115 |
116 | public ExtractedColorCollection ExtractedColorSet { get; set; }
117 | #endregion
118 |
119 | #region Constructor
120 |
121 | public MainViewModel()
122 | {
123 | ColorClickCommand = new RelayCommand(ColorSelected);
124 | CaptureCommand = new RelayCommand