├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Controls ├── CustomColorsRenderer.cs └── CustomComboBox.cs ├── Docs └── ToDo_Ideas.txt ├── Forms ├── DateForm.cs ├── DateForm.designer.cs ├── DateForm.resx ├── MessageForm.Designer.cs ├── MessageForm.cs ├── MessageForm.resx └── WeekNumberForDateForm.cs ├── IGui.cs ├── IconSize.cs ├── Installation ├── License.de-DE.txt ├── License.en-US.txt └── License.sv-SE.txt ├── LICENSE ├── Log.cs ├── Message.cs ├── NativeMethods.cs ├── Program.cs ├── Properties ├── App.config ├── AssemblyInfo.cs ├── WeekNumber.snk └── app.manifest ├── README.de-DE.md ├── README.md ├── README.sv-SE.md ├── Resources ├── Resources.Designer.cs ├── Resources.de-DE.Designer.cs ├── Resources.de-DE.resx ├── Resources.en-US.Designer.cs ├── Resources.en-US.resx ├── Resources.resx ├── Resources.sv-SE.Designer.cs ├── Resources.sv-SE.resx ├── WeekNumber.bmp ├── infoIconWhite.png └── weekicon.ico ├── SECURITY.md ├── Settings.cs ├── TaskbarGui.cs ├── TaskbarUtil.cs ├── Tools └── fart199b_win32.zip ├── Week.cs ├── WeekApplicationContext.cs ├── WeekIcon.cs ├── WeekNumber.csproj ├── WeekNumber.sln ├── WeekNumberContextMenu.cs ├── WeekNumberMonitor ├── AssemblyInfo.cs ├── Program.cs ├── WeekNumber.snk ├── WeekNumberMonitor.csproj └── app.config ├── _config.yml ├── app.config └── build.bat /.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 | ko_fi: voltura 2 | custom: ["https://www.paypal.me/voltura"] 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | 2 | # supported CodeQL languages. 3 | # 4 | name: "CodeQL" 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | # The branches below must be a subset of the branches above 11 | branches: [ master ] 12 | schedule: 13 | - cron: '23 18 * * 5' 14 | 15 | jobs: 16 | analyze: 17 | name: Analyze 18 | runs-on: windows-2019 19 | permissions: 20 | actions: write 21 | contents: write 22 | security-events: write 23 | 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | language: [ 'csharp' ] 28 | 29 | steps: 30 | - name: Checkout repository 31 | uses: actions/checkout@v2 32 | 33 | # Initializes the CodeQL tools for scanning. 34 | - name: Initialize CodeQL 35 | uses: github/codeql-action/init@v1 36 | with: 37 | languages: ${{ matrix.language }} 38 | # Add msbuild 39 | - name: Add msbuild to PATH 40 | uses: microsoft/setup-msbuild@v1.0.2 41 | with: 42 | vs-version: '[16.11,)' 43 | # make release 44 | 45 | - name: Release build 46 | run: msbuild WeekNumber.sln /p:Platform=x86 /property:Configuration=Release -m 47 | shell: cmd 48 | 49 | - name: Debug clean build 50 | run: msbuild WeekNumber.sln /t:rebuild 51 | 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | - name: Perform CodeQL Analysis 56 | uses: github/codeql-action/analyze@v1 57 | -------------------------------------------------------------------------------- /.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 | *.log 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Mono auto generated files 18 | mono_crash.* 19 | 20 | # Build results 21 | [Dd]ebug/ 22 | [Dd]ebugPublic/ 23 | [Rr]elease/ 24 | [Rr]eleases/ 25 | x64/ 26 | x86/ 27 | [Ww][Ii][Nn]32/ 28 | [Aa][Rr][Mm]/ 29 | [Aa][Rr][Mm]64/ 30 | bld/ 31 | [Bb]in/ 32 | [Oo]bj/ 33 | [Oo]ut/ 34 | [Ll]og/ 35 | [Ll]ogs/ 36 | 37 | # Visual Studio 2015/2017 cache/options directory 38 | .vs/ 39 | # Uncomment if you have tasks that create the project's static files in wwwroot 40 | #wwwroot/ 41 | 42 | # Visual Studio 2017 auto generated files 43 | Generated\ Files/ 44 | 45 | # MSTest test Results 46 | [Tt]est[Rr]esult*/ 47 | [Bb]uild[Ll]og.* 48 | 49 | # NUnit 50 | *.VisualState.xml 51 | TestResult.xml 52 | nunit-*.xml 53 | 54 | # Build Results of an ATL Project 55 | [Dd]ebugPS/ 56 | [Rr]eleasePS/ 57 | dlldata.c 58 | 59 | # Benchmark Results 60 | BenchmarkDotNet.Artifacts/ 61 | 62 | # .NET Core 63 | project.lock.json 64 | project.fragment.lock.json 65 | artifacts/ 66 | 67 | # ASP.NET Scaffolding 68 | ScaffoldingReadMe.txt 69 | 70 | # StyleCop 71 | StyleCopReport.xml 72 | 73 | # Files built by Visual Studio 74 | *_i.c 75 | *_p.c 76 | *_h.h 77 | *.ilk 78 | *.meta 79 | *.obj 80 | *.iobj 81 | *.pch 82 | *.pdb 83 | *.ipdb 84 | *.pgc 85 | *.pgd 86 | *.rsp 87 | *.sbr 88 | *.tlb 89 | *.tli 90 | *.tlh 91 | *.tmp 92 | *.tmp_proj 93 | *_wpftmp.csproj 94 | *.log 95 | *.vspscc 96 | *.vssscc 97 | .builds 98 | *.pidb 99 | *.svclog 100 | *.scc 101 | 102 | # Chutzpah Test files 103 | _Chutzpah* 104 | 105 | # Visual C++ cache files 106 | ipch/ 107 | *.aps 108 | *.ncb 109 | *.opendb 110 | *.opensdf 111 | *.sdf 112 | *.cachefile 113 | *.VC.db 114 | *.VC.VC.opendb 115 | 116 | # Visual Studio profiler 117 | *.psess 118 | *.vsp 119 | *.vspx 120 | *.sap 121 | 122 | # Visual Studio Trace Files 123 | *.e2e 124 | 125 | # TFS 2012 Local Workspace 126 | $tf/ 127 | 128 | # Guidance Automation Toolkit 129 | *.gpState 130 | 131 | # ReSharper is a .NET coding add-in 132 | _ReSharper*/ 133 | *.[Rr]e[Ss]harper 134 | *.DotSettings.user 135 | 136 | # TeamCity is a build add-in 137 | _TeamCity* 138 | 139 | # DotCover is a Code Coverage Tool 140 | *.dotCover 141 | 142 | # AxoCover is a Code Coverage Tool 143 | .axoCover/* 144 | !.axoCover/settings.json 145 | 146 | # Coverlet is a free, cross platform Code Coverage Tool 147 | coverage*.json 148 | coverage*.xml 149 | coverage*.info 150 | 151 | # Visual Studio code coverage results 152 | *.coverage 153 | *.coveragexml 154 | 155 | # NCrunch 156 | _NCrunch_* 157 | .*crunch*.local.xml 158 | nCrunchTemp_* 159 | 160 | # MightyMoose 161 | *.mm.* 162 | AutoTest.Net/ 163 | 164 | # Web workbench (sass) 165 | .sass-cache/ 166 | 167 | # Installshield output folder 168 | [Ee]xpress/ 169 | 170 | # DocProject is a documentation generator add-in 171 | DocProject/buildhelp/ 172 | DocProject/Help/*.HxT 173 | DocProject/Help/*.HxC 174 | DocProject/Help/*.hhc 175 | DocProject/Help/*.hhk 176 | DocProject/Help/*.hhp 177 | DocProject/Help/Html2 178 | DocProject/Help/html 179 | 180 | # Click-Once directory 181 | publish/ 182 | 183 | # Publish Web Output 184 | *.[Pp]ublish.xml 185 | *.azurePubxml 186 | # Note: Comment the next line if you want to checkin your web deploy settings, 187 | # but database connection strings (with potential passwords) will be unencrypted 188 | *.pubxml 189 | *.publishproj 190 | 191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 192 | # checkin your Azure Web App publish settings, but sensitive information contained 193 | # in these scripts will be unencrypted 194 | PublishScripts/ 195 | 196 | # NuGet Packages 197 | *.nupkg 198 | # NuGet Symbol Packages 199 | *.snupkg 200 | # The packages folder can be ignored because of Package Restore 201 | **/[Pp]ackages/* 202 | # except build/, which is used as an MSBuild target. 203 | !**/[Pp]ackages/build/ 204 | # Uncomment if necessary however generally it will be regenerated when needed 205 | #!**/[Pp]ackages/repositories.config 206 | # NuGet v3's project.json files produces more ignorable files 207 | *.nuget.props 208 | *.nuget.targets 209 | 210 | # Microsoft Azure Build Output 211 | csx/ 212 | *.build.csdef 213 | 214 | # Microsoft Azure Emulator 215 | ecf/ 216 | rcf/ 217 | 218 | # Windows Store app package directories and files 219 | AppPackages/ 220 | BundleArtifacts/ 221 | Package.StoreAssociation.xml 222 | _pkginfo.txt 223 | *.appx 224 | *.appxbundle 225 | *.appxupload 226 | 227 | # Visual Studio cache files 228 | # files ending in .cache can be ignored 229 | *.[Cc]ache 230 | # but keep track of directories ending in .cache 231 | !?*.[Cc]ache/ 232 | 233 | # Others 234 | ClientBin/ 235 | ~$* 236 | *~ 237 | *.dbmdl 238 | *.dbproj.schemaview 239 | *.jfm 240 | *.pfx 241 | *.publishsettings 242 | orleans.codegen.cs 243 | 244 | # Including strong name files can present a security risk 245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 246 | #*.snk 247 | 248 | # Since there are multiple workflows, uncomment next line to ignore bower_components 249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 250 | #bower_components/ 251 | 252 | # RIA/Silverlight projects 253 | Generated_Code/ 254 | 255 | # Backup & report files from converting an old project file 256 | # to a newer Visual Studio version. Backup files are not needed, 257 | # because we have git ;-) 258 | _UpgradeReport_Files/ 259 | Backup*/ 260 | UpgradeLog*.XML 261 | UpgradeLog*.htm 262 | ServiceFabricBackup/ 263 | *.rptproj.bak 264 | 265 | # SQL Server files 266 | *.mdf 267 | *.ldf 268 | *.ndf 269 | 270 | # Business Intelligence projects 271 | *.rdl.data 272 | *.bim.layout 273 | *.bim_*.settings 274 | *.rptproj.rsuser 275 | *- [Bb]ackup.rdl 276 | *- [Bb]ackup ([0-9]).rdl 277 | *- [Bb]ackup ([0-9][0-9]).rdl 278 | 279 | # Microsoft Fakes 280 | FakesAssemblies/ 281 | 282 | # GhostDoc plugin setting file 283 | *.GhostDoc.xml 284 | 285 | # Node.js Tools for Visual Studio 286 | .ntvs_analysis.dat 287 | node_modules/ 288 | 289 | # Visual Studio 6 build log 290 | *.plg 291 | 292 | # Visual Studio 6 workspace options file 293 | *.opt 294 | 295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 296 | *.vbw 297 | 298 | # Visual Studio LightSwitch build output 299 | **/*.HTMLClient/GeneratedArtifacts 300 | **/*.DesktopClient/GeneratedArtifacts 301 | **/*.DesktopClient/ModelManifest.xml 302 | **/*.Server/GeneratedArtifacts 303 | **/*.Server/ModelManifest.xml 304 | _Pvt_Extensions 305 | 306 | # Paket dependency manager 307 | .paket/paket.exe 308 | paket-files/ 309 | 310 | # FAKE - F# Make 311 | .fake/ 312 | 313 | # CodeRush personal settings 314 | .cr/personal 315 | 316 | # Python Tools for Visual Studio (PTVS) 317 | __pycache__/ 318 | *.pyc 319 | 320 | # Cake - Uncomment if you are using it 321 | # tools/** 322 | # !tools/packages.config 323 | 324 | # Tabs Studio 325 | *.tss 326 | 327 | # Telerik's JustMock configuration file 328 | *.jmconfig 329 | 330 | # BizTalk build output 331 | *.btp.cs 332 | *.btm.cs 333 | *.odx.cs 334 | *.xsd.cs 335 | 336 | # OpenCover UI analysis results 337 | OpenCover/ 338 | 339 | # Azure Stream Analytics local run output 340 | ASALocalRun/ 341 | 342 | # MSBuild Binary and Structured Log 343 | *.binlog 344 | 345 | # NVidia Nsight GPU debugger configuration file 346 | *.nvuser 347 | 348 | # MFractors (Xamarin productivity tool) working folder 349 | .mfractor/ 350 | 351 | # Local History for Visual Studio 352 | .localhistory/ 353 | 354 | # BeatPulse healthcheck temp database 355 | healthchecksdb 356 | 357 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 358 | MigrationBackup/ 359 | 360 | # Ionide (cross platform F# VS Code tools) working folder 361 | .ionide/ 362 | 363 | # Fody - auto-generated XML schema 364 | FodyWeavers.xsd 365 | /Tools/fart.exe 366 | GITHUB_ACCESS_TOKEN.bat 367 | CreateGithubRelease.bat 368 | /Tools/curl-7.76.1_2-win64-mingw.zip 369 | curl_examples.txt 370 | GITHUB_ACCESS_TOKEN.bat 371 | /Tools/curl-7.84.0_4-win64-mingw.zip 372 | release_info.txt 373 | /NSIS Installation/Plugins 374 | /NSIS Installation/CompileInstaller.bat 375 | /NSIS Installation/WeekNumber.nsi 376 | /Installation/CompileInstaller.bat 377 | /Installation/WeekNumber.nsi 378 | /Installation/Plugins 379 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | weeknumber@voltura.se. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Feel free to fork this branch and contribute to the application by modifications or additions to its logic, all merge requests will be evaluated and if deemed fit merged into the master branch/included in future release 2 | -------------------------------------------------------------------------------- /Controls/CustomColorsRenderer.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | #endregion 7 | 8 | namespace WeekNumber.Controls 9 | { 10 | /// 11 | /// Customize menu item selected colors 12 | /// 13 | public class CustomColorsRenderer : ToolStripProfessionalRenderer 14 | { 15 | #region Constructor 16 | 17 | /// 18 | /// Constructor 19 | /// 20 | public CustomColorsRenderer() : base(new CustomColors()) 21 | { 22 | } 23 | 24 | #endregion 25 | 26 | #region Private class 27 | 28 | private class CustomColors : ProfessionalColorTable 29 | { 30 | public override Color MenuItemSelected => Color.DeepSkyBlue; 31 | 32 | public override Color MenuItemSelectedGradientBegin => Color.DeepSkyBlue; 33 | 34 | public override Color MenuItemSelectedGradientEnd => Color.DeepSkyBlue; 35 | } 36 | 37 | #endregion 38 | } 39 | } -------------------------------------------------------------------------------- /Controls/CustomComboBox.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | #endregion 7 | 8 | namespace WeekNumber.Controls 9 | { 10 | /// 11 | /// Combobox with custom colors 12 | /// 13 | public class CustomComboBox : ComboBox 14 | { 15 | #region Public properties 16 | 17 | /// 18 | /// DrawMode 19 | /// 20 | public new DrawMode DrawMode { get; set; } 21 | 22 | /// 23 | /// Highlight color 24 | /// 25 | public Color HighlightColor { get; set; } 26 | 27 | #endregion 28 | 29 | #region Public constructor 30 | 31 | /// 32 | /// Constructor, sets highlight color 33 | /// 34 | public CustomComboBox() 35 | { 36 | base.DrawMode = DrawMode.OwnerDrawFixed; 37 | HighlightColor = Color.DeepSkyBlue; 38 | DrawItem += CustomComboBox_DrawItem; 39 | } 40 | 41 | #endregion 42 | 43 | #region Private methods 44 | 45 | private void CustomComboBox_DrawItem(object sender, DrawItemEventArgs e) 46 | { 47 | if (e.Index < 0) 48 | { 49 | return; 50 | } 51 | 52 | ComboBox combo = sender as ComboBox; 53 | if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) 54 | { 55 | using (SolidBrush brush = new SolidBrush(HighlightColor)) 56 | { 57 | e.Graphics.FillRectangle(brush, e.Bounds); 58 | } 59 | } 60 | else if (combo != null) 61 | { 62 | using (SolidBrush brush = new SolidBrush(combo.BackColor)) 63 | { 64 | e.Graphics.FillRectangle(brush, e.Bounds); 65 | } 66 | } 67 | 68 | if (combo != null) 69 | { 70 | using (SolidBrush brush = new SolidBrush(combo.ForeColor)) 71 | { 72 | e.Graphics.DrawString(combo.Items[e.Index].ToString(), e.Font, 73 | brush, new Point(e.Bounds.X, e.Bounds.Y)); 74 | } 75 | } 76 | 77 | e.DrawFocusRectangle(); 78 | } 79 | 80 | #endregion 81 | } 82 | } -------------------------------------------------------------------------------- /Docs/ToDo_Ideas.txt: -------------------------------------------------------------------------------- 1 | Application improvement ideas 2 | ============================= 3 | - Custom context menu colors for text and background (use contextmenustrip...) 4 | 5 | - When user activates notifications, make sure Windows settings are also updated to display notifications for WeekNumber by Voltura AB application 6 | suppression is stored in registry as well as a SquirrelSQL DB, need to get the GUID Windows assigns to the app, this could be used by querying the 7 | %LOCALAPPDATA%\Microsoft\Windows\Notifications\wpndatabase.db tables 8 | 1) Notification (query right after first app start and use HandlerId from row with Payload containing "WeekNumber by Voltura AB") 9 | 2) NotificationHandler, use key ID (HandlerID from 1), take Primary Id: Microsoft.Explorer.Notification.{GUID for registry use here} 10 | 3) Using PrimaryID .> save to settings 11 | 4) Remove suppression in registry when user activates messages in menu (or if show notifications setting is set during startup of app ) 12 | Reg path: 13 | Computer\HKEY_CURRENT_USER\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify\ToastAppIdentities\Microsoft.Explorer.Notification.{} 14 | Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.Explorer.Notification.{} 15 | Enabled dword 0 <- remove 16 | -------------------------------------------------------------------------------- /Forms/DateForm.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | #endregion 8 | 9 | namespace WeekNumber.Forms 10 | { 11 | /// 12 | /// Message form 13 | /// 14 | public partial class DateForm : Form 15 | { 16 | #region Private variables 17 | 18 | private Image _img; 19 | private bool _initComplete = false; 20 | 21 | #endregion Private variables 22 | 23 | #region Protected property 24 | 25 | /// 26 | /// Mouse location offset used form form movement 27 | /// 28 | protected Point Offset { get; set; } 29 | 30 | #endregion 31 | 32 | #region Private constructor 33 | 34 | private DateForm() 35 | { 36 | InitializeComponent(); 37 | StartPosition = FormStartPosition.CenterScreen; 38 | SetControlTexts(); 39 | } 40 | 41 | #endregion 42 | 43 | #region Public static method 44 | 45 | /// 46 | /// Displays Date form 47 | /// 48 | public static void Display() 49 | { 50 | using (DateForm dateForm = new DateForm()) 51 | { 52 | dateForm.ShowDialog(); 53 | } 54 | } 55 | 56 | #endregion 57 | 58 | #region Events handling 59 | 60 | private void Close_Click(object sender, EventArgs e) 61 | { 62 | DisposeImage(); 63 | Close(); 64 | } 65 | 66 | private void DisposeImage() 67 | { 68 | _img?.Dispose(); 69 | _img = pictureBoxWeek.Image; 70 | _img?.Dispose(); 71 | } 72 | 73 | private void SettingsTitle_MouseDown(object sender, MouseEventArgs e) 74 | { 75 | UpdateOffset(e); 76 | } 77 | 78 | private void SettingsTitle_MouseMove(object sender, MouseEventArgs e) 79 | { 80 | MoveForm(e); 81 | } 82 | 83 | private void MinimizePanel_MouseEnter(object sender, EventArgs e) 84 | { 85 | FocusMinimizeIcon(); 86 | } 87 | 88 | private void MinimizePanel_MouseLeave(object sender, EventArgs e) 89 | { 90 | UnfocusMinimizeIcon(); 91 | } 92 | 93 | private void MinimizePanel_Click(object sender, EventArgs e) 94 | { 95 | DisposeImage(); 96 | Close(); 97 | } 98 | 99 | private void MinimizePanelFrame_Click(object sender, EventArgs e) 100 | { 101 | DisposeImage(); 102 | Close(); 103 | } 104 | 105 | private void SelectedYearChanged(object sender, EventArgs e) 106 | { 107 | UpdateDaysDropdown(); 108 | UpdateWeekInfo(); 109 | } 110 | 111 | private void SelectedMonthChanged(object sender, EventArgs e) 112 | { 113 | UpdateDaysDropdown(); 114 | UpdateWeekInfo(); 115 | } 116 | 117 | private void SelectedDayChanged(object sender, EventArgs e) 118 | { 119 | UpdateWeekInfo(); 120 | } 121 | 122 | private void DateForm_Shown(object sender, EventArgs e) 123 | { 124 | _initComplete = true; 125 | } 126 | 127 | #endregion 128 | 129 | #region Private methods 130 | 131 | private void UpdateWeekInfo(bool initial = false) 132 | { 133 | if (!_initComplete && !initial) return; 134 | string weekDayPrefix = string.Empty; 135 | if (int.TryParse(ccbYear.SelectedItem?.ToString(), out int year) == true && 136 | int.TryParse(ccbMonth.SelectedItem?.ToString(), out int month) == true && 137 | int.TryParse(ccbDay.SelectedItem?.ToString(), out int day) == true) 138 | { 139 | DateTime selectedDate = new DateTime(year, month, day); 140 | if (System.Threading.Thread.CurrentThread.CurrentUICulture.Name == Resources.Swedish) 141 | { 142 | weekDayPrefix = Message.SWEDISH_DAY_OF_WEEK_PREFIX[(int)selectedDate.DayOfWeek]; 143 | } 144 | int selectedWeek = Week.GetWeekNumber(selectedDate); 145 | lblInformation.Text = $"{Resources.Week} {selectedWeek}\r\n{weekDayPrefix}{selectedDate.ToLongDateString()}"; 146 | _img = pictureBoxWeek.Image; 147 | pictureBoxWeek.Image = WeekIcon.GetImage(selectedWeek); 148 | _img?.Dispose(); 149 | } 150 | else if (initial) 151 | { 152 | if (System.Threading.Thread.CurrentThread.CurrentUICulture.Name == Resources.Swedish) 153 | { 154 | weekDayPrefix = Message.SWEDISH_DAY_OF_WEEK_PREFIX[(int)DateTime.Now.DayOfWeek]; 155 | } 156 | lblInformation.Text = $"{Resources.Week} {Week.Current()}\r\n{weekDayPrefix}{DateTime.Now.ToLongDateString()}"; 157 | pictureBoxWeek.Image = WeekIcon.GetImage(Week.Current()); 158 | } 159 | else 160 | { 161 | lblInformation.Text = Resources.SelectDate; 162 | pictureBoxWeek.Image = null; 163 | } 164 | } 165 | 166 | private void UpdateDaysDropdown() 167 | { 168 | 169 | if (int.TryParse(ccbYear.SelectedItem?.ToString(), out int year) == true && 170 | int.TryParse(ccbMonth.SelectedItem?.ToString(), out int month) == true) 171 | { 172 | bool gotPreviousSelectedDay = int.TryParse(ccbDay.SelectedItem?.ToString(), out int previousSelectedDay); 173 | if (ccbDay.Items.Count != DateTime.DaysInMonth(year, month)) 174 | { 175 | ccbDay.Items.Clear(); 176 | for (int i = 1; i <= DateTime.DaysInMonth(year, month); i++) 177 | { 178 | ccbDay.Items.Add(i.ToString()); 179 | } 180 | if (gotPreviousSelectedDay == true && previousSelectedDay <= DateTime.DaysInMonth(year, month)) 181 | { 182 | ccbDay.Text = previousSelectedDay.ToString(); 183 | } 184 | else 185 | { 186 | ccbDay.Text = DateTime.Now.Day.ToString(); 187 | } 188 | } 189 | } 190 | } 191 | 192 | private void SetControlTexts() 193 | { 194 | btnClose.Text = Resources.Close; 195 | lblDateFormTitle.Text = Message.CAPTION; 196 | Text = Message.CAPTION; 197 | lblYear.Text = Resources.Year; 198 | lblMonth.Text = Resources.Month; 199 | lblDay.Text = Resources.Day; 200 | PopulateYearDropdown(); 201 | PopulateMonthDropdown(); 202 | PopulateDayDropdown(); 203 | UpdateWeekInfo(true); 204 | } 205 | 206 | private void PopulateDayDropdown() 207 | { 208 | ccbDay.Items.Clear(); 209 | for (int i = 1; i <= DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month); i++) 210 | { 211 | ccbDay.Items.Add(i.ToString()); 212 | } 213 | ccbDay.Text = DateTime.Now.Day.ToString(); 214 | } 215 | 216 | private void PopulateMonthDropdown() 217 | { 218 | ccbMonth.Items.Clear(); 219 | for (int i = 1; i < 13; i++) 220 | { 221 | ccbMonth.Items.Add(i.ToString()); 222 | } 223 | ccbMonth.Text = DateTime.Now.Month.ToString(); 224 | } 225 | 226 | private void PopulateYearDropdown() 227 | { 228 | ccbYear.Items.Clear(); 229 | for (int i = DateTime.Now.Year - 10; i < DateTime.Now.Year + 10; i++) 230 | { 231 | ccbYear.Items.Add(i.ToString()); 232 | } 233 | ccbYear.Text = DateTime.Now.Year.ToString(); 234 | } 235 | 236 | private void FocusMinimizeIcon() 237 | { 238 | minimizePanel.BackColor = Color.LightGray; 239 | } 240 | 241 | private void MoveForm(MouseEventArgs e) 242 | { 243 | if (e.Button != MouseButtons.Left) 244 | { 245 | return; 246 | } 247 | 248 | Top = Cursor.Position.Y - Offset.Y; 249 | Left = Cursor.Position.X - Offset.X; 250 | } 251 | 252 | private void UpdateOffset(MouseEventArgs e) 253 | { 254 | Offset = new Point(e.X, e.Y); 255 | } 256 | 257 | private void UnfocusMinimizeIcon() 258 | { 259 | minimizePanel.BackColor = Color.White; 260 | } 261 | 262 | #endregion 263 | } 264 | } -------------------------------------------------------------------------------- /Forms/DateForm.designer.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows.Forms; 3 | 4 | namespace WeekNumber.Forms 5 | { 6 | partial class DateForm 7 | { 8 | /// 9 | /// Required designer variable. 10 | /// 11 | private IContainer components = null; 12 | 13 | /// 14 | /// Clean up any resources being used. 15 | /// 16 | /// true if managed resources should be disposed; otherwise, false. 17 | protected override void Dispose(bool disposing) 18 | { 19 | if (disposing && (components != null)) 20 | { 21 | components.Dispose(); 22 | } 23 | base.Dispose(disposing); 24 | } 25 | 26 | #region Windows Form Designer generated code 27 | 28 | /// 29 | /// Required method for Designer support - do not modify 30 | /// the contents of this method with the code editor. 31 | /// 32 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Windows.Forms.Control.set_Text(System.String)")] 33 | private void InitializeComponent() 34 | { 35 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DateForm)); 36 | this.lblDateFormTitle = new System.Windows.Forms.Label(); 37 | this.minimizePanelFrame = new System.Windows.Forms.Panel(); 38 | this.minimizePanel = new System.Windows.Forms.Panel(); 39 | this.titleIcon = new System.Windows.Forms.PictureBox(); 40 | this.btnClose = new System.Windows.Forms.Button(); 41 | this.settingsPanel = new System.Windows.Forms.Panel(); 42 | this.lblDay = new System.Windows.Forms.Label(); 43 | this.lblMonth = new System.Windows.Forms.Label(); 44 | this.lblYear = new System.Windows.Forms.Label(); 45 | this.pictureBoxWeek = new System.Windows.Forms.PictureBox(); 46 | this.lblInformation = new System.Windows.Forms.Label(); 47 | this.ccbDay = new WeekNumber.Controls.CustomComboBox(); 48 | this.ccbMonth = new WeekNumber.Controls.CustomComboBox(); 49 | this.ccbYear = new WeekNumber.Controls.CustomComboBox(); 50 | this.minimizePanelFrame.SuspendLayout(); 51 | ((System.ComponentModel.ISupportInitialize)(this.titleIcon)).BeginInit(); 52 | this.settingsPanel.SuspendLayout(); 53 | ((System.ComponentModel.ISupportInitialize)(this.pictureBoxWeek)).BeginInit(); 54 | this.SuspendLayout(); 55 | // 56 | // lblDateFormTitle 57 | // 58 | this.lblDateFormTitle.Dock = System.Windows.Forms.DockStyle.Top; 59 | this.lblDateFormTitle.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 60 | this.lblDateFormTitle.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 61 | this.lblDateFormTitle.Location = new System.Drawing.Point(0, 0); 62 | this.lblDateFormTitle.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 63 | this.lblDateFormTitle.Name = "lblDateFormTitle"; 64 | this.lblDateFormTitle.Padding = new System.Windows.Forms.Padding(56, 0, 0, 0); 65 | this.lblDateFormTitle.Size = new System.Drawing.Size(959, 58); 66 | this.lblDateFormTitle.TabIndex = 1; 67 | this.lblDateFormTitle.Text = "Select date to display its week number"; 68 | this.lblDateFormTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 69 | this.lblDateFormTitle.MouseDown += new System.Windows.Forms.MouseEventHandler(this.SettingsTitle_MouseDown); 70 | this.lblDateFormTitle.MouseMove += new System.Windows.Forms.MouseEventHandler(this.SettingsTitle_MouseMove); 71 | // 72 | // minimizePanelFrame 73 | // 74 | this.minimizePanelFrame.Controls.Add(this.minimizePanel); 75 | this.minimizePanelFrame.Location = new System.Drawing.Point(892, 0); 76 | this.minimizePanelFrame.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 77 | this.minimizePanelFrame.Name = "minimizePanelFrame"; 78 | this.minimizePanelFrame.Size = new System.Drawing.Size(63, 58); 79 | this.minimizePanelFrame.TabIndex = 3; 80 | this.minimizePanelFrame.Click += new System.EventHandler(this.MinimizePanelFrame_Click); 81 | this.minimizePanelFrame.MouseEnter += new System.EventHandler(this.MinimizePanel_MouseEnter); 82 | this.minimizePanelFrame.MouseLeave += new System.EventHandler(this.MinimizePanel_MouseLeave); 83 | // 84 | // minimizePanel 85 | // 86 | this.minimizePanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 87 | this.minimizePanel.BackColor = System.Drawing.Color.White; 88 | this.minimizePanel.Location = new System.Drawing.Point(12, 13); 89 | this.minimizePanel.Margin = new System.Windows.Forms.Padding(0); 90 | this.minimizePanel.Name = "minimizePanel"; 91 | this.minimizePanel.Size = new System.Drawing.Size(44, 14); 92 | this.minimizePanel.TabIndex = 3; 93 | this.minimizePanel.Click += new System.EventHandler(this.MinimizePanel_Click); 94 | this.minimizePanel.MouseEnter += new System.EventHandler(this.MinimizePanel_MouseEnter); 95 | // 96 | // titleIcon 97 | // 98 | this.titleIcon.BackColor = System.Drawing.Color.Transparent; 99 | this.titleIcon.Image = ((System.Drawing.Image)(resources.GetObject("titleIcon.Image"))); 100 | this.titleIcon.Location = new System.Drawing.Point(7, 7); 101 | this.titleIcon.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 102 | this.titleIcon.Name = "titleIcon"; 103 | this.titleIcon.Size = new System.Drawing.Size(46, 47); 104 | this.titleIcon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; 105 | this.titleIcon.TabIndex = 4; 106 | this.titleIcon.TabStop = false; 107 | // 108 | // btnClose 109 | // 110 | this.btnClose.BackColor = System.Drawing.Color.DeepSkyBlue; 111 | this.btnClose.FlatAppearance.BorderColor = System.Drawing.Color.DeepSkyBlue; 112 | this.btnClose.FlatAppearance.MouseDownBackColor = System.Drawing.Color.DeepSkyBlue; 113 | this.btnClose.FlatAppearance.MouseOverBackColor = System.Drawing.Color.LightBlue; 114 | this.btnClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 115 | this.btnClose.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 116 | this.btnClose.Location = new System.Drawing.Point(682, 337); 117 | this.btnClose.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 118 | this.btnClose.Name = "btnClose"; 119 | this.btnClose.Size = new System.Drawing.Size(256, 72); 120 | this.btnClose.TabIndex = 1; 121 | this.btnClose.Text = "&Close"; 122 | this.btnClose.UseVisualStyleBackColor = false; 123 | this.btnClose.Click += new System.EventHandler(this.Close_Click); 124 | // 125 | // settingsPanel 126 | // 127 | this.settingsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 128 | | System.Windows.Forms.AnchorStyles.Right))); 129 | this.settingsPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(73)))), ((int)(((byte)(76)))), ((int)(((byte)(76))))); 130 | this.settingsPanel.Controls.Add(this.lblDay); 131 | this.settingsPanel.Controls.Add(this.lblMonth); 132 | this.settingsPanel.Controls.Add(this.lblYear); 133 | this.settingsPanel.Controls.Add(this.pictureBoxWeek); 134 | this.settingsPanel.Controls.Add(this.lblInformation); 135 | this.settingsPanel.Controls.Add(this.ccbDay); 136 | this.settingsPanel.Controls.Add(this.ccbMonth); 137 | this.settingsPanel.Controls.Add(this.ccbYear); 138 | this.settingsPanel.Controls.Add(this.btnClose); 139 | this.settingsPanel.Location = new System.Drawing.Point(0, 58); 140 | this.settingsPanel.Margin = new System.Windows.Forms.Padding(0); 141 | this.settingsPanel.Name = "settingsPanel"; 142 | this.settingsPanel.Size = new System.Drawing.Size(959, 430); 143 | this.settingsPanel.TabIndex = 2; 144 | // 145 | // lblDay 146 | // 147 | this.lblDay.AutoSize = true; 148 | this.lblDay.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold); 149 | this.lblDay.Location = new System.Drawing.Point(436, 33); 150 | this.lblDay.Name = "lblDay"; 151 | this.lblDay.Size = new System.Drawing.Size(72, 41); 152 | this.lblDay.TabIndex = 20; 153 | this.lblDay.Text = "Day"; 154 | // 155 | // lblMonth 156 | // 157 | this.lblMonth.AutoSize = true; 158 | this.lblMonth.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold); 159 | this.lblMonth.Location = new System.Drawing.Point(236, 33); 160 | this.lblMonth.Name = "lblMonth"; 161 | this.lblMonth.Size = new System.Drawing.Size(113, 41); 162 | this.lblMonth.TabIndex = 19; 163 | this.lblMonth.Text = "Month"; 164 | // 165 | // lblYear 166 | // 167 | this.lblYear.AutoSize = true; 168 | this.lblYear.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold); 169 | this.lblYear.Location = new System.Drawing.Point(36, 33); 170 | this.lblYear.Name = "lblYear"; 171 | this.lblYear.Size = new System.Drawing.Size(77, 41); 172 | this.lblYear.TabIndex = 18; 173 | this.lblYear.Text = "Year"; 174 | // 175 | // pictureBoxWeek 176 | // 177 | this.pictureBoxWeek.Location = new System.Drawing.Point(682, 43); 178 | this.pictureBoxWeek.Name = "pictureBoxWeek"; 179 | this.pictureBoxWeek.Size = new System.Drawing.Size(256, 256); 180 | this.pictureBoxWeek.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 181 | this.pictureBoxWeek.TabIndex = 17; 182 | this.pictureBoxWeek.TabStop = false; 183 | // 184 | // lblInformation 185 | // 186 | this.lblInformation.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold); 187 | this.lblInformation.Location = new System.Drawing.Point(36, 162); 188 | this.lblInformation.Name = "lblInformation"; 189 | this.lblInformation.Size = new System.Drawing.Size(581, 107); 190 | this.lblInformation.TabIndex = 16; 191 | this.lblInformation.Text = "Week 22\r\nSunday, 5th of June 2021"; 192 | // 193 | // ccbDay 194 | // 195 | this.ccbDay.DropDownWidth = 174; 196 | this.ccbDay.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold); 197 | this.ccbDay.FormattingEnabled = true; 198 | this.ccbDay.HighlightColor = System.Drawing.Color.DeepSkyBlue; 199 | this.ccbDay.Location = new System.Drawing.Point(443, 87); 200 | this.ccbDay.Name = "ccbDay"; 201 | this.ccbDay.Size = new System.Drawing.Size(174, 48); 202 | this.ccbDay.TabIndex = 15; 203 | this.ccbDay.SelectedIndexChanged += new System.EventHandler(this.SelectedDayChanged); 204 | // 205 | // ccbMonth 206 | // 207 | this.ccbMonth.DropDownWidth = 174; 208 | this.ccbMonth.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold); 209 | this.ccbMonth.FormattingEnabled = true; 210 | this.ccbMonth.HighlightColor = System.Drawing.Color.DeepSkyBlue; 211 | this.ccbMonth.Location = new System.Drawing.Point(243, 87); 212 | this.ccbMonth.Name = "ccbMonth"; 213 | this.ccbMonth.Size = new System.Drawing.Size(174, 48); 214 | this.ccbMonth.TabIndex = 14; 215 | this.ccbMonth.SelectedIndexChanged += new System.EventHandler(this.SelectedMonthChanged); 216 | // 217 | // ccbYear 218 | // 219 | this.ccbYear.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold); 220 | this.ccbYear.FormattingEnabled = true; 221 | this.ccbYear.HighlightColor = System.Drawing.Color.DeepSkyBlue; 222 | this.ccbYear.Location = new System.Drawing.Point(43, 87); 223 | this.ccbYear.Name = "ccbYear"; 224 | this.ccbYear.Size = new System.Drawing.Size(174, 48); 225 | this.ccbYear.TabIndex = 13; 226 | this.ccbYear.SelectedIndexChanged += new System.EventHandler(this.SelectedYearChanged); 227 | // 228 | // DateForm 229 | // 230 | this.AutoScaleDimensions = new System.Drawing.SizeF(14F, 29F); 231 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 232 | this.BackColor = System.Drawing.Color.DeepSkyBlue; 233 | this.ClientSize = new System.Drawing.Size(959, 488); 234 | this.ControlBox = false; 235 | this.Controls.Add(this.titleIcon); 236 | this.Controls.Add(this.minimizePanelFrame); 237 | this.Controls.Add(this.settingsPanel); 238 | this.Controls.Add(this.lblDateFormTitle); 239 | this.DoubleBuffered = true; 240 | this.ForeColor = System.Drawing.Color.White; 241 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 242 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 243 | this.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 244 | this.MaximizeBox = false; 245 | this.MinimizeBox = false; 246 | this.Name = "DateForm"; 247 | this.ShowInTaskbar = false; 248 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 249 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 250 | this.TopMost = true; 251 | this.Shown += new System.EventHandler(this.DateForm_Shown); 252 | this.minimizePanelFrame.ResumeLayout(false); 253 | ((System.ComponentModel.ISupportInitialize)(this.titleIcon)).EndInit(); 254 | this.settingsPanel.ResumeLayout(false); 255 | this.settingsPanel.PerformLayout(); 256 | ((System.ComponentModel.ISupportInitialize)(this.pictureBoxWeek)).EndInit(); 257 | this.ResumeLayout(false); 258 | 259 | } 260 | 261 | #endregion 262 | 263 | private Label lblDateFormTitle; 264 | private Panel minimizePanelFrame; 265 | private Panel minimizePanel; 266 | private PictureBox titleIcon; 267 | private Button btnClose; 268 | private Panel settingsPanel; 269 | private PictureBox pictureBoxWeek; 270 | private Label lblInformation; 271 | private Controls.CustomComboBox ccbDay; 272 | private Controls.CustomComboBox ccbMonth; 273 | private Controls.CustomComboBox ccbYear; 274 | private Label lblMonth; 275 | private Label lblYear; 276 | private Label lblDay; 277 | } 278 | } -------------------------------------------------------------------------------- /Forms/MessageForm.Designer.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows.Forms; 3 | 4 | namespace WeekNumber.Forms 5 | { 6 | partial class MessageForm 7 | { 8 | /// 9 | /// Required designer variable. 10 | /// 11 | private IContainer components = null; 12 | 13 | /// 14 | /// Clean up any resources being used. 15 | /// 16 | /// true if managed resources should be disposed; otherwise, false. 17 | protected override void Dispose(bool disposing) 18 | { 19 | if (disposing && (components != null)) 20 | { 21 | components.Dispose(); 22 | } 23 | base.Dispose(disposing); 24 | } 25 | 26 | #region Windows Form Designer generated code 27 | 28 | /// 29 | /// Required method for Designer support - do not modify 30 | /// the contents of this method with the code editor. 31 | /// 32 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Windows.Forms.Control.set_Text(System.String)")] 33 | private void InitializeComponent() 34 | { 35 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MessageForm)); 36 | this.lblMessageFormTitle = new System.Windows.Forms.Label(); 37 | this.minimizePanelFrame = new System.Windows.Forms.Panel(); 38 | this.minimizePanel = new System.Windows.Forms.Panel(); 39 | this.titleIcon = new System.Windows.Forms.PictureBox(); 40 | this.btnOK = new System.Windows.Forms.Button(); 41 | this.settingsPanel = new System.Windows.Forms.Panel(); 42 | this.messageBox = new System.Windows.Forms.TextBox(); 43 | this.Link = new System.Windows.Forms.LinkLabel(); 44 | this.minimizePanelFrame.SuspendLayout(); 45 | ((System.ComponentModel.ISupportInitialize)(this.titleIcon)).BeginInit(); 46 | this.settingsPanel.SuspendLayout(); 47 | this.SuspendLayout(); 48 | // 49 | // lblMessageFormTitle 50 | // 51 | this.lblMessageFormTitle.Dock = System.Windows.Forms.DockStyle.Top; 52 | this.lblMessageFormTitle.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 53 | this.lblMessageFormTitle.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 54 | this.lblMessageFormTitle.Location = new System.Drawing.Point(0, 0); 55 | this.lblMessageFormTitle.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 56 | this.lblMessageFormTitle.Name = "lblMessageFormTitle"; 57 | this.lblMessageFormTitle.Padding = new System.Windows.Forms.Padding(56, 0, 0, 0); 58 | this.lblMessageFormTitle.Size = new System.Drawing.Size(959, 58); 59 | this.lblMessageFormTitle.TabIndex = 1; 60 | this.lblMessageFormTitle.Text = "Information"; 61 | this.lblMessageFormTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 62 | this.lblMessageFormTitle.MouseDown += new System.Windows.Forms.MouseEventHandler(this.SettingsTitle_MouseDown); 63 | this.lblMessageFormTitle.MouseMove += new System.Windows.Forms.MouseEventHandler(this.SettingsTitle_MouseMove); 64 | // 65 | // minimizePanelFrame 66 | // 67 | this.minimizePanelFrame.Controls.Add(this.minimizePanel); 68 | this.minimizePanelFrame.Location = new System.Drawing.Point(892, 0); 69 | this.minimizePanelFrame.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 70 | this.minimizePanelFrame.Name = "minimizePanelFrame"; 71 | this.minimizePanelFrame.Size = new System.Drawing.Size(63, 58); 72 | this.minimizePanelFrame.TabIndex = 3; 73 | this.minimizePanelFrame.Click += new System.EventHandler(this.MinimizePanelFrame_Click); 74 | this.minimizePanelFrame.MouseEnter += new System.EventHandler(this.MinimizePanel_MouseEnter); 75 | this.minimizePanelFrame.MouseLeave += new System.EventHandler(this.MinimizePanel_MouseLeave); 76 | // 77 | // minimizePanel 78 | // 79 | this.minimizePanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 80 | this.minimizePanel.BackColor = System.Drawing.Color.White; 81 | this.minimizePanel.Location = new System.Drawing.Point(12, 13); 82 | this.minimizePanel.Margin = new System.Windows.Forms.Padding(0); 83 | this.minimizePanel.Name = "minimizePanel"; 84 | this.minimizePanel.Size = new System.Drawing.Size(44, 14); 85 | this.minimizePanel.TabIndex = 3; 86 | this.minimizePanel.Click += new System.EventHandler(this.MinimizePanel_Click); 87 | this.minimizePanel.MouseEnter += new System.EventHandler(this.MinimizePanel_MouseEnter); 88 | // 89 | // titleIcon 90 | // 91 | this.titleIcon.BackColor = System.Drawing.Color.Transparent; 92 | this.titleIcon.Image = ((System.Drawing.Image)(resources.GetObject("titleIcon.Image"))); 93 | this.titleIcon.Location = new System.Drawing.Point(7, 7); 94 | this.titleIcon.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 95 | this.titleIcon.Name = "titleIcon"; 96 | this.titleIcon.Size = new System.Drawing.Size(46, 47); 97 | this.titleIcon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; 98 | this.titleIcon.TabIndex = 4; 99 | this.titleIcon.TabStop = false; 100 | // 101 | // btnOK 102 | // 103 | this.btnOK.BackColor = System.Drawing.Color.DeepSkyBlue; 104 | this.btnOK.FlatAppearance.BorderColor = System.Drawing.Color.DeepSkyBlue; 105 | this.btnOK.FlatAppearance.MouseDownBackColor = System.Drawing.Color.DeepSkyBlue; 106 | this.btnOK.FlatAppearance.MouseOverBackColor = System.Drawing.Color.LightBlue; 107 | this.btnOK.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 108 | this.btnOK.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 109 | this.btnOK.Location = new System.Drawing.Point(682, 332); 110 | this.btnOK.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 111 | this.btnOK.Name = "btnOK"; 112 | this.btnOK.Size = new System.Drawing.Size(256, 72); 113 | this.btnOK.TabIndex = 1; 114 | this.btnOK.Text = "OK"; 115 | this.btnOK.UseVisualStyleBackColor = false; 116 | this.btnOK.Click += new System.EventHandler(this.OK_Click); 117 | // 118 | // settingsPanel 119 | // 120 | this.settingsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 121 | | System.Windows.Forms.AnchorStyles.Right))); 122 | this.settingsPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(73)))), ((int)(((byte)(76)))), ((int)(((byte)(76))))); 123 | this.settingsPanel.Controls.Add(this.messageBox); 124 | this.settingsPanel.Controls.Add(this.Link); 125 | this.settingsPanel.Controls.Add(this.btnOK); 126 | this.settingsPanel.Location = new System.Drawing.Point(0, 58); 127 | this.settingsPanel.Margin = new System.Windows.Forms.Padding(0); 128 | this.settingsPanel.Name = "settingsPanel"; 129 | this.settingsPanel.Size = new System.Drawing.Size(959, 430); 130 | this.settingsPanel.TabIndex = 2; 131 | // 132 | // messageBox 133 | // 134 | this.messageBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(73)))), ((int)(((byte)(76)))), ((int)(((byte)(76))))); 135 | this.messageBox.BorderStyle = System.Windows.Forms.BorderStyle.None; 136 | this.messageBox.Font = new System.Drawing.Font("Segoe UI Semibold", 10.2F, System.Drawing.FontStyle.Bold); 137 | this.messageBox.ForeColor = System.Drawing.Color.White; 138 | this.messageBox.Location = new System.Drawing.Point(12, 18); 139 | this.messageBox.Multiline = true; 140 | this.messageBox.Name = "messageBox"; 141 | this.messageBox.ReadOnly = true; 142 | this.messageBox.RightToLeft = System.Windows.Forms.RightToLeft.No; 143 | this.messageBox.Size = new System.Drawing.Size(936, 234); 144 | this.messageBox.TabIndex = 12; 145 | this.messageBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; 146 | // 147 | // Link 148 | // 149 | this.Link.ActiveLinkColor = System.Drawing.Color.LightSkyBlue; 150 | this.Link.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 151 | | System.Windows.Forms.AnchorStyles.Right))); 152 | this.Link.Font = new System.Drawing.Font("Segoe UI Semibold", 10.2F, System.Drawing.FontStyle.Bold); 153 | this.Link.LinkColor = System.Drawing.Color.DeepSkyBlue; 154 | this.Link.Location = new System.Drawing.Point(21, 265); 155 | this.Link.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 156 | this.Link.Name = "Link"; 157 | this.Link.Size = new System.Drawing.Size(917, 42); 158 | this.Link.TabIndex = 11; 159 | this.Link.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 160 | this.Link.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.Link_LinkClicked); 161 | // 162 | // MessageForm 163 | // 164 | this.AutoScaleDimensions = new System.Drawing.SizeF(14F, 29F); 165 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 166 | this.BackColor = System.Drawing.Color.DeepSkyBlue; 167 | this.ClientSize = new System.Drawing.Size(959, 488); 168 | this.ControlBox = false; 169 | this.Controls.Add(this.titleIcon); 170 | this.Controls.Add(this.minimizePanelFrame); 171 | this.Controls.Add(this.settingsPanel); 172 | this.Controls.Add(this.lblMessageFormTitle); 173 | this.DoubleBuffered = true; 174 | this.ForeColor = System.Drawing.Color.White; 175 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 176 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 177 | this.Margin = new System.Windows.Forms.Padding(5, 4, 5, 4); 178 | this.MaximizeBox = false; 179 | this.MinimizeBox = false; 180 | this.Name = "MessageForm"; 181 | this.ShowInTaskbar = false; 182 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 183 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 184 | this.TopMost = true; 185 | this.minimizePanelFrame.ResumeLayout(false); 186 | ((System.ComponentModel.ISupportInitialize)(this.titleIcon)).EndInit(); 187 | this.settingsPanel.ResumeLayout(false); 188 | this.settingsPanel.PerformLayout(); 189 | this.ResumeLayout(false); 190 | 191 | } 192 | 193 | #endregion 194 | private Label lblMessageFormTitle; 195 | private Panel minimizePanelFrame; 196 | private Panel minimizePanel; 197 | private PictureBox titleIcon; 198 | private Button btnOK; 199 | private Panel settingsPanel; 200 | private LinkLabel Link; 201 | private TextBox messageBox; 202 | } 203 | } -------------------------------------------------------------------------------- /Forms/MessageForm.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | 8 | #endregion 9 | 10 | namespace WeekNumber.Forms 11 | { 12 | /// 13 | /// Message form 14 | /// 15 | public partial class MessageForm : Form 16 | { 17 | #region Public methods 18 | 19 | /// 20 | /// Set message to display in form 21 | /// 22 | /// Message text 23 | public void SetMessage(string messageText) 24 | { 25 | messageBox.Text = messageText; 26 | } 27 | 28 | /// 29 | /// Set link to product URL 30 | /// 31 | public void SetLink(string url) 32 | { 33 | Link.Text = url; 34 | } 35 | 36 | #endregion 37 | 38 | #region Protected class properties 39 | 40 | /// 41 | /// Mouse location offset used form form movement 42 | /// 43 | protected Point Offset { get; set; } 44 | 45 | #endregion 46 | 47 | #region Constructors 48 | 49 | /// 50 | /// Settings form constructor 51 | /// 52 | /// Message text 53 | public MessageForm(string messageText) 54 | { 55 | InitializeComponent(); 56 | StartPosition = FormStartPosition.CenterScreen; 57 | SetControlTexts(); 58 | SetMessage(messageText); 59 | } 60 | 61 | /// 62 | /// Settings form constructor 63 | /// 64 | public MessageForm() 65 | { 66 | InitializeComponent(); 67 | StartPosition = FormStartPosition.CenterScreen; 68 | SetControlTexts(); 69 | } 70 | 71 | #endregion 72 | 73 | #region Public static methods 74 | 75 | /// 76 | /// Display a message 77 | /// 78 | /// 79 | public static void DisplayMessage(string messageText) 80 | { 81 | using (MessageForm message = new MessageForm(messageText)) 82 | { 83 | message.ShowDialog(); 84 | } 85 | } 86 | 87 | /// 88 | /// Displays a message on dialogbox with matching icon 89 | /// 90 | /// 91 | /// 92 | public static void DisplayMessage(string messageText, bool error = false) 93 | { 94 | using (MessageForm message = new MessageForm(messageText)) 95 | { 96 | if (error) message.titleIcon.Image = SystemIcons.Exclamation.ToBitmap(); 97 | message.ShowDialog(); 98 | } 99 | } 100 | 101 | /// 102 | /// Logs and displays message 103 | /// 104 | /// 105 | public static void LogAndDisplayMessage(string messageText) 106 | { 107 | Log.Info = messageText; 108 | using (MessageForm message = new MessageForm(messageText)) 109 | { 110 | message.ShowDialog(); 111 | } 112 | } 113 | 114 | /// 115 | /// Logs and displays message with Product URL link 116 | /// 117 | /// 118 | /// 119 | public static void LogAndDisplayLinkMessage(string messageText, string url) 120 | { 121 | Log.Info = messageText; 122 | using (MessageForm msgForm = new MessageForm(messageText)) 123 | { 124 | msgForm.SetLink(url); 125 | msgForm.ShowDialog(); 126 | } 127 | } 128 | 129 | #endregion 130 | 131 | #region Events handling 132 | 133 | private void OK_Click(object sender, EventArgs e) 134 | { 135 | Close(); 136 | } 137 | 138 | private void SettingsTitle_MouseDown(object sender, MouseEventArgs e) 139 | { 140 | UpdateOffset(e); 141 | } 142 | 143 | private void SettingsTitle_MouseMove(object sender, MouseEventArgs e) 144 | { 145 | MoveForm(e); 146 | } 147 | 148 | private void MinimizePanel_MouseEnter(object sender, EventArgs e) 149 | { 150 | FocusMinimizeIcon(); 151 | } 152 | 153 | private void MinimizePanel_MouseLeave(object sender, EventArgs e) 154 | { 155 | UnfocusMinimizeIcon(); 156 | } 157 | 158 | private void MinimizePanel_Click(object sender, EventArgs e) 159 | { 160 | Close(); 161 | } 162 | 163 | private void MinimizePanelFrame_Click(object sender, EventArgs e) 164 | { 165 | Close(); 166 | } 167 | 168 | private void Link_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 169 | { 170 | OpenUrl(); 171 | Close(); 172 | } 173 | 174 | #endregion 175 | 176 | #region Private methods 177 | 178 | private void SetControlTexts() 179 | { 180 | btnOK.Text = Resources.OK; 181 | lblMessageFormTitle.Text = Message.CAPTION; 182 | Text = Message.CAPTION; 183 | } 184 | 185 | private void FocusMinimizeIcon() 186 | { 187 | minimizePanel.BackColor = Color.LightGray; 188 | } 189 | 190 | private void MoveForm(MouseEventArgs e) 191 | { 192 | if (e.Button != MouseButtons.Left) 193 | { 194 | return; 195 | } 196 | 197 | Top = Cursor.Position.Y - Offset.Y; 198 | Left = Cursor.Position.X - Offset.X; 199 | } 200 | 201 | private void UpdateOffset(MouseEventArgs e) 202 | { 203 | Offset = new Point(e.X, e.Y); 204 | } 205 | 206 | private void UnfocusMinimizeIcon() 207 | { 208 | minimizePanel.BackColor = Color.White; 209 | } 210 | 211 | private void OpenUrl() 212 | { 213 | using (Process p = new Process()) 214 | { 215 | p.StartInfo = new ProcessStartInfo 216 | { 217 | UseShellExecute = true, 218 | FileName = Link.Text 219 | }; 220 | p.Start(); 221 | } 222 | } 223 | 224 | #endregion 225 | } 226 | } -------------------------------------------------------------------------------- /Forms/WeekNumberForDateForm.cs: -------------------------------------------------------------------------------- 1 | namespace WeekNumber.Forms 2 | { 3 | class WeekNumberForDateForm 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /IGui.cs: -------------------------------------------------------------------------------- 1 | namespace WeekNumber 2 | { 3 | /// 4 | /// GUI Interface 5 | /// 6 | public interface IGui 7 | { 8 | /// 9 | /// Updates icon on GUI with given week number 10 | /// 11 | /// The week number to display on icon 12 | /// The width and height of the icon 13 | /// Redraw context menu 14 | void UpdateIcon(int weekNumber, int iconResolution = (int)IconSize.Icon256, bool redrawContextMenu = false); 15 | 16 | /// 17 | /// Disposes GUI 18 | /// 19 | void Dispose(); 20 | 21 | /// 22 | /// Event handler for when GUI (icon) update is requested 23 | /// 24 | event System.EventHandler UpdateRequest; 25 | } 26 | } -------------------------------------------------------------------------------- /IconSize.cs: -------------------------------------------------------------------------------- 1 | namespace WeekNumber 2 | { 3 | #region Internal enum of icon sizes 4 | 5 | internal enum IconSize : int 6 | { 7 | Icon16 = 16, 8 | Icon20 = 20, 9 | Icon24 = 24, 10 | Icon32 = 32, 11 | Icon40 = 40, 12 | Icon48 = 48, 13 | Icon64 = 64, 14 | Icon128 = 128, 15 | Icon256 = 256, 16 | Icon512 = 512 17 | } 18 | 19 | #endregion 20 | } 21 | -------------------------------------------------------------------------------- /Installation/License.de-DE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Installation/License.de-DE.txt -------------------------------------------------------------------------------- /Installation/License.en-US.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Installation/License.en-US.txt -------------------------------------------------------------------------------- /Installation/License.sv-SE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Installation/License.sv-SE.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Voltura AB 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 | -------------------------------------------------------------------------------- /Log.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using System.Globalization; 6 | using System.IO; 7 | using System.Windows.Forms; 8 | 9 | #endregion 10 | namespace WeekNumber 11 | { 12 | internal static class Log 13 | { 14 | #region Static variables 15 | 16 | private static readonly string logFile = Path.GetFileNameWithoutExtension(Application.ExecutablePath) + ".log"; 17 | private static readonly string appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 18 | Application.CompanyName, Application.ProductName); 19 | private static readonly string logFileFullPath = Path.Combine(appDataFolder, logFile); 20 | private static readonly int DEFAULT_LOGFILE_SIZE_IN_MEGABYTES = 10; 21 | 22 | #endregion 23 | 24 | #region Internal static constructor 25 | 26 | /// 27 | /// Constructor - Init log 28 | /// 29 | static Log() 30 | { 31 | Init(); 32 | } 33 | 34 | #endregion 35 | 36 | #region Internal methods 37 | 38 | /// 39 | /// Init log 40 | /// 41 | internal static void Init() 42 | { 43 | try 44 | { 45 | if (!Directory.Exists(appDataFolder)) 46 | { 47 | Directory.CreateDirectory(appDataFolder); 48 | } 49 | Trace.Listeners.Clear(); 50 | if (!Settings.SettingIsValue(Resources.UseApplicationLog, "True")) 51 | { 52 | Trace.Listeners.Clear(); 53 | Trace.Flush(); 54 | Trace.Close(); 55 | if (File.Exists(logFileFullPath)) File.Delete(logFileFullPath); 56 | return; 57 | } 58 | FileStream fs = new FileStream(logFileFullPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, 1024, FileOptions.WriteThrough); 59 | TextWriterTraceListener traceListener = new TextWriterTraceListener(fs); 60 | Trace.Listeners.Add(traceListener); 61 | Trace.AutoFlush = true; 62 | Trace.UseGlobalLock = false; 63 | } 64 | catch (Exception ex) 65 | { 66 | Debug.WriteLine(ex); 67 | } 68 | } 69 | 70 | internal static void Close(string info) 71 | { 72 | Info = info; 73 | Close(); 74 | } 75 | 76 | internal static void Close() 77 | { 78 | Truncate(); 79 | Trace.Flush(); 80 | Trace.Close(); 81 | } 82 | 83 | /// 84 | /// Truncate log 85 | /// 86 | internal static void Truncate() 87 | { 88 | try 89 | { 90 | Trace.Flush(); 91 | Trace.Close(); 92 | Trace.Listeners.Clear(); 93 | FileInfo fi = new FileInfo(logFileFullPath); 94 | if (fi.Exists) 95 | { 96 | int trimSize = Settings.GetIntSetting(Resources.MaxLogFileSizeInMB, DEFAULT_LOGFILE_SIZE_IN_MEGABYTES) * 1024 * 1024; 97 | if (fi.Length > trimSize) 98 | { 99 | using (MemoryStream ms = new MemoryStream(trimSize)) 100 | using (FileStream s = new FileStream(logFileFullPath, FileMode.Open, FileAccess.ReadWrite)) 101 | { 102 | s.Seek(-trimSize, SeekOrigin.End); 103 | byte[] bytes = new byte[trimSize]; 104 | s.Read(bytes, 0, trimSize); 105 | ms.Write(bytes, 0, trimSize); 106 | ms.Position = 0; 107 | s.SetLength(trimSize); 108 | s.Position = 0; 109 | ms.CopyTo(s); 110 | } 111 | } 112 | } 113 | } 114 | catch (Exception ex) 115 | { 116 | Debug.WriteLine(ex); 117 | } 118 | Init(); 119 | } 120 | 121 | internal static void Show(string info) 122 | { 123 | Info = info; 124 | Show(); 125 | } 126 | 127 | internal static void Show() 128 | { 129 | try 130 | { 131 | if (File.Exists(logFileFullPath)) 132 | { 133 | using (Process process = new Process() { StartInfo = new ProcessStartInfo(logFileFullPath) { UseShellExecute = true } }) 134 | { 135 | process.Start(); 136 | } 137 | } 138 | } 139 | catch (InvalidOperationException ex) 140 | { 141 | Error = ex; 142 | } 143 | } 144 | 145 | internal static void LogCaller() 146 | { 147 | StackTrace stackTrace = new StackTrace(); 148 | string method = stackTrace.GetFrame(1).GetMethod().Name; 149 | string methodClass = stackTrace.GetFrame(1).GetMethod().DeclaringType.FullName; 150 | string calleeMethod = stackTrace.GetFrame(2).GetMethod().Name; 151 | string calleeClass = stackTrace.GetFrame(2).GetMethod().DeclaringType.FullName; 152 | string infoText = $"{methodClass}::{(method == ".ctor" ? "constructor" : method)} called from {calleeClass}::{(calleeMethod == ".ctor" ? "constructor" : calleeMethod)}"; 153 | Info = infoText; 154 | } 155 | 156 | #endregion 157 | 158 | #region Internal static log properties 159 | 160 | /// 161 | /// Log info 162 | /// 163 | internal static string Info 164 | { 165 | private get => string.Empty; 166 | set 167 | { 168 | try 169 | { 170 | string formattedValue = value.Replace('\r', ' ').Replace('\n', ' ').Trim(); 171 | Trace.TraceInformation($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff", CultureInfo.InvariantCulture)} {formattedValue}"); 172 | } 173 | catch (Exception ex) 174 | { 175 | Debug.WriteLine(ex); 176 | } 177 | } 178 | } 179 | 180 | /// 181 | /// Log error 182 | /// 183 | internal static Exception Error 184 | { 185 | private get => new ArgumentNullException(logFile); 186 | set 187 | { 188 | try 189 | { 190 | string formattedValue = value.ToString().Replace('\r', ' ').Replace('\n', ' ').Trim(); 191 | Trace.TraceError($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff", CultureInfo.InvariantCulture)} {formattedValue}"); 192 | } 193 | catch (Exception ex) 194 | { 195 | Debug.WriteLine(ex); 196 | } 197 | } 198 | } 199 | 200 | /// 201 | /// Log an error string 202 | /// 203 | internal static string ErrorString 204 | { 205 | private get => string.Empty; 206 | set 207 | { 208 | try 209 | { 210 | string formattedValue = value.Replace('\r', ' ').Replace('\n', ' ').Trim(); 211 | Trace.TraceError($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff", CultureInfo.InvariantCulture)} {formattedValue}"); 212 | } 213 | catch (Exception ex) 214 | { 215 | Debug.WriteLine(ex); 216 | } 217 | } 218 | } 219 | 220 | #endregion 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /Message.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Windows.Forms; 5 | 6 | #endregion Using statements 7 | 8 | namespace WeekNumber 9 | { 10 | internal static class Message 11 | { 12 | #region Internal readonly strings 13 | 14 | internal static readonly string[] SWEDISH_DAY_OF_WEEK_PREFIX = { "Söndagen ", "Måndagen ", "Tisdagen ", "Onsdagen ", "Torsdagen ", "Fredagen ", "Lördagen " }; 15 | internal static readonly string CAPTION = $"{Resources.ProductName} {Resources.Version} {Application.ProductVersion}"; 16 | 17 | #endregion Internal readonly strings 18 | 19 | #region Show Information or Error dialog methods 20 | 21 | internal static void Show(string text, Exception ex = null) 22 | { 23 | var message = ex is null ? text : $"{text}\r\n{ex}"; 24 | if (ex is null) Log.Info = message; else Log.ErrorString = message; 25 | Forms.MessageForm.DisplayMessage(message, !(ex is null)); 26 | } 27 | 28 | internal static void Show(string text) 29 | { 30 | Show(text, null); 31 | } 32 | 33 | internal static void Show(string message, bool isError) 34 | { 35 | if (isError) Log.Info = message; else Log.ErrorString = message; 36 | Forms.MessageForm.DisplayMessage(message, isError); 37 | } 38 | 39 | internal static bool UserAcceptedQuestion(string message) 40 | { 41 | Log.Info = message; 42 | // TODO: Customize and use MessageForm 43 | DialogResult userAnswer = MessageBox.Show(message, CAPTION, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly); 44 | return userAnswer == DialogResult.Yes; 45 | } 46 | 47 | #endregion Show Information or Error dialog methods 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /NativeMethods.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | #endregion Using statements 7 | 8 | namespace WeekNumber 9 | { 10 | internal static class NativeMethods 11 | { 12 | #region Internal constants 13 | 14 | internal const int HWND_BROADCAST = 0xffff; 15 | internal const int WM_SETTINGCHANGE = 0x001a; 16 | 17 | #endregion Internal constants 18 | 19 | #region External user32.dll function to free GDI+ icon from memory 20 | 21 | [DllImport("user32.dll", CharSet = CharSet.Auto)] 22 | [return: MarshalAs(UnmanagedType.Bool)] 23 | internal static extern bool DestroyIcon(IntPtr handle); 24 | 25 | #endregion External user32.dll function to free GDI+ icon from memory 26 | 27 | #region External user32.dll function to inform Windows about changed taskbar setting 28 | 29 | [DllImport("User32.dll", CharSet = CharSet.Auto)] 30 | [return: MarshalAs(UnmanagedType.Bool)] 31 | internal static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam); 32 | 33 | #endregion External user32.dll function to inform Windows about changed taskbar setting 34 | 35 | #region External wininet.dll function to check Internet connection state 36 | 37 | [DllImport("wininet.dll", CharSet = CharSet.Auto)] 38 | [return: MarshalAs(UnmanagedType.Bool)] 39 | private extern static bool InternetGetConnectedState(out int Description, int ReservedValue); 40 | 41 | internal static bool IsConnectedToInternet() 42 | { 43 | return InternetGetConnectedState(out _, 0); 44 | } 45 | 46 | #endregion External wininet.dll function to check Internet connection state 47 | 48 | #region Refresh tray area (only English user interface) 49 | 50 | [StructLayout(LayoutKind.Sequential)] 51 | public struct RECT 52 | { 53 | public int left; 54 | public int top; 55 | public int right; 56 | public int bottom; 57 | } 58 | 59 | [DllImport("user32.dll")] 60 | public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 61 | 62 | [DllImport("user32.dll")] 63 | public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, 64 | string lpszWindow); 65 | 66 | [DllImport("user32.dll")] 67 | public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); 68 | 69 | [DllImport("user32.dll")] 70 | public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam); 71 | 72 | public static void RefreshTrayArea() 73 | { 74 | Log.LogCaller(); 75 | IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null); 76 | IntPtr systemTrayHandle = FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null); 77 | IntPtr sysPagerHandle = FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null); 78 | IntPtr notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area"); 79 | if (notificationAreaHandle == IntPtr.Zero) 80 | { 81 | notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", 82 | "User Promoted Notification Area"); 83 | IntPtr notifyIconOverflowWindowHandle = FindWindow("NotifyIconOverflowWindow", null); 84 | IntPtr overflowNotificationAreaHandle = FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, 85 | "ToolbarWindow32", "Overflow Notification Area"); 86 | RefreshTrayArea(overflowNotificationAreaHandle); 87 | } 88 | RefreshTrayArea(notificationAreaHandle); 89 | } 90 | 91 | private static void RefreshTrayArea(IntPtr windowHandle) 92 | { 93 | const uint wmMousemove = 0x0200; 94 | GetClientRect(windowHandle, out RECT rect); 95 | for (var x = 0; x < rect.right; x += 5) 96 | for (var y = 0; y < rect.bottom; y += 5) 97 | SendMessage(windowHandle, wmMousemove, 0, (y << 16) + x); 98 | } 99 | 100 | #endregion Refresh tray area (only English user interface) 101 | } 102 | } -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Runtime; 5 | using System.Threading; 6 | using System.Windows.Forms; 7 | using System.Windows.Forms.VisualStyles; 8 | 9 | #endregion Using statements 10 | 11 | namespace WeekNumber 12 | { 13 | internal class Program 14 | { 15 | #region Private variable to allow only one instance of application 16 | 17 | private static readonly Mutex Mutex = new Mutex(true, "550adc75-8afb-4813-ac91-8c8c6cb681ae"); 18 | 19 | #endregion Private variable to allow only one instance of application 20 | 21 | #region Application starting point 22 | 23 | [STAThread] 24 | private static void Main() 25 | { 26 | if (!Mutex.WaitOne(TimeSpan.Zero, true)) 27 | { 28 | return; 29 | } 30 | WeekApplicationContext context = null; 31 | try 32 | { 33 | Settings.RestoreBackupSettings(); 34 | Log.Init(); 35 | Settings.SetCultureInfoFromSystemOrSettings(); 36 | AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; 37 | Log.Info = "=== Application started ==="; 38 | Log.Info = Application.ProductName + " version " + Application.ProductVersion; 39 | NativeMethods.RefreshTrayArea(); 40 | SetGCSettings(); 41 | Application.EnableVisualStyles(); 42 | Application.VisualStyleState = VisualStyleState.ClientAndNonClientAreasEnabled; 43 | Application.SetCompatibleTextRenderingDefault(false); 44 | context = new WeekApplicationContext(); 45 | if (context?.Gui != null) 46 | { 47 | Application.Run(context); 48 | } 49 | } 50 | finally 51 | { 52 | Log.Close("=== Application ended ==="); 53 | context?.Dispose(); 54 | Mutex.ReleaseMutex(); 55 | } 56 | } 57 | 58 | #endregion Application starting point 59 | 60 | #region Private methods 61 | 62 | /// 63 | /// Configures garbarge collection settings 64 | /// 65 | private static void SetGCSettings() 66 | { 67 | Log.LogCaller(); 68 | GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; 69 | GCSettings.LatencyMode = GCLatencyMode.Batch; 70 | } 71 | 72 | #endregion Private methods that configures garbarge collection settings 73 | 74 | #region Global unhandled Exception trap 75 | 76 | /// 77 | /// Catches all unhandled exceptions for the application 78 | /// Writes the exception to the application log file 79 | /// Terminates the application with exit code -1 80 | /// 81 | /// 82 | /// 83 | private static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) 84 | { 85 | Exception ex = (Exception)e.ExceptionObject; 86 | Log.Error = ex; 87 | Message.Show(Resources.UnhandledException, ex); 88 | Log.Close("=== Application ended ==="); 89 | Environment.Exit(1); 90 | } 91 | 92 | #endregion Global unhandled Exception trap 93 | } 94 | } -------------------------------------------------------------------------------- /Properties/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System.Reflection; 4 | using System.Resources; 5 | using System.Runtime.InteropServices; 6 | 7 | #endregion Using statements 8 | 9 | #region Assembly information 10 | 11 | [assembly: AssemblyTitle("WeekNumber by Voltura AB")] 12 | [assembly: AssemblyDescription("WeekNumber by Voltura AB")] 13 | [assembly: AssemblyConfiguration("")] 14 | [assembly: AssemblyCompany("Voltura AB")] 15 | [assembly: AssemblyProduct("WeekNumber")] 16 | [assembly: AssemblyCopyright("Copyright © Voltura AB 2018-2024")] 17 | [assembly: AssemblyTrademark("")] 18 | [assembly: AssemblyCulture("")] 19 | [assembly: ComVisible(false)] 20 | [assembly: Guid("550adc75-8afb-4813-ac91-8c8c6cb681ae")] 21 | [assembly: AssemblyVersion("1.6.6.9")] 22 | [assembly: AssemblyFileVersion("1.6.6.9")] 23 | [assembly: NeutralResourcesLanguage("en-US")] 24 | 25 | #endregion Assembly information -------------------------------------------------------------------------------- /Properties/WeekNumber.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Properties/WeekNumber.snk -------------------------------------------------------------------------------- /Properties/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | True/PM 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /README.de-DE.md: -------------------------------------------------------------------------------- 1 | 🌍[English](README.md) ∙ [Deutsch](README.de-DE.md) ∙ [Svenska](README.sv-SE.md) 2 | 3 | # WeekNumber 4 | Windows 11/10 Systemtray-Anwendung, die die aktuelle Kalenderwoche anzeigt 5 | 6 | WeekNumber ![image](https://user-images.githubusercontent.com/2292809/121431601-e8451780-c979-11eb-9734-f30304c348d1.png) 7 | 8 | [![Neueste Version herunterladen](https://img.shields.io/github/v/release/voltura/WeekNumber?label=ladda%20ner%20senaste%20versionen&style=for-the-badge)](https://github.com/voltura/weeknumber/releases/latest/download/WeekNumber_v1.6.6.9.zip) 9 | 10 | [![Github All Releases](https://img.shields.io/github/downloads/voltura/WeekNumber/total.svg)]() 11 | [![License](https://img.shields.io/badge/licence-MIT-green)]() 12 | 13 | ## Funktionen 14 | Das aktuelle Kalenderwoche wird als Symbol im Systemtray der Windows-Taskleiste angezeigt. 15 | Durch Doppelklicken auf das Symbol können Sie die Kalenderwoche für andere Daten nachschlagen. 16 | 17 | Stellen Sie ein, dass die Anwendung mit Windows startet, passen Sie die Symbolfarben, die Sprache, Benachrichtigungen, Kalenderregeln und vieles mehr an. Für eine detaillierte Beschreibung siehe den _**Hilfebereich**_ unten. 18 | 19 | ### Sprachunterstützung 20 | - Englisch 21 | - Deutsch 22 | - Schwedisch 23 | 24 | _Wenn Sie eine Übersetzung in eine andere Sprache beitragen möchten, erstellen Sie bitte ein Issue auf GitHub, und ich werde Sie kontaktieren!_ 25 | 26 | ## Screenshots 27 | #### Symbol mit Standardfarben 28 | ![Taskbar-Symbol](https://user-images.githubusercontent.com/2292809/120904782-473f1f80-c64e-11eb-9256-c3d0ddab2124.png) 29 | 30 | #### Kontextmenü - Einstellungsmenü mit Sprachauswahl 31 | ![Kontextmenü]() 32 | 33 | #### Kalenderwoche für ein beliebiges Datum nachschlagen 34 | ![Kalenderwoche-Formular](https://github.com/user-attachments/assets/c629bf3f-439a-4415-93df-dfa4f9af19e0) 35 | 36 | #### Beispiele für Symbole mit benutzerdefinierten Farben 37 | ![Benutzerdefinierte Farben #1](https://user-images.githubusercontent.com/2292809/118048718-f4d74f80-b37c-11eb-8b36-211250ff25c5.png) ![Benutzerdefinierte Farben #2](https://user-images.githubusercontent.com/2292809/120920791-e997eb00-c6c0-11eb-889e-9a3e67787033.png) ![Benutzerdefinierte Farben #3](https://user-images.githubusercontent.com/2292809/120921288-498f9100-c6c3-11eb-8451-d2c3e19fba30.png) 38 | 39 | #### Farbauswahl, mit der Möglichkeit, benutzerdefinierte Farben zu definieren und zu verwenden; sowohl die Textfarbe als auch die Hintergrundfarbe des Symbols können geändert werden 40 | ![Farbwähler](https://user-images.githubusercontent.com/2292809/121435848-dd8d8100-c97f-11eb-8cf9-5ce7178aea73.png) 41 | 42 | ## Installation 43 | Zip-Datei herunterladen, extrahieren und WeekNumber.exe ausführen. 44 | 45 | Eine Benachrichtigung wird angezeigt, wenn WeekNumber gestartet ist 46 | 47 | ![image](https://user-images.githubusercontent.com/2292809/121437224-3a8a3680-c982-11eb-898c-84d45d33611f.png) 48 | 49 | Das aktuelle Kalenderwoche wird nun unter den Systemtraysymbolen angezeigt. Wenn Sie die Kalenderwoche nicht sehen, klicken Sie auf das Dachsymbol (^) im Systemtray und ziehen Sie das Symbol herunter, damit es sichtbar wird. 50 | 51 | 52 | ## Hilfebereich 53 | Alle Funktionen sind durch Rechtsklick auf das Symbol der Anwendung im Windows-Systemtray zugänglich. 54 | Wenn Sie das Symbol der Anwendung nicht sehen, klicken Sie auf das Dachsymbol (^) im Systemtray, klicken und halten Sie die Maustaste gedrückt, während Sie das Symbol in den Systemtray ziehen; das Symbol wird dort fixiert und sichtbar. 55 | 56 | ### Kontextmenü: 57 | - **Über WeekNumber** - _Zeigt Versionsinformationen an_ 58 | - **Einstellungen** 59 | - **Mit Windows starten** - _Wenn angekreuzt, startet die Anwendung automatisch mit Windows_ 60 | - **Sprache** - _Ändert die Sprache, die die Anwendung verwendet_ 61 | - **English** - _Englisch_ 62 | - **Deutsch** 63 | - **Svenska** 64 | - **Anwendungsprotokoll** 65 | - **Anwendungsprotokoll verwenden** - _Wenn angekreuzt, schreibt die Anwendung in eine Protokolldatei_ 66 | - **Anwendungsprotokoll anzeigen** - _Wenn oben angekreuzt, wird die Protokolldatei der Anwendung in einem Texteditor angezeigt (technisches Protokoll)_ 67 | - **Benachrichtigungen** 68 | - **Startbenachrichtigung anzeigen** - _Wenn angekreuzt, zeigt die Anwendung eine Startbenachrichtigung an_ 69 | 70 | 71 | 72 | - **Neue Wochenbenachrichtigung anzeigen** - _Wenn angekreuzt, wird eine Benachrichtigung angezeigt, wenn die aktuelle Woche sich ändert_ 73 | 74 | 75 | 76 | - **Stille Benachrichtigungen verwenden** - _Wenn angekreuzt, wird kein Ton abgespielt, wenn diese Anwendung Benachrichtigungen anzeigt_ 77 | - **Kleine/große Taskleistensymbole verwenden** - _Wechselt zwischen großen und kleinen Taskleistensymbolen. Haben Sie Schwierigkeiten, die Kalenderwoche zu sehen? Versuchen Sie, große Taskleistensymbole zu verwenden_ 78 | - **Einstellungen exportieren..." - _Möglichkeit, eine Kopie der aktuellen Anwendungseinstellungen zu exportieren/speichern_ 79 | - **Einstellungen importieren..." - _Möglichkeit, eine zuvor exportierte/gespeicherte Kopie der Anwendungseinstellungen zu importieren_ 80 | - **Kalender** - _Kalenderregeln, die die Anwendung verwendet; normalerweise stammen diese aus den regionalen Einstellungen, die im System eingestellt sind, können aber hier manuell angepasst werden_ 81 | - **'Erster-Tag-in-der-Woche'-Regel** - _Kalenderregel, wählen Sie den Tag, an dem eine Woche beginnt_ 82 | - **'Erste-Woche-des-Jahres'-Regel** - _Eine weitere Kalenderregel, die angibt, welche Regel für die erste Woche des Jahres verwendet werden soll_ 83 | - **Symbol** - _Einstellungen für das Anwendungssymbol_ 84 | - **Symbolfarben** - _Möglichkeit, die Farben der Anwendung anzupassen_ 85 | - **Symbolauflösung** - _Möglichkeit, die Auflösung des WeekNumber-Symbols anzupassen; wenn das Symbol verschwommen aussieht, kann eine andere Auflösung ein besseres Symbolbild liefern_ 86 | - **Grafikeinstellungen** - _Möglichkeit, die Grafikoptionen anzupassen, die beim Zeichnen des Symbols durch die Anwendung verwendet werden_ 87 | - **Glättungsmodus** 88 | - **Kompositionsqualität** 89 | - **Interpolationsmodus** 90 | - **Textkontrast** 91 | - **Symbol speichern...** - _Speichert das aktuelle WeekNumber-Symbol in einer .ico-Datei_ 92 | - **Kalenderwoche für Datum erhalten...** - _Zeigt die Kalenderwoche für das angegebene Datum an_ 93 | 94 | 95 | - **WeekNumber beenden** - _Beendet die Anwendung. Starten Sie sie erneut im Windows-Startmenü_ 96 | 97 | ## Spenden 98 | *- WeekNumber ist vollständig kostenlos und Open Source. Spenden sind willkommen!* 99 | 100 | [![Spenden](https://img.shields.io/badge/donate_via-paypal_or_card-blue)](https://www.paypal.com/donate?hosted_button_id=7PN65YXN64DBG) __⟵__ _**Hier klicken, um zu spenden!**_ 101 | 102 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G74W5F8) __⟵__ _**Hier klicken, um mir einen Kaffee zu kaufen!**_ 103 | 104 | ## Statistik 105 | [![Open issues](https://img.shields.io/github/issues/voltura/WeekNumber)](https://github.com/voltura/WeekNumber/issues) 106 | [![Code Quality](https://img.shields.io/github/workflow/status/voltura/WeekNumber/CodeQL)]() 107 | [![Website Status](https://img.shields.io/website?url=https%3A%2F%2Fvoltura.github.io%2FWeekNumber%2F)]() 108 | 109 | [![Anzahl der Programmiersprachen](https://img.shields.io/github/languages/count/voltura/WeekNumber)]() 110 | [![Top-Programmiersprache](https://img.shields.io/github/languages/top/voltura/WeekNumber)]() 111 | [![Code-Größe](https://img.shields.io/github/languages/code-size/voltura/WeekNumber)]() 112 | [![Anzahl der Forks](https://img.shields.io/github/forks/voltura/WeekNumber)]() 113 | [![Anzahl der Stars](https://img.shields.io/github/stars/voltura/WeekNumber)]() 114 | [![goto counter](https://img.shields.io/github/search/voltura/WeekNumber/goto)]() 115 | [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fvoltura%2FWeekNumber%2Fhit-counter&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)]() 116 | ![Letzter Commit auf GitHub](https://img.shields.io/github/last-commit/voltura/WeekNumber?color=red) 117 | 118 | ![Besucher](https://estruyf-github.azurewebsites.net/api/VisitorHit?user=volturaf&repo=WeekNumber&countColorcountColor&countColor=%235690f2) 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 🌍[English](README.md) ∙ [Deutsch](README.de-DE.md) ∙ [Svenska](README.sv-SE.md) 2 | 3 | # WeekNumber 4 | Windows 11/10 system tray area application that displays the current week number 5 | 6 | WeekNumber ![image](https://user-images.githubusercontent.com/2292809/120940539-0f071200-c71e-11eb-8b03-8f24b9fb36ad.png) 7 | 8 | 9 | [![Latest release ZIP](https://img.shields.io/github/v/release/voltura/WeekNumber?label=download%20latest%20release&style=for-the-badge)](https://github.com/voltura/weeknumber/releases/latest/download/WeekNumber_v1.6.6.9.zip) 10 | 11 | [![Github All Releases](https://img.shields.io/github/downloads/voltura/WeekNumber/total.svg)]() 12 | [![License](https://img.shields.io/badge/licence-MIT-green)]() 13 | 14 | ## Features 15 | Always see the current week number in the system tray area in Windows taskbar and lookup the week number for any other date via double-click on the application icon. 16 | 17 | Options to start with Windows, customize icon colors, language, notifications, calendar rules and more. For details see _**Help section**_ below. 18 | 19 | ### Supported Languages 20 | - English 21 | - Deutsch 22 | - Swedish 23 | 24 | _If you want to contribute with another language, please create an Issue on Github and I'll contact you!_ 25 | 26 | ## Screenshots 27 | #### System tray area icon with default colors 28 | ![Taskbar icon](https://user-images.githubusercontent.com/2292809/120904782-473f1f80-c64e-11eb-9256-c3d0ddab2124.png) 29 | #### Context menu - accessible via right-click on icon - with language selection 30 | ![Context menu](https://github.com/user-attachments/assets/53a8908f-0674-4563-b458-a13b93da5248) 31 | #### Find out week number for any date 32 | ![Weeknumber form](https://github.com/user-attachments/assets/918860bb-9926-44c0-8363-84d3ecfed81f) 33 | 34 | #### System tray area icon with customized colors 35 | ![Custom colors #1](https://user-images.githubusercontent.com/2292809/118048718-f4d74f80-b37c-11eb-8b36-211250ff25c5.png) ![Custom colors #2](https://user-images.githubusercontent.com/2292809/120920791-e997eb00-c6c0-11eb-889e-9a3e67787033.png) ![Custom colors #3](https://user-images.githubusercontent.com/2292809/120921288-498f9100-c6c3-11eb-8451-d2c3e19fba30.png) 36 | #### Icon color picker, possible to define and use custom colors; both icon text and background can be customized 37 | ![Color picker](https://user-images.githubusercontent.com/2292809/118050315-4e407e00-b37f-11eb-8ac9-17cc1a08aa08.png) 38 | 39 | ## Installation 40 | After download of WeekNumber_v1.6.6.9.zip via [*Download latest release*](https://github.com/voltura/weeknumber/releases/latest/download/WeekNumber_v1.6.6.9.zip) first unzip the archive, then run WeekNumber.exe. 41 | To remove the application just delete the executable and other files extracted from the zip archive and the generated application configuration file WeekNumber.exe.config. 42 | 43 | ### Download notes 44 | Choose to keep the file downloaded if prompted - it will look similar to this (depends on your web browser and settings) 45 | 46 | ![Keep file if prompted #1](https://user-images.githubusercontent.com/2292809/120716901-fa7d0c80-c4c6-11eb-9232-f279f959f0a6.png) 47 | 48 | 49 | ### Security notes / alternative lightweight version 50 | Microsoft Defender / Windows Security could identify application as a virus, trojan and/or malware which is *not* the case. 51 | I have created a lightweight version that does not trigger any false alarm, this version only can display the current week number in the task area, nothing else. 52 | Not autostart with Windows (it can manually be made to start with Windows - google how). 53 | Nor do the lightweight version have options to change icon colors or anything else that the full version of WeekNumber can do. 54 | 55 | See more [here](https://voltura.github.io/WeekNumberLite2/) if interested. 56 | 57 | ## Help section 58 | All application features are accessible via right-click on the application icon residing in the system tray area in Windows taskbar. 59 | If the application icon is not visible then press the ^ symbol on the system tray area, click and hold on the application icon and then drag it to the visible system tray area to pin it there. 60 | 61 | ### Context menu options: 62 | - **About WeekNumber** - _Displays version information_ 63 | - **Settings** 64 | - **Start with Windows** - _If ticked, the application starts automatically with Windows_ 65 | - **Language** - _Change language used by the application_ 66 | - **English** 67 | - **Deutsch** 68 | - **Svenska** - _Swedish_ 69 | - **Application log** 70 | - **Use application log** - _Application writes to a log file if ticked_ 71 | - **Show application log** - _If above is ticked, opens the application log file in a text editor; quite technical_ 72 | - **Notifications** - _Control the application notification messages in sub-menus_ 73 | - **Display startup notification** - _If ticked, the application will show a notification when started_ 74 | 75 | 76 | 77 | - **Display new week notification** - _If ticked, a notification will be shown when the week changes_ 78 | 79 | 80 | 81 | - **Use silent notifications** - _If ticked, any notifications for this application will not trigger system sounds to be played_ 82 | - **Use small / large taskbar buttons** - _Toogles Windows taskbar size and also adjusts the application icon resolution to match. Having trouble seeing the week number? Try using large taskbar buttons_ 83 | - **Export settings...** - _Option to export / backup the current application settings_ 84 | - **Import settings...** - _Option to import previously exported / backed up application settings_ 85 | - **Calendar** - _Calendar rules used by the application; per default the application uses the systems regional settings to figure this out, but it can be manually overridden here_ 86 | - **First Day Of Week** - _Calendar rule, select what day a week starts on_ 87 | - **Calendar week rule** - _Additional calendar rule that tells what rule is used for the first week of a year_ 88 | - **Icon** - _Application icon settings_ 89 | - **Icon colors** - _Allows user to change icon background and foreground color or reset colors used back to default in sub-menus_ 90 | - **Icon resolution** - _Possibility to tweak the WeekNumber icon resolution, if the icon is fuzzy setting a higher or lower resolution can help with apperance_ 91 | - **Graphics settings** - _Possibility to tweak icon graphics settings used by the application when drawing the week number icon_ 92 | - **Smoothing mode** 93 | - **Compositing Quality** 94 | - **Interpolation Mode** 95 | - **Text Contrast** 96 | - **Save icon...** - _Saves the current WeekNumber icon displayed to a .ico file_ 97 | - **Get week number for date...** - _Get week number for specified date_ 98 | 99 | 100 | - **Exit WeekNumber** - _Closes the application. Start it again from the Windows Start Menu_ 101 | 102 | ## Donations 103 | *- WeekNumber is completely free and open source. Donations are very much appreciated!* 104 | 105 | [![Donate](https://img.shields.io/badge/donate_via-paypal_or_card-blue)](https://www.paypal.com/donate?hosted_button_id=7PN65YXN64DBG) __⟵__ _**Press here to donate!**_ 106 | 107 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G74W5F8) __⟵__ _**Press here to buy me a coffee!**_ 108 | 109 | ## Statistics 110 | [![Open issues](https://img.shields.io/github/issues/voltura/WeekNumber)](https://github.com/voltura/WeekNumber/issues) 111 | [![Code Quality](https://img.shields.io/github/workflow/status/voltura/WeekNumber/CodeQL)]() 112 | [![Website Status](https://img.shields.io/website?url=https%3A%2F%2Fvoltura.github.io%2FWeekNumber%2F)]() 113 | 114 | [![Number of programming langauges](https://img.shields.io/github/languages/count/voltura/WeekNumber)]() 115 | [![Top programming language](https://img.shields.io/github/languages/top/voltura/WeekNumber)]() 116 | [![Code size](https://img.shields.io/github/languages/code-size/voltura/WeekNumber)]() 117 | [![Number of repo forks](https://img.shields.io/github/forks/voltura/WeekNumber)]() 118 | [![Number of repo stars](https://img.shields.io/github/stars/voltura/WeekNumber)]() 119 | [![goto counter](https://img.shields.io/github/search/voltura/WeekNumber/goto)]() 120 | [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fvoltura%2FWeekNumber%2Fhit-counter&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)]() 121 | ![GitHub last commit](https://img.shields.io/github/last-commit/voltura/WeekNumber?color=red) 122 | 123 | ![Visitors](https://estruyf-github.azurewebsites.net/api/VisitorHit?user=volturaf&repo=WeekNumber&countColorcountColor&countColor=%235690f2) 124 | -------------------------------------------------------------------------------- /README.sv-SE.md: -------------------------------------------------------------------------------- 1 | 🌍[English](README.md) ∙ [Deutsch](README.de-DE.md) ∙ [Svenska](README.sv-SE.md) 2 | 3 | # WeekNumber 4 | Windows 11/10 systemfältsapplikation som visar aktuellt veckonummer 5 | 6 | WeekNumber ![image](https://user-images.githubusercontent.com/2292809/121431601-e8451780-c979-11eb-9734-f30304c348d1.png) 7 | 8 | [![Latest release ZIP](https://img.shields.io/github/v/release/voltura/WeekNumber?label=ladda%20ner%20senaste%20versionen&style=for-the-badge)](https://github.com/voltura/weeknumber/releases/latest/download/WeekNumber_v1.6.6.9.zip) 9 | 10 | [![Github All Releases](https://img.shields.io/github/downloads/voltura/WeekNumber/total.svg)]() 11 | [![License](https://img.shields.io/badge/licence-MIT-green)]() 12 | 13 | ## Funktioner 14 | Aktuellt veckonummer visas som en ikon i systemfältet i Windows aktivitetsfält. 15 | Slå upp veckonummer för andra datum genom att dubbel-klicka på ikonen. 16 | 17 | Ställ in att starta med Windows, anpassa ikonfärger, språk, notiser, kalender-regler och mycket mer. För detaljerad beskrivning se _**Hjälpavsnitt**_ nedan. 18 | 19 | ### Språkstöd 20 | - Engelska 21 | - Tyska 22 | - Svenska 23 | 24 | _Om du vill bidra med översättning till ett annat språk, vänligen skapa ett ärende på GitHub så kontaktar jag dig!_ 25 | 26 | ## Skärmbilder 27 | #### Ikon med standard-färger 28 | ![Taskbar icon](https://user-images.githubusercontent.com/2292809/120904782-473f1f80-c64e-11eb-9256-c3d0ddab2124.png) 29 | 30 | #### Högerklicks-meny - Inställningsmeny med språkval 31 | ![Högerklicks-menu](https://github.com/user-attachments/assets/d536981f-7566-4709-95a9-aea89b418280) 32 | 33 | #### Ta reda på veckonummer för valfritt datum 34 | ![Weeknumber formulär](https://user-images.githubusercontent.com/2292809/121432297-c730f680-c97a-11eb-9530-005d5062039b.png) 35 | 36 | #### Exempel på ikoner med anpassade färger 37 | ![Custom colors #1](https://user-images.githubusercontent.com/2292809/118048718-f4d74f80-b37c-11eb-8b36-211250ff25c5.png) ![Custom colors #2](https://user-images.githubusercontent.com/2292809/120920791-e997eb00-c6c0-11eb-889e-9a3e67787033.png) ![Custom colors #3](https://user-images.githubusercontent.com/2292809/120921288-498f9100-c6c3-11eb-8451-d2c3e19fba30.png) 38 | 39 | #### Färgval, med möjlighet att definiera och nyttja egendefinierade färger; både ikonens text och bakgrundsfärg kan ändras 40 | ![Färgväljare](https://user-images.githubusercontent.com/2292809/121435848-dd8d8100-c97f-11eb-8cf9-5ce7178aea73.png) 41 | 42 | ## Installation 43 | Ladda ner zip, extrahera och kör WeekNumber.exe. 44 | 45 | En notis visas då WeekNumber är startad 46 | 47 | ![image](https://user-images.githubusercontent.com/2292809/121437224-3a8a3680-c982-11eb-898c-84d45d33611f.png) 48 | 49 | Aktuellt veckonummer visas nu bland systemfältets ikoner, ser du inte veckonummer tryck på taktecknet (^) i systemfältet och klicka-håll och dra ned ikonen så den blir synlig. 50 | 51 | 52 | ## Hjälpavsnitt 53 | Alla funktioner är tillgängliga genom att höger-klicka på applikationens ikon i Windows systemfält. 54 | Om du inte ser applikationens ikon så tryck på taktecknet (^) vid systemfältet, klicka och håll inne musknappen medans du drar ikonen ned i systemfältet; då kommer ikonen fästas där och vara synlig. 55 | 56 | ### Högerklicks-meny: 57 | - **Om WeekNumber** - _Visar versionsinformation_ 58 | - **Inställningar** 59 | - **Starta med Windows** - _Om ikryssad så startar applikationen automatiskt med Windows_ 60 | - **Språk** - _Ändrar vilket språk som applikationen använder_ 61 | - **English** - _Engelska_ 62 | - **German** - _Tyska_ 63 | - **Svenska** 64 | - **Applikationslogg** 65 | - **Använd applikationlogg** - _Om ikryssad så skriver applikationen till en loggfil_ 66 | - **Visa applikationslogg** - _Om ovan är ikryssad så visas applikationens loggfil i en texteditor (teknisk loggfil)_ 67 | - **Notiser** 68 | - **Visa uppstartsnotis** - _Om ikryssad så visar applikationen en uppstartsnotis_ 69 | 70 | 71 | 72 | - **Visa ny veckonotis** - _Om ikryssad så visas en notis då aktuell vecka ändras_ 73 | 74 | 75 | 76 | - **Använd tysta notiser** - _Om ikryssad så spelas inte något ljud upp då denna applikation visar notiser_ 77 | - **Använd små / stora aktivitetsfältsikoner** - _Skiftar mellan stora och små aktivitetsfältsikoner. Har du svårt att se veckonumret? Testa att använda stora aktivitetsfältsikoner_ 78 | - **Exportera inställningar..." - _Möjlighet att exportera / spara kopia av aktuella applikationsinställningar_ 79 | - **Importera inställningar..." - _Möjlighet att importera tidigare exporterad / sparad kopia av applikationsinställningar_ 80 | - **Kalender** - _Kalenderregler som appliationen använder sig av; vanligtvis tas detta från de regionella inställningar som är inställda på systemet, men de går alltså att justera manuellt här_ 81 | - **'Första-dag-i-vecka'-regel** - _Kalenderregel, välj dag som en vecka startar på_ 82 | - **'Årets-första-vecka'-regel** - _Ytterligare kalender-regel som anger vilket regelverk som ska nyttjas för årets första vecka_ 83 | - **Ikon** - _Inställningar för applikationsikon_ 84 | - **Ikonfärger** - _Möjlighet att anpassa appliktionens färger_ 85 | - **Ikonupplösning** - _Möjlighet att anpassa WeekNumber-ikonens upplösning, om ikonen ser suddig ut kan en annan upplösning ge bättre ikonutseende_ 86 | - **Grafikinställningar** - _Möjlighet att anpassa grafikalternativ som nyttjas då ikonen ritas av applikationen_ 87 | - **Utjämningsläge** 88 | - **Kompositkvalitet** 89 | - **Interpolationsläge** 90 | - **Textkontrast** 91 | - **Spara ikon...** - _Sparar aktuell WeekNumber-ikon till en .ico fil_ 92 | - **Få veckonummer för datum...** - _Visa veckonummer för angivet datum_ 93 | 94 | 95 | - **Avsluta WeekNumber** - _Avslutar applikationen. Starta igen från Windows Startmeny_ 96 | 97 | ## Donationer 98 | *- WeekNumber är fullständigt gratis och öppen källkod. Donationer uppskattas!* 99 | 100 | [![Donate](https://img.shields.io/badge/donate_via-paypal_or_card-blue)](https://www.paypal.com/donate?hosted_button_id=7PN65YXN64DBG) __⟵__ _**Tryck här för att donera!**_ 101 | 102 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G74W5F8) __⟵__ _**Tryck här för att köpa mig en kaffe!**_ 103 | 104 | ## Statistik 105 | [![Open issues](https://img.shields.io/github/issues/voltura/WeekNumber)](https://github.com/voltura/WeekNumber/issues) 106 | [![Code Quality](https://img.shields.io/github/workflow/status/voltura/WeekNumber/CodeQL)]() 107 | [![Website Status](https://img.shields.io/website?url=https%3A%2F%2Fvoltura.github.io%2FWeekNumber%2F)]() 108 | 109 | [![Number of programming langauges](https://img.shields.io/github/languages/count/voltura/WeekNumber)]() 110 | [![Top programming language](https://img.shields.io/github/languages/top/voltura/WeekNumber)]() 111 | [![Code size](https://img.shields.io/github/languages/code-size/voltura/WeekNumber)]() 112 | [![Number of repo forks](https://img.shields.io/github/forks/voltura/WeekNumber)]() 113 | [![Number of repo stars](https://img.shields.io/github/stars/voltura/WeekNumber)]() 114 | [![goto counter](https://img.shields.io/github/search/voltura/WeekNumber/goto)]() 115 | [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fvoltura%2FWeekNumber%2Fhit-counter&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)]() 116 | ![GitHub last commit](https://img.shields.io/github/last-commit/voltura/WeekNumber?color=red) 117 | 118 | ![Visitors](https://estruyf-github.azurewebsites.net/api/VisitorHit?user=volturaf&repo=WeekNumber&countColorcountColor&countColor=%235690f2) 119 | -------------------------------------------------------------------------------- /Resources/Resources.de-DE.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Resources/Resources.de-DE.Designer.cs -------------------------------------------------------------------------------- /Resources/Resources.de-DE.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | WeekNumber von Voltura AB 122 | 123 | Copyright © Voltura AB 2018-2024 124 | 125 | 126 | Über WeekNumber 127 | 128 | 129 | ApplicationLog 130 | 131 | 132 | Anwendungs Log 133 | 134 | 135 | Blue 136 | 137 | 138 | IconBackground 139 | 140 | 141 | IconBackgroundBlue 142 | 143 | 144 | IconBackgroundGreen 145 | 146 | 147 | Hintergrund 148 | 149 | 150 | IconBackgroundRed 151 | 152 | 153 | Kalender Wochen Regeln 154 | 155 | 156 | Überprüfen Sie, ob Sie über einen Webbrowser zu dieser Adresse navigieren können: 157 | 158 | 159 | Hole Kalender Woche für Datum... 160 | 161 | 162 | Schließen 163 | 164 | 165 | Symbol Farben 166 | 167 | 168 | Tag 169 | 170 | 171 | DisplayStartupNotification 172 | 173 | 174 | Zeige Start Benachrichtigung 175 | 176 | 177 | Beende WeekNumber 178 | 179 | 180 | Aktualisierung der Symbolauflösung fehlgeschlagen 181 | 182 | 183 | Konnte Windows nicht über die Änderung der Taskleistensymbolgröße informieren. 184 | 185 | Bitte melden Sie dies an feedback@voltura.se! 186 | 187 | 188 | Konnte Symbol nicht festlegen. 189 | 190 | Bitte melden Sie dies an feedback@voltura.se! 191 | 192 | 193 | Konnte Kalenderwochenregel-Einstellung nicht festlegen. 194 | 195 | Bitte melden Sie dies an feedback@voltura.se! 196 | 197 | 198 | Farbe konnte nicht aktualisiert werden. 199 | 200 | 201 | Konnte Einstellung für den ersten Wochentag nicht aktualisieren. 202 | 203 | Bitte melden Sie dies an feedback@voltura.se! 204 | 205 | 206 | Konnte Registrierung nicht aktualisieren. 207 | 208 | Bitte melden Sie dies an feedback@voltura.se! 209 | 210 | 211 | Erster Tag 212 | 213 | 214 | Erster Tag der Woche 215 | 216 | 217 | Erste 4-Tage Woche 218 | 219 | 220 | Erste volle Woche 221 | 222 | 223 | IconForeground 224 | 225 | 226 | IconForegroundBlue 227 | 228 | 229 | IconForegroundGreen 230 | 231 | 232 | Foreground 233 | 234 | 235 | IconForegroundRed 236 | 237 | 238 | Freitag 239 | 240 | 241 | Green 242 | 243 | 244 | Icon 245 | 246 | 247 | 128x128 248 | 249 | 250 | 16x16 251 | 252 | 253 | 20x20 254 | 255 | 256 | 24x24 257 | 258 | 259 | 256x256 260 | 261 | 262 | 32x32 263 | 264 | 265 | 40x40 266 | 267 | 268 | 48x48 269 | 270 | 271 | 512x512 272 | 273 | 274 | 64x64 275 | 276 | 277 | IconResolution 278 | 279 | 280 | Symbol Auflösung 281 | 282 | 283 | Deine Version: 284 | 285 | 286 | Sie haben die neueste Version! 287 | 288 | 289 | MaxLogFileSizeInMB 290 | 291 | 292 | Montag 293 | 294 | 295 | Monat 296 | 297 | 298 | Es ist eine neue Version verfügbar 299 | 300 | 301 | Entschuldigung, diese Funktion ist noch nicht implementiert. 302 | 303 | 304 | OK 305 | 306 | 307 | Anwendungswebseite öffnen 308 | 309 | 310 | Red 311 | 312 | 313 | Colors reset 314 | 315 | 316 | Farben zurücksetzen 317 | 318 | 319 | Samstag 320 | 321 | 322 | Symbol speichern... 323 | 324 | 325 | Bitte wählen Sie die Hintergrundfarbe aus 326 | 327 | 328 | Bitte wählen Sie ein Datum, um die Wochennummer anzuzeigen 329 | 330 | 331 | Bitte wählen Sie die Vordergrundfarbe aus 332 | 333 | 334 | - 335 | 336 | 337 | Einstellungen 338 | 339 | 340 | ShowLog 341 | 342 | 343 | Zeige das Anwendungsprotokoll 344 | 345 | 346 | UseSilentNotifications 347 | 348 | 349 | Benutze versteckte Benachrichtigungen 350 | 351 | 352 | Benachrichtigungen 353 | 354 | 355 | Rechtsklick auf das Symbol im System-Tray für Funktionen und Einstellungen 356 | 357 | 358 | StartWithWindows 359 | 360 | 361 | Starte mit Windows 362 | 363 | 364 | Sonntag 365 | 366 | 367 | Benutze große Taskbar 368 | 369 | 370 | Benutze kleine Taskbar 371 | 372 | 373 | Donnerstag 374 | 375 | 376 | Dienstag 377 | 378 | 379 | Irgendetwas ist schiefgelaufen. Bitte an feedback@voltura.se melden! 380 | 381 | 382 | UseApplicationLog 383 | 384 | 385 | Benutze Anwendungsprotokoll 386 | 387 | 388 | version 389 | 390 | 391 | Mittwoch 392 | 393 | 394 | Woche 395 | 396 | 397 | Jahr 398 | 399 | 400 | Kalender 401 | 402 | 403 | Symbol 404 | 405 | 406 | DisplayWeekChangedNotification 407 | 408 | 409 | Zeige neue Woche Benachrichtigung 410 | 411 | 412 | Schließen Sie diese Anwendung und führen Sie sie manuell aus 413 | 414 | 415 | information 416 | 417 | 418 | Installationsprogramm-Prüfsumme inkorrekt, automatische Installation fehlgeschlagen. 419 | 420 | 421 | um die Anwendung zu aktualisieren. 422 | 423 | 424 | Versuchen Sie, es manuell über einen Webbrowser von dieser Adresse herunterzuladen: 425 | 426 | 427 | Umwandlung fehlgeschlagen 428 | 429 | 430 | en-US 431 | 432 | 433 | English 434 | 435 | 436 | Language 437 | 438 | 439 | Sprache 440 | 441 | 442 | WeekNumber von Voltura AB 443 | 444 | 445 | sv-SE 446 | 447 | 448 | Svenska 449 | 450 | 451 | de-DE 452 | 453 | 454 | Deutsch 455 | 456 | 457 | CompositingQuality 458 | 459 | 460 | Assume Linear 461 | 462 | 463 | Standard 464 | 465 | 466 | Gamma korrigiert 467 | 468 | 469 | Hohe Qualität 470 | 471 | 472 | Hohe Geschwindigkeit 473 | 474 | 475 | Kompositionsqualität 476 | 477 | 478 | Grafik Einstellungen 479 | 480 | 481 | InterpolationMode 482 | 483 | 484 | Bicubic 485 | 486 | 487 | Bilinear 488 | 489 | 490 | Standard 491 | 492 | 493 | Hoch 494 | 495 | 496 | Hohe Qualität Bicubic 497 | 498 | 499 | Hohe Qualität Bilinear 500 | 501 | 502 | Niedrig 503 | 504 | 505 | Interpolations Modus 506 | 507 | 508 | Nächster Nachbar 509 | 510 | 511 | Anti Alias 512 | 513 | 514 | SmoothingMode 515 | 516 | 517 | Standard 518 | 519 | 520 | Hohe Qualität 521 | 522 | 523 | Hohe Geschwindigkeit 524 | 525 | 526 | Glättungsmodus 527 | 528 | 529 | Keine 530 | 531 | 532 | TextContrast 533 | 534 | 535 | 1 536 | 537 | 538 | 2 539 | 540 | 541 | 3 542 | 543 | 544 | 4 545 | 546 | 547 | 5 548 | 549 | 550 | Text Kontrast 551 | 552 | 553 | Exportiere Einstellungen... 554 | 555 | 556 | Export der Einstellungen fehlgeschlagen! 557 | 558 | 559 | Import der Einstellungen fehlgeschlagen! 560 | 561 | 562 | Importiere Einstellungen... 563 | 564 | 565 | Einstellungen erfolgreich exportiert! 566 | 567 | 568 | Einstellungen erfolgreich importiert! 569 | 570 | 571 | IconBackgroundAlpha 572 | 573 | 574 | Benutze Transparenten Hintergrund 575 | 576 | -------------------------------------------------------------------------------- /Resources/Resources.en-US.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Resources/Resources.en-US.Designer.cs -------------------------------------------------------------------------------- /Resources/Resources.sv-SE.Designer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Resources/Resources.sv-SE.Designer.cs -------------------------------------------------------------------------------- /Resources/WeekNumber.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Resources/WeekNumber.bmp -------------------------------------------------------------------------------- /Resources/infoIconWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Resources/infoIconWhite.png -------------------------------------------------------------------------------- /Resources/weekicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Resources/weekicon.ico -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only latest version will receive updates. Make sure you are on latest version before reporting an issue. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | Register an issue here in the WeekNumber repo on GitHub, as detailed as possible. 10 | -------------------------------------------------------------------------------- /Settings.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using Microsoft.Win32; 4 | using System; 5 | using System.Configuration; 6 | using System.Globalization; 7 | using System.IO; 8 | using System.Windows.Forms; 9 | using System.Xml; 10 | 11 | #endregion Using statements 12 | 13 | namespace WeekNumber 14 | { 15 | internal static class Settings 16 | { 17 | #region Internal static property that updates registry for application to start when Windows start 18 | 19 | internal static bool StartWithWindows 20 | { 21 | get 22 | { 23 | bool startWithWindows = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\", Application.ProductName, null) != null; 24 | return startWithWindows; 25 | } 26 | set 27 | { 28 | using (RegistryKey registryKey = Registry.CurrentUser) 29 | using (RegistryKey regRun = registryKey?.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run\", true)) 30 | { 31 | if (value) 32 | { 33 | regRun?.SetValue(Application.ProductName, Application.ExecutablePath); 34 | UpdateSetting(Resources.StartWithWindows, true.ToString()); 35 | } 36 | else 37 | { 38 | if (regRun?.GetValue(Application.ProductName) != null) 39 | regRun?.DeleteValue(Application.ProductName); 40 | UpdateSetting(Resources.StartWithWindows, false.ToString()); 41 | } 42 | registryKey?.Flush(); 43 | } 44 | } 45 | } 46 | 47 | #endregion Internal static property that updates registry for application to start when Windows start 48 | 49 | #region Internal static methods 50 | 51 | internal static bool SettingIsValue(string setting, string value) 52 | { 53 | CreateSettings(); 54 | return ConfigurationManager.AppSettings.Get(setting) == value; 55 | } 56 | 57 | internal static string GetSetting(string setting) 58 | { 59 | CreateSettings(); 60 | return ConfigurationManager.AppSettings.Get(setting); 61 | } 62 | 63 | internal static int GetIntSetting(string setting, int defaultValue = 0) 64 | { 65 | if (int.TryParse(GetSetting(setting), out int settingInt)) 66 | { 67 | return settingInt; 68 | } 69 | return defaultValue; 70 | } 71 | 72 | internal static void UpdateSetting(string setting, string value) 73 | { 74 | CreateSettings(); 75 | Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 76 | KeyValueConfigurationCollection settings = configFile.AppSettings.Settings; 77 | settings[setting].Value = value; 78 | configFile.Save(ConfigurationSaveMode.Modified); 79 | ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name); 80 | Log.Info = $"'{setting}' set to '{value}'"; 81 | } 82 | 83 | /// 84 | /// Creates a backup of the applications current settings file 85 | /// 86 | internal static bool BackupSettings(string fileName = "") 87 | { 88 | Log.LogCaller(); 89 | string settingsFile = Application.ExecutablePath + ".config"; 90 | string settingsBackupDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Temp"); 91 | string settingsFileBackup = Path.Combine(settingsBackupDir, Application.ExecutablePath + ".config.bak"); 92 | if (fileName != string.Empty) 93 | { 94 | settingsBackupDir = Path.GetDirectoryName(fileName); 95 | settingsFileBackup = fileName; 96 | } 97 | try 98 | { 99 | if (settingsFile.Equals(settingsFileBackup, StringComparison.InvariantCultureIgnoreCase)) 100 | { 101 | Log.ErrorString = $"Cannot create copy of settings file since it has same fullpath as original: '{settingsFileBackup}'"; 102 | return false; 103 | } 104 | if (File.Exists(settingsFile)) 105 | { 106 | if (!Directory.Exists(settingsBackupDir)) Directory.CreateDirectory(settingsBackupDir); 107 | File.Copy(settingsFile, settingsFileBackup, true); 108 | Log.Info = $"Copy of settings file created: '{settingsFileBackup}'."; 109 | return true; 110 | } 111 | } 112 | catch (Exception ex) 113 | { 114 | Log.Error = ex; 115 | } 116 | Log.ErrorString = $"Failed to create copy of settings file: '{settingsFileBackup}'"; 117 | return false; 118 | } 119 | 120 | internal static void RestoreBackupSettings() 121 | { 122 | Log.LogCaller(); 123 | string settingsFile = Application.ExecutablePath + ".config"; 124 | string settingsBackupDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Temp"); 125 | string settingsFileBackup = Path.Combine(settingsBackupDir, Application.ExecutablePath + ".config.bak"); 126 | try 127 | { 128 | if (!File.Exists(settingsFileBackup)) return; 129 | if (!File.Exists(settingsFile)) CreateSettings(); 130 | XmlDocument doc = new XmlDocument(); 131 | doc.Load(settingsFileBackup); 132 | XmlNodeList nodeList = doc.SelectNodes("/configuration/appSettings"); 133 | foreach (XmlNode node in nodeList) 134 | foreach (XmlNode child in node.ChildNodes) 135 | if (child.Name == "add") 136 | { 137 | XmlAttributeCollection attribs = child.Attributes; 138 | if (attribs.Count == 2) 139 | { 140 | string settingsName = attribs[0].Value; 141 | string settingsValue = attribs[1].Value; 142 | try 143 | { 144 | UpdateSetting(settingsName, settingsValue); 145 | } 146 | catch (Exception ex) 147 | { 148 | Log.Error = ex; 149 | } 150 | } 151 | } 152 | File.Delete(settingsFileBackup); 153 | Log.Info = "Removed backup settings file after restore."; 154 | } 155 | catch (Exception ex) 156 | { 157 | Log.Error = ex; 158 | } 159 | } 160 | 161 | /// 162 | /// Import settings from file 163 | /// 164 | /// 165 | /// 166 | internal static bool ImportSettings(string fileToImport) 167 | { 168 | Log.LogCaller(); 169 | string settingsFile = Application.ExecutablePath + ".config"; 170 | try 171 | { 172 | if (!File.Exists(fileToImport)) 173 | { 174 | Log.ErrorString = $"Settings file '{fileToImport}' not found, no import made."; 175 | return false; 176 | } 177 | if (!File.Exists(settingsFile)) CreateSettings(); 178 | XmlDocument doc = new XmlDocument(); 179 | doc.Load(fileToImport); 180 | XmlNodeList nodeList = doc.SelectNodes("/configuration/appSettings"); 181 | foreach (XmlNode node in nodeList) 182 | foreach (XmlNode child in node.ChildNodes) 183 | if (child.Name == "add") 184 | { 185 | XmlAttributeCollection attribs = child.Attributes; 186 | if (attribs.Count == 2) 187 | { 188 | string settingsName = attribs[0].Value; 189 | string settingsValue = attribs[1].Value; 190 | try 191 | { 192 | UpdateSetting(settingsName, settingsValue); 193 | } 194 | catch (Exception ex) 195 | { 196 | Log.Error = ex; 197 | } 198 | } 199 | } 200 | } 201 | catch (Exception ex) 202 | { 203 | Log.ErrorString = $"Failed to import settings file '{fileToImport}'."; 204 | Log.Error = ex; 205 | return false; 206 | } 207 | Log.Info = $"Imported settings from '{fileToImport}'."; 208 | return true; 209 | } 210 | 211 | /// 212 | /// Set application culture info 213 | /// 214 | internal static void SetCultureInfoFromSystemOrSettings() 215 | { 216 | Log.LogCaller(); 217 | try 218 | { 219 | string language = GetSetting(Resources.Language); 220 | if (string.IsNullOrEmpty(language)) // First run there is no setting for language 221 | { 222 | if (CultureInfo.CurrentCulture.Name == Resources.Swedish) 223 | { 224 | language = Resources.Swedish; 225 | } 226 | else if (CultureInfo.CurrentCulture.Name == Resources.German) 227 | { 228 | language = Resources.German; 229 | } 230 | else 231 | { 232 | language = Resources.English; 233 | } 234 | UpdateSetting(Resources.Language, language); 235 | } 236 | System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(language, false); 237 | System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(language, false); 238 | Log.Info = $"Set application Culture to '{language}'"; 239 | } 240 | catch (Exception ex) 241 | { 242 | Log.Error = ex; 243 | System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(Resources.English, false); 244 | System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(Resources.English, false); 245 | Log.Info = $"Set application Culture to '{Resources.English}'"; 246 | } 247 | } 248 | 249 | 250 | #endregion Internal static methods 251 | 252 | #region Private method that creates the application settings file if needed 253 | 254 | private static void CreateSettings() 255 | { 256 | string settingsFile = Application.ExecutablePath + ".config"; 257 | if (!File.Exists(settingsFile) || !File.ReadAllText(settingsFile).Contains("Language")) 258 | { 259 | Log.LogCaller(); 260 | CultureInfo currentCultureInfo = CultureInfo.CurrentCulture; 261 | DayOfWeek firstDay = currentCultureInfo.DateTimeFormat.FirstDayOfWeek; 262 | CalendarWeekRule calendarWeekRule = currentCultureInfo.DateTimeFormat.CalendarWeekRule; 263 | string xml = $@" 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | "; 289 | File.Delete(settingsFile); 290 | File.WriteAllText(settingsFile, xml, System.Text.Encoding.UTF8); 291 | Log.Info = $"Created '{settingsFile}'"; 292 | } 293 | } 294 | 295 | #endregion Private method that creates the application settings file if needed 296 | } 297 | } -------------------------------------------------------------------------------- /TaskbarGui.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using Microsoft.Win32; 4 | using System; 5 | using System.Threading; 6 | using System.Windows.Forms; 7 | 8 | #region Test code 9 | /* 10 | using System.Reflection; 11 | using System.Runtime.InteropServices; 12 | using System.Drawing; 13 | */ 14 | #endregion Test code 15 | 16 | #endregion Using statements 17 | 18 | namespace WeekNumber 19 | { 20 | internal class TaskbarGui : IDisposable, IGui 21 | { 22 | #region Public event handler (update icon request) 23 | 24 | public event EventHandler UpdateRequest; 25 | 26 | #endregion Public event handler (update icon request) 27 | 28 | #region Private variables 29 | 30 | private NotifyIcon _notifyIcon; 31 | private readonly WeekNumberContextMenu _contextMenu; 32 | private int _latestWeek; 33 | 34 | #endregion Private variables 35 | 36 | #region Constructor 37 | 38 | internal TaskbarGui(int week, int iconResolution = (int)IconSize.Icon256) 39 | { 40 | Log.LogCaller(); 41 | _latestWeek = week; 42 | _contextMenu = new WeekNumberContextMenu(); 43 | _notifyIcon = GetNotifyIcon(_contextMenu.ContextMenu); 44 | UpdateIcon(week, ref _notifyIcon, iconResolution); 45 | _notifyIcon.DoubleClick += NotifyIcon_DoubleClick; 46 | 47 | #region Test code 48 | /* test code 49 | Rectangle rect =NotifyIconHelper.GetIconRect(_notifyIcon);*/ 50 | #endregion Test code 51 | 52 | if (Settings.SettingIsValue(Resources.DisplayStartupNotification, "True")) 53 | { 54 | DisplayUserInfoBalloonTip($"{_notifyIcon.Text}\r\n{Resources.StartupMessageText}"); 55 | } 56 | _contextMenu.SettingsChangedHandler += OnSettingsChange; 57 | } 58 | 59 | #endregion Constructor 60 | 61 | #region Display NotifyIcon BalloonTip 62 | 63 | private void DisplayUserInfoBalloonTip(string message) 64 | { 65 | Log.LogCaller(); 66 | bool siletMsg = Settings.SettingIsValue(Resources.UseSilentNotifications, "True"); 67 | object currentSound = null; 68 | if (siletMsg) 69 | { 70 | using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings", true)) 71 | { 72 | currentSound = regKey.GetValue("NOC_GLOBAL_SETTING_ALLOW_NOTIFICATION_SOUND"); 73 | regKey.SetValue("NOC_GLOBAL_SETTING_ALLOW_NOTIFICATION_SOUND", 0); 74 | regKey.Flush(); 75 | regKey.Close(); 76 | } 77 | } 78 | _notifyIcon.ShowBalloonTip(10000, Message.CAPTION, message, ToolTipIcon.None); 79 | if (siletMsg) 80 | { 81 | using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings", true)) 82 | { 83 | System.Threading.Thread.Sleep(1000); 84 | if (currentSound is null) 85 | { 86 | regKey.DeleteValue("NOC_GLOBAL_SETTING_ALLOW_NOTIFICATION_SOUND"); 87 | } 88 | else 89 | { 90 | regKey.SetValue("NOC_GLOBAL_SETTING_ALLOW_NOTIFICATION_SOUND", currentSound); 91 | } 92 | regKey.Flush(); 93 | regKey.Close(); 94 | } 95 | } 96 | } 97 | 98 | #endregion Display NotifyIcon BalloonTip 99 | 100 | #region Private event handlers 101 | 102 | private void OnSettingsChange(object sender, EventArgs e) 103 | { 104 | UpdateRequest?.Invoke(null, null); 105 | } 106 | private void NotifyIcon_DoubleClick(object sender, EventArgs e) 107 | { 108 | Forms.DateForm.Display(); 109 | } 110 | 111 | #endregion Private event handlers 112 | 113 | #region Public UpdateIcon method 114 | 115 | /// 116 | /// Updates icon on GUI with given week number 117 | /// 118 | /// The week number to display on icon 119 | /// The width and height of the icon 120 | /// Redraw context menu 121 | public void UpdateIcon(int weekNumber, int iconResolution = (int)IconSize.Icon256, bool redrawContextMenu = false) 122 | { 123 | UpdateIcon(weekNumber, ref _notifyIcon, iconResolution); 124 | if (redrawContextMenu) 125 | { 126 | _contextMenu.CreateContextMenu(); 127 | _notifyIcon.ContextMenu = _contextMenu.ContextMenu; 128 | } 129 | } 130 | 131 | #endregion Public UpdateIcon method 132 | 133 | #region Private UpdateIcon method 134 | 135 | private void UpdateIcon(int weekNumber, ref NotifyIcon notifyIcon, int iconResolution) 136 | { 137 | Log.LogCaller(); 138 | try 139 | { 140 | string weekDayPrefix = string.Empty; 141 | string longDateString = DateTime.Now.ToLongDateString(); 142 | const string SWEDISH_LONG_DATE_PREFIX_STRING = "den "; 143 | if (Thread.CurrentThread.CurrentUICulture.Name == Resources.Swedish || longDateString.StartsWith(SWEDISH_LONG_DATE_PREFIX_STRING)) 144 | { 145 | weekDayPrefix = Message.SWEDISH_DAY_OF_WEEK_PREFIX[(int)DateTime.Now.DayOfWeek]; 146 | } 147 | notifyIcon.Text = $"{Resources.Week} {weekNumber}\r\n{weekDayPrefix}{longDateString}"; 148 | System.Drawing.Icon prevIcon = notifyIcon.Icon; 149 | notifyIcon.Icon = WeekIcon.GetIcon(weekNumber, iconResolution); 150 | WeekIcon.CleanupIcon(ref prevIcon); 151 | } 152 | finally 153 | { 154 | if (_latestWeek != weekNumber) 155 | { 156 | if (Settings.SettingIsValue(Resources.DisplayWeekChangedNotification, "True")) 157 | { 158 | DisplayUserInfoBalloonTip(notifyIcon.Text); 159 | } 160 | _latestWeek = weekNumber; 161 | } 162 | } 163 | } 164 | 165 | #endregion Private UpdateIcon method 166 | 167 | #region Private helper property to create NotifyIcon 168 | 169 | private static NotifyIcon GetNotifyIcon(ContextMenu contextMenu) 170 | { 171 | return new NotifyIcon { Visible = true, ContextMenu = contextMenu }; 172 | } 173 | 174 | #endregion Private helper property to create NotifyIcon 175 | 176 | #region IDisposable methods 177 | 178 | /// 179 | /// Disposes the GUI resources 180 | /// 181 | public void Dispose() 182 | { 183 | Dispose(true); 184 | GC.SuppressFinalize(this); 185 | } 186 | 187 | protected virtual void Dispose(bool disposing) 188 | { 189 | if (!disposing) 190 | { 191 | return; 192 | } 193 | CleanupNotifyIcon(); 194 | _contextMenu.Dispose(); 195 | } 196 | 197 | private void CleanupNotifyIcon() 198 | { 199 | if (_notifyIcon != null) 200 | { 201 | _notifyIcon.Visible = false; 202 | if (_notifyIcon.Icon != null) 203 | { 204 | NativeMethods.DestroyIcon(_notifyIcon.Icon.Handle); 205 | _notifyIcon.Icon?.Dispose(); 206 | } 207 | _notifyIcon.ContextMenu?.MenuItems.Clear(); 208 | _notifyIcon.ContextMenu?.Dispose(); 209 | _notifyIcon.Dispose(); 210 | _notifyIcon = null; 211 | } 212 | } 213 | 214 | #endregion IDisposable methods 215 | } 216 | 217 | /* Use this to clear icon area instead, inspiration code only, need modification, but with area of icon then maybe move mouse over it programmatically instead of current more complex solution 218 | 219 | 220 | 221 | 222 | sealed class NotifyIconHelper 223 | { 224 | 225 | public static Rectangle GetIconRect(NotifyIcon icon) 226 | { 227 | RECT rect = new RECT(); 228 | NOTIFYICONIDENTIFIER notifyIcon = new NOTIFYICONIDENTIFIER(); 229 | 230 | notifyIcon.cbSize = Marshal.SizeOf(notifyIcon); 231 | //use hWnd and id of NotifyIcon instead of guid is needed 232 | notifyIcon.hWnd = GetHandle(icon); 233 | notifyIcon.uID = GetId(icon); 234 | 235 | int hresult = Shell_NotifyIconGetRect(ref notifyIcon, out rect); 236 | //rect now has the position and size of icon 237 | 238 | return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 239 | } 240 | 241 | private static int GetIconID(NotifyIcon icon) 242 | { 243 | RECT rect = new RECT(); 244 | NOTIFYICONIDENTIFIER notifyIcon = new NOTIFYICONIDENTIFIER(); 245 | 246 | notifyIcon.cbSize = Marshal.SizeOf(notifyIcon); 247 | //use hWnd and id of NotifyIcon instead of guid is needed 248 | notifyIcon.hWnd = GetHandle(icon); 249 | notifyIcon.uID = GetId(icon); 250 | 251 | int hresult = Shell_NotifyIconGetRect(ref notifyIcon, out rect); 252 | //rect now has the position and size of icon 253 | 254 | return notifyIcon.uID; 255 | } 256 | 257 | [StructLayout(LayoutKind.Sequential)] 258 | private struct RECT 259 | { 260 | public Int32 left; 261 | public Int32 top; 262 | public Int32 right; 263 | public Int32 bottom; 264 | } 265 | 266 | [StructLayout(LayoutKind.Sequential)] 267 | private struct NOTIFYICONIDENTIFIER 268 | { 269 | public Int32 cbSize; 270 | public IntPtr hWnd; 271 | public Int32 uID; 272 | public Guid guidItem; 273 | } 274 | 275 | [DllImport("shell32.dll", SetLastError = true)] 276 | private static extern int Shell_NotifyIconGetRect([In] ref NOTIFYICONIDENTIFIER identifier, [Out] out RECT iconLocation); 277 | 278 | private static FieldInfo windowField = typeof(NotifyIcon).GetField("window", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 279 | private static IntPtr GetHandle(NotifyIcon icon) 280 | { 281 | if (windowField == null) throw new InvalidOperationException("[Useful error message]"); 282 | NativeWindow window = windowField.GetValue(icon) as NativeWindow; 283 | 284 | if (window == null) throw new InvalidOperationException("[Useful error message]"); // should not happen? 285 | return window.Handle; 286 | } 287 | 288 | private static FieldInfo idField = typeof(NotifyIcon).GetField("id", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 289 | 290 | private static int GetId(NotifyIcon icon) 291 | { 292 | if (idField == null) throw new InvalidOperationException("[Useful error message]"); 293 | return (int)idField.GetValue(icon); 294 | } 295 | 296 | } 297 | 298 | */ 299 | } -------------------------------------------------------------------------------- /TaskbarUtil.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using Microsoft.Win32; 4 | using System; 5 | 6 | #endregion Using statements 7 | 8 | namespace WeekNumber 9 | { 10 | internal static class TaskbarUtil 11 | { 12 | #region Private registry constants 13 | 14 | private const string EXPLORER_ADVANCED_REG_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced"; 15 | private const string TASKBAR_SMALL_ICONS_REG_NAME = "TaskbarSmallIcons"; 16 | 17 | #endregion Private registry constants 18 | 19 | #region Internal taskbar method 20 | 21 | internal static void ToogleTaskbarIconSize() 22 | { 23 | try 24 | { 25 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey(EXPLORER_ADVANCED_REG_KEY, true)) 26 | { 27 | if (key is null) 28 | { 29 | Message.Show(Resources.FailedToUpdateRegistry); 30 | return; 31 | } 32 | int newValue = Math.Abs(((int)key?.GetValue(TASKBAR_SMALL_ICONS_REG_NAME, 0, RegistryValueOptions.None)) - 1); 33 | key?.SetValue(TASKBAR_SMALL_ICONS_REG_NAME, newValue, RegistryValueKind.DWord); 34 | Log.Info = $"{TASKBAR_SMALL_ICONS_REG_NAME}={(newValue == 0 ? "false" : "true")}"; 35 | } 36 | } 37 | catch (Exception ex) 38 | { 39 | Message.Show(Resources.FailedToUpdateRegistry, ex); 40 | return; 41 | } 42 | try 43 | { 44 | if (!NativeMethods.SendNotifyMessage((IntPtr)NativeMethods.HWND_BROADCAST, 45 | NativeMethods.WM_SETTINGCHANGE, UIntPtr.Zero, "TraySettings")) //NOTE: Will only work for English Windows UI locale 46 | { 47 | Message.Show(Resources.FailedToNotifyWindowsOfTaskbarIconSizeChange); 48 | } 49 | } 50 | catch (Exception ex) 51 | { 52 | Message.Show(Resources.FailedToNotifyWindowsOfTaskbarIconSizeChange, ex); 53 | } 54 | } 55 | 56 | #endregion Internal taskbar method 57 | 58 | #region Internal taskbar function 59 | 60 | internal static bool UsingSmallTaskbarButtons() 61 | { 62 | try 63 | { 64 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey(EXPLORER_ADVANCED_REG_KEY, false)) 65 | { 66 | return (int)key?.GetValue(TASKBAR_SMALL_ICONS_REG_NAME, 0, RegistryValueOptions.None) != 0; 67 | } 68 | } 69 | catch (Exception ex) 70 | { 71 | Log.LogCaller(); 72 | Log.Error = ex; 73 | } 74 | return true; 75 | } 76 | 77 | #endregion Internal taskbar function 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Tools/fart199b_win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/Tools/fart199b_win32.zip -------------------------------------------------------------------------------- /Week.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Globalization; 5 | 6 | #endregion Using statements 7 | 8 | namespace WeekNumber 9 | { 10 | internal class Week 11 | { 12 | #region Private variable that holds active week 13 | 14 | private int _week; 15 | 16 | #endregion Private variable that holds active week 17 | 18 | #region Constructor that initiates active week 19 | 20 | /// 21 | /// Initiates the week to current 22 | /// 23 | public Week() 24 | { 25 | _week = Current(); 26 | } 27 | 28 | #endregion Constructor that initiates active week 29 | 30 | #region Internal static week strings 31 | 32 | internal const string CalendarWeekRuleString = nameof(CalendarWeekRule); 33 | internal const string FirstDay = nameof(CalendarWeekRule.FirstDay); 34 | internal const string FirstFourDayWeek = nameof(CalendarWeekRule.FirstFourDayWeek); 35 | internal const string FirstFullWeek = nameof(CalendarWeekRule.FirstFullWeek); 36 | internal const string DayOfWeekString = nameof(DayOfWeek); 37 | internal const string Monday = nameof(DayOfWeek.Monday); 38 | internal const string Tuesday = nameof(DayOfWeek.Tuesday); 39 | internal const string Wednesday = nameof(DayOfWeek.Wednesday); 40 | internal const string Thursday = nameof(DayOfWeek.Thursday); 41 | internal const string Friday = nameof(DayOfWeek.Friday); 42 | internal const string Saturday = nameof(DayOfWeek.Saturday); 43 | internal const string Sunday = nameof(DayOfWeek.Sunday); 44 | 45 | #endregion Internal static week strings 46 | 47 | #region Public function to check if week has changed 48 | 49 | /// 50 | /// Returns if week was changed since last check 51 | /// 52 | /// true|false 53 | public bool WasChanged() 54 | { 55 | bool changed = _week != Current(); 56 | if (changed) 57 | { 58 | _week = Current(); 59 | } 60 | Log.Info = $"Current week number is {_week} and this was {(changed ? "a change" : "same as last checked")}"; 61 | return changed; 62 | } 63 | 64 | #endregion Public function to check if week has changed 65 | 66 | #region Public functions that returns week number based on calendar rules 67 | 68 | /// 69 | /// Get current week based on calendar rules in application settings 70 | /// 71 | /// Current week as int based on calendar rules in application settings 72 | public static int Current() 73 | { 74 | DayOfWeek dayOfWeek; 75 | CalendarWeekRule calendarWeekRule; 76 | dayOfWeek = Enum.TryParse(Settings.GetSetting(DayOfWeekString), true, out dayOfWeek) ? 77 | dayOfWeek : DayOfWeek.Monday; 78 | calendarWeekRule = Enum.TryParse(Settings.GetSetting(CalendarWeekRuleString), true, 79 | out calendarWeekRule) ? calendarWeekRule : CalendarWeekRule.FirstFourDayWeek; 80 | int week = CultureInfo.CurrentCulture.Calendar. 81 | GetWeekOfYear(DateTime.Now, calendarWeekRule, dayOfWeek); 82 | if (week == 53 && (!YearHas53Weeks(DateTime.Now.Year))) 83 | { 84 | week = 1; 85 | } 86 | Log.Info = $"Current week is #{week}"; 87 | return week; 88 | } 89 | 90 | /// 91 | /// Get week number based on calendar rules in application settings 92 | /// 93 | /// Date for which to get week number for 94 | /// Week number as for supplied date 95 | public static int GetWeekNumber(DateTime date) 96 | { 97 | DayOfWeek dayOfWeek; 98 | CalendarWeekRule calendarWeekRule; 99 | dayOfWeek = Enum.TryParse(Settings.GetSetting(DayOfWeekString), true, out dayOfWeek) ? 100 | dayOfWeek : DayOfWeek.Monday; 101 | calendarWeekRule = Enum.TryParse(Settings.GetSetting(CalendarWeekRuleString), true, 102 | out calendarWeekRule) ? calendarWeekRule : CalendarWeekRule.FirstFourDayWeek; 103 | int week = CultureInfo.CurrentCulture.Calendar. 104 | GetWeekOfYear(date, calendarWeekRule, dayOfWeek); 105 | if (week == 53 && (!YearHas53Weeks(DateTime.Now.Year))) 106 | { 107 | week = 1; 108 | } 109 | Log.Info = $"Week number is {week} for date {date.Year}-{date.Month}-{date.Day}"; 110 | return week; 111 | } 112 | 113 | #endregion Public functions that returns week number based on calendar rules 114 | 115 | #region Private helper functions to determine if it is week 1 or 53 116 | 117 | private static bool YearHas53Weeks(int year) 118 | { 119 | return Weeks(year) == 53; 120 | } 121 | 122 | private static int Weeks(int year) 123 | { 124 | int w = 52; 125 | if (P(year) == 4 || P(year - 1) == 3) 126 | { 127 | w++; 128 | } 129 | return w; // returns the number of weeks in that year 130 | } 131 | 132 | private static int P(int year) 133 | { 134 | return (int)(year + Math.Floor(year / 4f) - Math.Floor(year / 100f) + Math.Floor(year / 400f)) % 7; 135 | } 136 | 137 | #endregion Private helper functions to determine if it is week 1 or 53 138 | } 139 | } -------------------------------------------------------------------------------- /WeekApplicationContext.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using Microsoft.Win32; 4 | using System; 5 | using System.Windows.Forms; 6 | 7 | #endregion Using statements 8 | 9 | namespace WeekNumber 10 | { 11 | internal class WeekApplicationContext : ApplicationContext 12 | { 13 | #region Internal Taskbar GUI 14 | 15 | internal IGui Gui; 16 | 17 | #endregion Internal Taskbar GUI 18 | 19 | #region Private variables 20 | 21 | private readonly Timer _timer; 22 | private int _currentWeek; 23 | private int _lastIconRes; 24 | 25 | #endregion Private variables 26 | 27 | #region Constructor 28 | 29 | internal WeekApplicationContext() 30 | { 31 | try 32 | { 33 | Log.LogCaller(); 34 | Settings.StartWithWindows = Settings.SettingIsValue(Resources.StartWithWindows, true.ToString()); 35 | Application.ApplicationExit += OnApplicationExit; 36 | SystemEvents.UserPreferenceChanged += OnUserPreferenceChanged; 37 | _currentWeek = Week.Current(); 38 | _lastIconRes = WeekIcon.GetIconResolution(); 39 | Gui = new TaskbarGui(_currentWeek, _lastIconRes); 40 | Gui.UpdateRequest += GuiUpdateRequestHandler; 41 | _timer = GetTimer; 42 | } 43 | catch (Exception ex) 44 | { 45 | _timer?.Stop(); 46 | Log.LogCaller(); 47 | Message.Show(Resources.UnhandledException, ex); 48 | Application.Exit(); 49 | } 50 | } 51 | 52 | #endregion Constructor 53 | 54 | #region Private Timer property 55 | 56 | private Timer GetTimer 57 | { 58 | get 59 | { 60 | if (_timer != null) 61 | { 62 | return _timer; 63 | } 64 | //int calculatedInterval = 86400000 - ((DateTime.Now.Hour * 3600000) + (DateTime.Now.Minute * 60000) + (DateTime.Now.Second * 1000)); 65 | int calculatedInterval = 10000; // workaround for blurry icon due to Windows icon rendering bug, update icon every 10 seconds instead of when week change occurs only 66 | Timer timer = new Timer 67 | { 68 | Interval = calculatedInterval, 69 | Enabled = true 70 | }; 71 | Log.Info = $"Timer interval={calculatedInterval / 1000}s"; 72 | timer.Tick += OnTimerTick; 73 | return timer; 74 | } 75 | } 76 | 77 | #endregion Private Timer property 78 | 79 | #region Private event handlers 80 | 81 | private void GuiUpdateRequestHandler(object sender, EventArgs e) 82 | { 83 | Log.LogCaller(); 84 | UpdateIcon(true, true); 85 | } 86 | 87 | private void OnApplicationExit(object sender, EventArgs e) 88 | { 89 | Log.LogCaller(); 90 | Cleanup(false); 91 | } 92 | 93 | private void OnUserPreferenceChanged(object sender, EventArgs e) 94 | { 95 | Log.LogCaller(); 96 | int iconRes = WeekIcon.GetIconResolution(true); 97 | if (iconRes != _lastIconRes) 98 | { 99 | UpdateIcon(true, true); 100 | _lastIconRes = iconRes; 101 | } 102 | } 103 | 104 | private void OnTimerTick(object sender, EventArgs e) 105 | { 106 | UpdateIcon(); 107 | } 108 | 109 | private void UpdateIcon(bool force = false, bool redrawContextMenu = false) 110 | { 111 | if (_currentWeek == Week.Current() && force == false) 112 | { 113 | return; 114 | } 115 | _timer?.Stop(); 116 | Application.DoEvents(); 117 | try 118 | { 119 | Log.LogCaller(); 120 | _currentWeek = Week.Current(); 121 | int iconResolution = Settings.GetIntSetting(Resources.IconResolution, (int)IconSize.Icon256); 122 | Log.Info = $"Update icon with week number {_currentWeek} using resolution {iconResolution}x{iconResolution}, redraw context menu={redrawContextMenu}, forced update={force}"; 123 | Gui?.UpdateIcon(_currentWeek, iconResolution, redrawContextMenu); 124 | } 125 | catch (Exception ex) 126 | { 127 | Message.Show(Resources.FailedToSetIcon, ex); 128 | Cleanup(); 129 | throw; 130 | } 131 | if (_timer != null) 132 | { 133 | int calculatedInterval = 86400000 - ((DateTime.Now.Hour * 3600000) + (DateTime.Now.Minute * 60000) + (DateTime.Now.Second * 1000)); 134 | _timer.Interval = calculatedInterval; 135 | Log.Info = $"Timer interval={calculatedInterval / 1000}s"; 136 | _timer.Start(); 137 | } 138 | } 139 | 140 | #endregion Private event handlers 141 | 142 | #region Private methods 143 | 144 | private void Cleanup(bool forceExit = true) 145 | { 146 | Log.LogCaller(); 147 | _timer?.Stop(); 148 | _timer?.Dispose(); 149 | Gui?.Dispose(); 150 | Gui = null; 151 | if (forceExit) 152 | { 153 | Application.Exit(); 154 | } 155 | } 156 | 157 | #endregion Private methods 158 | } 159 | } -------------------------------------------------------------------------------- /WeekIcon.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Drawing; 6 | using System.Globalization; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Windows.Forms; 10 | 11 | #endregion Using statements 12 | 13 | namespace WeekNumber 14 | { 15 | internal static class WeekIcon 16 | { 17 | #region Icon Size 18 | 19 | private const int _defaultSize = (int)IconSize.Icon256; 20 | private const int _saveSize = (int)IconSize.Icon256; 21 | 22 | #endregion Icon Size 23 | 24 | #region Internal static functions 25 | 26 | internal static int GetIconResolution(bool forceUpdate = false) 27 | { 28 | int iconResolution = Settings.GetIntSetting(Resources.IconResolution, -1); 29 | double myDbl = 1.0d; 30 | if (forceUpdate || iconResolution == -1) 31 | { 32 | // guess what icon resolution to use based on system 33 | double winZoomLvl = GetWindowsZoom(); 34 | bool usingSmallTaskbarIcons = TaskbarUtil.UsingSmallTaskbarButtons(); 35 | myDbl = (double)System.Windows.SystemParameters.SmallIconHeight * winZoomLvl; 36 | if (!usingSmallTaskbarIcons) myDbl *= 1.5d; 37 | if (System.Windows.SystemParameters.PrimaryScreenWidth > 1600) myDbl *= 2.0d; 38 | Log.Info = $"SmallIconHeight={System.Windows.SystemParameters.SmallIconHeight}"; 39 | Log.Info = $"WindowsZoomLevel={winZoomLvl * 100}"; 40 | Log.Info = $"UsingSmallTaskbarButtons={usingSmallTaskbarIcons}"; 41 | Log.Info = $"Guessed icon resolution={myDbl}x{myDbl}"; 42 | 43 | // find closes match to existing configs (do not allow 16, 20, 24, 32, 40, 48, 64, 128) 44 | List list = new List { 256, 512 }; 45 | int closest = list.Aggregate((x, y) => Math.Abs(x - myDbl) < Math.Abs(y - myDbl) ? x : y); 46 | 47 | Log.Info = $"Closest icon resolution={closest}x{closest}"; 48 | 49 | Settings.UpdateSetting(Resources.IconResolution, closest.ToString()); 50 | iconResolution = closest; 51 | } 52 | 53 | return iconResolution; 54 | } 55 | 56 | internal static Bitmap GetImage(int weekNumber) 57 | { 58 | Log.LogCaller(); 59 | int size = 256; 60 | using (Bitmap bitmap = new Bitmap(size, size)) 61 | using (Graphics graphics = Graphics.FromImage(bitmap)) 62 | { 63 | try 64 | { 65 | graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 66 | graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 67 | graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 68 | graphics.TextContrast = 1; 69 | DrawBackgroundOnGraphics(graphics, size); 70 | DrawWeekNumberOnGraphics(weekNumber, graphics, size); 71 | return bitmap.Clone(new RectangleF(0, 0, size, size), System.Drawing.Imaging.PixelFormat.DontCare); 72 | } 73 | finally 74 | { 75 | graphics.Dispose(); 76 | bitmap?.Dispose(); 77 | } 78 | } 79 | } 80 | 81 | internal static Icon GetIcon(int weekNumber, int size = 0) 82 | { 83 | Log.LogCaller(); 84 | if (size == 0) 85 | { 86 | Log.Info = $"Using default icon size {_defaultSize}x{_defaultSize}"; 87 | size = _defaultSize; 88 | } 89 | Icon icon = null; 90 | using (Bitmap bitmap = new Bitmap(size, size)) 91 | using (Graphics graphics = Graphics.FromImage(bitmap)) 92 | { 93 | graphics.SmoothingMode = (System.Drawing.Drawing2D.SmoothingMode)Settings.GetIntSetting(Resources.SmoothingMode, (int)System.Drawing.Drawing2D.SmoothingMode.HighQuality); 94 | graphics.CompositingQuality = (System.Drawing.Drawing2D.CompositingQuality)Settings.GetIntSetting(Resources.CompositingQuality, (int)System.Drawing.Drawing2D.CompositingQuality.HighQuality); 95 | graphics.InterpolationMode = (System.Drawing.Drawing2D.InterpolationMode)Settings.GetIntSetting(Resources.InterpolationMode, (int)System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic); 96 | graphics.TextContrast = Settings.GetIntSetting(Resources.TextContrast, 1); 97 | DrawBackgroundOnGraphics(graphics, size); 98 | DrawWeekNumberOnGraphics(weekNumber, graphics, size); 99 | IntPtr bHicon = bitmap.GetHicon(); 100 | Icon newIcon = Icon.FromHandle(bHicon); 101 | icon = new Icon(newIcon, size, size); 102 | CleanupIcon(ref newIcon); 103 | } 104 | return icon; 105 | } 106 | 107 | internal static void CleanupIcon(ref Icon icon) 108 | { 109 | if (icon is null) 110 | { 111 | return; 112 | } 113 | NativeMethods.DestroyIcon(icon.Handle); 114 | icon.Dispose(); 115 | } 116 | 117 | internal static bool SaveIcon(int weekNumber, string fullPath) 118 | { 119 | bool result = true; 120 | Icon icon = null; 121 | 122 | try 123 | { 124 | Log.LogCaller(); 125 | icon = GetIcon(weekNumber, _saveSize); 126 | using (FileStream fs = new FileStream(fullPath, FileMode.Create, 127 | FileAccess.Write, FileShare.None)) 128 | { 129 | icon.Save(fs); 130 | Log.Info = $"Save app icon as '{fullPath}'"; 131 | } 132 | } 133 | catch (System.Exception ex) 134 | { 135 | Message.Show(Resources.UnhandledException, ex); 136 | result = false; 137 | } 138 | finally 139 | { 140 | CleanupIcon(ref icon); 141 | } 142 | return result; 143 | } 144 | 145 | #endregion Internal static functions 146 | 147 | #region Privare static helper methods 148 | 149 | private static void DrawBackgroundOnGraphics(Graphics graphics, int size = 0) 150 | { 151 | if (size == 0) 152 | { 153 | size = _defaultSize; 154 | } 155 | Color backgroundColor = Color.FromArgb(Settings.GetIntSetting(Resources.IconBackgroundAlpha), 156 | Settings.GetIntSetting(Resources.IconBackgroundRed), 157 | Settings.GetIntSetting(Resources.IconBackgroundGreen), 158 | Settings.GetIntSetting(Resources.IconBackgroundBlue)); 159 | Color foregroundColor = Color.FromArgb( 160 | Settings.GetIntSetting(Resources.IconForegroundRed, 255), 161 | Settings.GetIntSetting(Resources.IconForegroundGreen, 255), 162 | Settings.GetIntSetting(Resources.IconForegroundBlue, 255)); 163 | using (SolidBrush foregroundBrush = new SolidBrush(foregroundColor)) 164 | using (SolidBrush backgroundBrush = new SolidBrush(backgroundColor)) 165 | { 166 | float inset = (float)System.Math.Abs(size * .03125); 167 | graphics?.FillRectangle(backgroundBrush, inset, inset, size - inset, size - inset); 168 | using (Pen pen = new Pen(foregroundColor, inset * 2)) 169 | { 170 | graphics?.DrawRectangle(pen, inset, inset, size - inset * 2, size - inset * 2); 171 | } 172 | float leftInset = (float)System.Math.Abs(size * .15625); 173 | graphics?.FillRectangle(foregroundBrush, leftInset, inset / 2, inset * 3, inset * 5); 174 | float rightInset = (float)System.Math.Abs(size * .75); 175 | graphics?.FillRectangle(foregroundBrush, rightInset, inset / 2, inset * 3, inset * 5); 176 | } 177 | } 178 | 179 | private static void DrawWeekNumberOnGraphics(int weekNumber, Graphics graphics, int size = 0) 180 | { 181 | if (size == 0) size = _defaultSize; 182 | float fontSize = (float)System.Math.Abs(size * .78125); 183 | // float insetX = (float)-(size > (int)IconSize.Icon16 ? System.Math.Abs(fontSize * .12) : System.Math.Abs(fontSize * .07)); 184 | float insetY = (float)(size > (int)IconSize.Icon16 ? System.Math.Abs(fontSize * .2) : System.Math.Abs(fontSize * .08)); 185 | Color foregroundColor = Color.FromArgb( 186 | Settings.GetIntSetting(Resources.IconForegroundRed), 187 | Settings.GetIntSetting(Resources.IconForegroundGreen), 188 | Settings.GetIntSetting(Resources.IconForegroundBlue)); 189 | 190 | using (Font font = new Font("Aurulent Sans Mono", fontSize * 0.8f, FontStyle.Regular, 191 | GraphicsUnit.Pixel, 0, false)) 192 | using (Brush brush = new SolidBrush(foregroundColor)) 193 | graphics?.DrawString(weekNumber.ToString(CultureInfo.InvariantCulture).PadLeft(2, '0'), font, brush, 0.0f, insetY); 194 | } 195 | 196 | private static double GetWindowsZoom() 197 | { 198 | return (double)(Screen.PrimaryScreen.WorkingArea.Width / System.Windows.SystemParameters.PrimaryScreenWidth); 199 | } 200 | 201 | #endregion Private static helper methods 202 | } 203 | } -------------------------------------------------------------------------------- /WeekNumber.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {82D086D4-E145-4487-81FA-28BD3B1577D2} 6 | WinExe 7 | WeekNumber 8 | WeekNumber 9 | v4.8 10 | 512 11 | true 12 | false 13 | True 14 | 15 | 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | true 30 | 31 | 32 | 33 | x64 34 | true 35 | full 36 | false 37 | bin\x64\Debug\ 38 | DEBUG;TRACE 39 | prompt 40 | 4 41 | true 42 | True 43 | 44 | 45 | x64 46 | pdbonly 47 | true 48 | bin\x64\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | false 53 | true 54 | bin\x64\Release\WeekNumber.xml 55 | false 56 | True 57 | 58 | 59 | true 60 | bin\x86\Debug\ 61 | TRACE;DEBUG;CODE_ANALYSIS 62 | true 63 | full 64 | x86 65 | prompt 66 | true 67 | True 68 | 69 | 70 | bin\x86\Release\ 71 | CODE_ANALYSIS;TRACE 72 | bin\x86\Release\WeekNumber.xml 73 | true 74 | true 75 | pdbonly 76 | x86 77 | prompt 78 | true 79 | True 80 | 81 | 82 | WeekNumber.Program 83 | 84 | 85 | Resources\weekicon.ico 86 | 87 | 88 | Properties\app.manifest 89 | 90 | 91 | true 92 | 93 | 94 | Properties\WeekNumber.snk 95 | 96 | 97 | false 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | Component 114 | 115 | 116 | Form 117 | 118 | 119 | DateForm.cs 120 | 121 | 122 | Form 123 | 124 | 125 | MessageForm.cs 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | True 137 | True 138 | Resources.de-DE.resx 139 | 140 | 141 | Resources.resx 142 | True 143 | True 144 | 145 | 146 | True 147 | True 148 | Resources.en-US.resx 149 | 150 | 151 | True 152 | True 153 | Resources.sv-SE.resx 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Designer 167 | 168 | 169 | Designer 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | DateForm.cs 186 | 187 | 188 | MessageForm.cs 189 | 190 | 191 | ResXFileCodeGenerator 192 | Resources.de-DE.Designer.cs 193 | Designer 194 | 195 | 196 | ResXFileCodeGenerator 197 | Resources.Designer.cs 198 | WeekNumber 199 | Designer 200 | 201 | 202 | WeekNumber 203 | ResXFileCodeGenerator 204 | Resources.sv-SE.Designer.cs 205 | Designer 206 | 207 | 208 | ResXFileCodeGenerator 209 | Resources.en-US.Designer.cs 210 | WeekNumber 211 | Designer 212 | 213 | 214 | 215 | 216 | 217 | CMD /C TASKKILL /IM $(TargetFileName) /FI "STATUS eq RUNNING" /T /F 218 | 219 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /WeekNumber.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35327.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WeekNumber", "WeekNumber.csproj", "{82D086D4-E145-4487-81FA-28BD3B1577D2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Debug|Any CPU.ActiveCfg = Debug|x86 19 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Debug|x64.ActiveCfg = Debug|x64 20 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Debug|x64.Build.0 = Debug|x64 21 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Debug|x86.ActiveCfg = Debug|x86 22 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Debug|x86.Build.0 = Debug|x86 23 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Release|Any CPU.ActiveCfg = Release|x86 24 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Release|x64.ActiveCfg = Release|x64 25 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Release|x64.Build.0 = Release|x64 26 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Release|x86.ActiveCfg = Release|x86 27 | {82D086D4-E145-4487-81FA-28BD3B1577D2}.Release|x86.Build.0 = Release|x86 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(ExtensibilityGlobals) = postSolution 33 | SolutionGuid = {B395858B-07BD-439B-863C-1A9505DFFBEE} 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /WeekNumberMonitor/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("WeekNumberMonitor")] 6 | [assembly: AssemblyDescription("WeekNumberMonitor")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("Voltura AB")] 9 | [assembly: AssemblyProduct("WeekNumberMonitor")] 10 | [assembly: AssemblyCopyright("Copyright © Voltura AB 2024")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | [assembly: ComVisible(false)] 14 | [assembly: Guid("65632C08-E70E-4C7F-94F2-BC68FBC42744")] 15 | [assembly: AssemblyVersion("1.0.0.*")] 16 | [assembly: AssemblyFileVersion("1.0.0.0")] 17 | [assembly: NeutralResourcesLanguage("en-US")] -------------------------------------------------------------------------------- /WeekNumberMonitor/Program.cs: -------------------------------------------------------------------------------- 1 | #region Using statements 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using System.Runtime; 6 | using System.Runtime.InteropServices; 7 | 8 | #endregion Using statements 9 | 10 | /// 11 | /// This program is used by WeekNumber to refresh taskbar notification area if WeekNumber.exe is process is terminated 12 | /// and its notification area icon is still displayed, even though the WeekNumber application is not running. 13 | /// This projects compiled executable file contents has been manually converted into a base64 encoded string which is utilized from 14 | /// WeekNumber::MonitorProcess class which writes the exe to %LOCALAPPDATA%\temp and starts the program when WeekNumber.exe 15 | /// is started. 16 | /// 17 | internal class Program 18 | { 19 | #region Application starting point 20 | 21 | [STAThread] 22 | private static void Main(string[] args) 23 | { 24 | try 25 | { 26 | int id = int.Parse(args[0]); 27 | GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; 28 | GCSettings.LatencyMode = GCLatencyMode.Batch; 29 | using (Process p = Process.GetProcessById(id)) 30 | { 31 | p.WaitForExit(); 32 | } 33 | } 34 | catch (Exception) 35 | { 36 | } 37 | RefreshTrayArea(); 38 | } 39 | 40 | #endregion Application starting point 41 | 42 | #region Logic for refreshing taskbar notification area 43 | 44 | [StructLayout(LayoutKind.Sequential)] 45 | private struct RECT 46 | { 47 | public int left; 48 | public int top; 49 | public int right; 50 | public int bottom; 51 | } 52 | 53 | [DllImport("user32.dll")] 54 | private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 55 | 56 | [DllImport("user32.dll")] 57 | private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, 58 | string lpszWindow); 59 | 60 | [DllImport("user32.dll")] 61 | private static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); 62 | 63 | [DllImport("user32.dll")] 64 | private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam); 65 | 66 | private static void RefreshTrayArea() 67 | { 68 | IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null); 69 | IntPtr systemTrayHandle = FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null); 70 | IntPtr sysPagerHandle = FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null); 71 | IntPtr notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area"); 72 | if (notificationAreaHandle == IntPtr.Zero) 73 | { 74 | notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", 75 | "User Promoted Notification Area"); 76 | IntPtr notifyIconOverflowWindowHandle = FindWindow("NotifyIconOverflowWindow", null); 77 | IntPtr overflowNotificationAreaHandle = FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, 78 | "ToolbarWindow32", "Overflow Notification Area"); 79 | RefreshTrayArea(overflowNotificationAreaHandle); 80 | } 81 | RefreshTrayArea(notificationAreaHandle); 82 | } 83 | 84 | private static void RefreshTrayArea(IntPtr windowHandle) 85 | { 86 | const uint wmMousemove = 0x0200; 87 | GetClientRect(windowHandle, out RECT rect); 88 | for (var x = 0; x < rect.right; x += 5) 89 | for (var y = 0; y < rect.bottom; y += 5) 90 | SendMessage(windowHandle, wmMousemove, 0, (y << 16) + x); 91 | } 92 | 93 | #endregion Logic for refreshing taskbar notification area 94 | } 95 | -------------------------------------------------------------------------------- /WeekNumberMonitor/WeekNumber.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voltura/WeekNumber/9017ce446081122109315f85f4fcc63e3fcdfbdd/WeekNumberMonitor/WeekNumber.snk -------------------------------------------------------------------------------- /WeekNumberMonitor/WeekNumberMonitor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {89755684-7EB2-4687-B21F-5B6A7D55C7DB} 6 | WinExe 7 | WeekNumberMonitor 8 | WeekNumberMonitor 9 | v4.8 10 | 512 11 | true 12 | false 13 | True 14 | 15 | 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | true 30 | 31 | 32 | 33 | bin\x86\Release\ 34 | TRACE 35 | 36 | 37 | true 38 | true 39 | none 40 | x86 41 | prompt 42 | true 43 | True 44 | 45 | 46 | 47 | 48 | 49 | 50 | true 51 | 52 | 53 | WeekNumber.snk 54 | 55 | 56 | false 57 | 58 | 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | False 76 | Microsoft .NET Framework 4.6.1 %28x86 and x64%29 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /WeekNumberMonitor/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | msbuild WeekNumber.sln /p:Platform=x86 /t:Clean,Build /property:Configuration=Release -maxcpucount 2 | --------------------------------------------------------------------------------