[
  {
    "path": ".github/ISSUE_TEMPLATE/BugReport_en.yaml",
    "content": "name: Bug Report\ndescription: File a bug report\nbody:\n  - type: checkboxes\n    attributes: \n      label: Prerequisites\n      options:\n        - label: I have searched for related issues in the [issues](https://github.com/halo-dev/halo/issues) list.\n          required: true\n        - label: I have read the [FAQ](https://github.com/zhongyang219/TrafficMonitor/blob/master/Help_en-us.md) in detail and searched for related issues in FAQ list.\n          required: true\n  - type: input\n    attributes:\n      label: Current TrafficMonitor Version\n      description: Right-click the TrafficMonitor tray icon, select `Help` → `About`.\n    validations: \n      required: true\n  - type: input\n    attributes:\n      label: Current Operating System Version\n    validations: \n      required: true\n  - type: textarea\n    attributes:\n      label: What happened?\n      description: \"For ease of management, please do not report multiple unrelated issues under the same issue.\"\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Log Output\n      description: \"Error logs can be found in the TrafficMonitor root directory.<br>This will be automatically formatted as code, so no backticks are needed.\"\n      render: shell\n  - type: textarea\n    attributes:\n      label: Additional Information\n      description: \"If you have other information to note, you can fill it in here.\"\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/BugReport_zh.yaml",
    "content": "name: Bug反馈\ndescription: 提交Bug反馈\nbody:\n  - type: checkboxes\n    attributes: \n      label: 前置条件\n      options:\n        - label: 已经在[issue](https://github.com/zhongyang219/TrafficMonitor/issues)列表中搜索了相关问题。\n          required: true\n        - label: 已详细阅读了[常见问题](https://github.com/zhongyang219/TrafficMonitor/blob/master/Help.md)并在常见问题列表中搜索了相关问题。\n          required: true\n  - type: input\n    attributes:\n      label: 您当前使用的TrafficMonitor版本\n      description: 右键TrafficMonitor托盘图标，选择`帮助` → `关于`。\n    validations: \n      required: true\n  - type: input\n    attributes:\n      label: 您当前使用的操作系统版本\n    validations: \n      required: true\n  - type: textarea\n    attributes:\n      label: 发生了什么?\n      description: \"为了方便我们管理，请不要在同一个issue下报告多个不相关的问题。\"\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: 日志输出\n      description: \"错误日志可在TrafficMonitor根目录中找到。<br>这将自动格式化为代码,因此无需反引号。\"\n      render: shell\n  - type: textarea\n    attributes:\n      label: 附加信息\n      description: \"如果你还有其他需要提供的信息，可以在这里填写。\"\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/FeatureRequest_en.yaml",
    "content": "name: Feature Request\ndescription: File a feature request\nbody:\n  - type: checkboxes\n    attributes: \n      label: Prerequisites\n      options:\n        - label: I have searched for related issues in the [issues](https://github.com/zhongyang219/TrafficMonitor/issues) list.\n          required: true\n        - label: I have read the [wiki](https://github.com/zhongyang219/TrafficMonitor/wiki/Home_en) page and make sure that the current version of TrafficMonitor does not provide this feature.\n          required: true\n  - type: input\n    attributes:\n      label: Current TrafficMonitor Version\n      description: \"Right-click the TrafficMonitor tray icon, select `Help` → `About`.\"\n    validations: \n      required: true\n  - type: textarea\n    attributes:   \n      label: Describe the feature\n      description: \"For ease of management, please do not report multiple unrelated issues under the same issue.\"\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Additional Information\n      description: \"If you have other information to note, you can fill it in here.\"\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/FeatureRequest_zh.yaml",
    "content": "name: 功能请求\ndescription: 请求一个新功能\nbody:\n  - type: checkboxes\n    attributes: \n      label: 前置条件\n      options:\n        - label: 已经在[issue](https://github.com/zhongyang219/TrafficMonitor/issues)列表中搜索了相关问题。\n          required: true\n        - label: 已经阅读了[wiki](https://github.com/zhongyang219/TrafficMonitor/wiki)页面并确保当前版本TrafficMonitor没有提供此功能。\n          required: true\n  - type: input\n    attributes:\n      label: 您当前使用的TrafficMonitor版本\n      description: 右键TrafficMonitor托盘图标，选择`帮助` → `关于`。\n    validations: \n      required: true\n  - type: textarea\n    attributes:   \n      label: 描述一下该功能\n      description: \"为了方便我们管理，请不要在同一个issue下提交多个没有相关性的特性。\"\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: 附加信息\n      description: \"如果你还有其他需要提供的信息，可以在这里填写。\"\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: Release CI\non: push\njobs:\n\n  x64_build:\n    runs-on: windows-latest\n\n    steps:\n    - uses: actions/checkout@v3\n      \n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v2\n      \n    - name: Run msbuild\n      run: msbuild -p:configuration=release -p:platform=x64 -p:platformToolset=v143\n      \n    - name: Get current time\n      uses: josStorer/get-current-time@v2.0.2\n      id: current-time\n      with:\n        format: YYYYMMDD_HHmmss\n        utcOffset: \"+08:00\"\n      \n    - name : Upload artifact\n      uses: actions/upload-artifact@v4\n      with:\n        name: x64_${{ steps.current-time.outputs.formattedTime }}_TrafficMonitor\n        path: |\n          Bin/x64/Release/TrafficMonitor.exe\n          Bin/x64/Release/*.dll\n\n    - name : Upload pdb files\n      uses: actions/upload-artifact@v4\n      with:\n        name: x64_${{ steps.current-time.outputs.formattedTime }}_pdb\n        path: Bin/x64/Release/*.pdb\n\n  x86_build:\n    runs-on: windows-latest\n\n    steps:\n    - uses: actions/checkout@v3\n      \n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v2\n      \n    - name: Run msbuild\n      run: msbuild -p:configuration=release -p:platform=x86 -p:platformToolset=v143\n      \n    - name: Get current time\n      uses: josStorer/get-current-time@v2.0.2\n      id: current-time\n      with:\n        format: YYYYMMDD_HHmmss\n        utcOffset: \"+08:00\"\n      \n    - name : Upload artifact\n      uses: actions/upload-artifact@v4\n      with:\n        name: x86_${{ steps.current-time.outputs.formattedTime }}_TrafficMonitor\n        path: |\n          Bin/Release/TrafficMonitor.exe\n          Bin/Release/*.dll\n      \n    - name : Upload pdb files\n      uses: actions/upload-artifact@v4\n      with:\n        name: x86_${{ steps.current-time.outputs.formattedTime }}_pdb\n        path: Bin/Release/*.pdb\n\n  arm64ec_build:\n    runs-on: windows-latest\n\n    steps:\n    - uses: actions/checkout@v3\n      \n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v2\n      \n    - name: Run msbuild\n      run: msbuild -p:configuration=release -p:platform=ARM64EC -p:platformToolset=v143\n      \n    - name: Get current time\n      uses: josStorer/get-current-time@v2.0.2\n      id: current-time\n      with:\n        format: YYYYMMDD_HHmmss\n        utcOffset: \"+08:00\"\n\n    - name: Move dll file path \n      run: mv Bin/x64/Release/*.dll  Bin/ARM64EC/Release/\n\n    - name : Upload artifact\n      uses: actions/upload-artifact@v4\n      with:\n        name: arm64EC_${{ steps.current-time.outputs.formattedTime }}_TrafficMonitor\n        path: |\n          Bin/ARM64EC/Release/TrafficMonitor.exe\n          Bin/ARM64EC/Release/*.dll\n\n    - name : Upload pdb files\n      uses: actions/upload-artifact@v4\n      with:\n        name: arm64EC_${{ steps.current-time.outputs.formattedTime }}_pdb\n        path: Bin/ARM64EC/Release/*.pdb\n  # winXP_build:\n    # runs-on: windows-latest\n\n    # steps:\n    # - uses: actions/checkout@v3\n      \n    # - name: Add msbuild to PATH\n      # uses: microsoft/setup-msbuild@v1.1.3\n      \n    # - name: Run msbuild\n      # run: |\n        # set ExternalCompilerOptions=/DCOMPILE_FOR_WINXP\n        # msbuild -p:configuration=release -p:platform=x86 -p:platformToolset=v140_xp\n      # shell: cmd\n      \n    # - name: Get current time\n      # uses: josStorer/get-current-time@v2.0.2\n      # id: current-time\n      # with:\n        # format: YYYYMMDD_HHmmss\n        # utcOffset: \"+08:00\"\n      \n    # - name : Upload artifact\n      # uses: actions/upload-artifact@v3\n      # with:\n        # name: winXP_${{ steps.current-time.outputs.formattedTime }}_TrafficMonitor\n        # path: Bin/Release/TrafficMonitor.exe\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n**/Properties/launchSettings.json\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Typescript v1 declaration files\ntypings/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n# CodeRush\n.cr/\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n*.ini\n!skin.ini\n*.dat\n*.bak\n/TrafficMonitor/skins/test*\n[Dd]ebug (without temperature)/\n[Rr]elease (without temperature)/\n[Dd]ebug (lite)/\n[Rr]elease (lite)/\n/TrafficMonitor/compile_time.txt\n!/TrafficMonitor/language/*.ini\n*.diagsession\n"
  },
  {
    "path": "Help.md",
    "content": "**简体中文 | [English](./Help_en-us.md)**\n\n## TrafficMonitor 常见问题\n这里是关于TrafficMonitor常见问题的页面，如果你想查看关于TrafficMonitor的各项功能和使用方法的详细介绍，请[点击这里](https://github.com/zhongyang219/TrafficMonitor/wiki)转到TraffinMonitor Wiki页面。\n\n### Windows11下任务栏窗口和系统小组件重叠\n\n在Windows11下，可以通过以下步骤解决此问题：\n\n打开“选项设置”——“任务栏设置”，点击“Windows11相关设置”按钮，勾选“避免与右侧小组件重叠”选项，如下图所示。\n\n<img src=\"Screenshots/image-20250310121048889.png\" alt=\"image-20250310121048889\" style=\"zoom:80%;\" />\n\n如果你的任务栏中没有显示“小组件”，则此选项是灰色不可用状态。\n\n### Windows11下“任务栏窗口显示在任务栏左侧”是灰色不可用状态\n\n在Windows11，只有在任务栏居中的情况下，此选项才可用。\n\n因为当任务栏靠左显示时，左侧没有给TrafficMonitor显示的空间。 \n\n### Windows11下，当任务栏被占满时，TrafficMonitor的任务栏窗口和任务栏图标重叠\n\n<img src=\"images/image-20250310173257156.png\" alt=\"image-20250310173257156\" style=\"zoom:80%;\" />\n\n这个问题目前无法解决，建议尽量不要让任务栏被占满，或者在系统设置中将“合并任务栏按钮和标签”改为“始终”。\n\n请不要向我反馈此问题。\n\n### 如何显示CPU和内存利用率？\n\n在主窗口点击右弹出键菜单，勾选“显示更多信息”。如果需要在任务栏窗口中也显示CPU和内存利用率，则在任务栏窗口中点击右键弹出菜单，选择“显示设置<img src=\"./Screenshots/images/item.png\" style=\"zoom: 80%;\" />”，在弹出对话框中勾选“CPU和内存利用率”即可。\n\n### 如何更改任务栏中“CPU”、“内存”等文本\n\n任务栏窗口中的标签文本是可以自定义的。点击鼠标右键，在右键菜单中选择“选项”，点击“任务栏窗口设置”，点击“显示文本设置”，双击项目右侧的文本即可更改，然后点击两次“确定”即可。\n\n<img src=\"Screenshots/images/image-20221119093547649.png\" alt=\"image-20221119093547649\" style=\"zoom:80%;\" />\n\n由于这些文本是可以自定义的，因此切换语言时不会自动更改。在切换语言后，你可以点击“显示文本”对话框中的“恢复默认”按钮。\n\n### 网速一直显示为0KB\n\n这种情况可能是因为你电脑中正在使用的网卡发生了切换导致的。\n\n点击右键菜单“选择网络连接”下面的“刷新网络连接列表”也许可以解决这个问题。\n\n<img src=\"Screenshots/images/image-20221119094324759.png\" alt=\"image-20221119094324759\" style=\"zoom:80%;\" />\n\n如果问题仍然存在，请尝试在“选择网络连接”的子菜单下选择你要监控的网络连接，而不是选择“自动选择”。\n\n如果问题仍然存在，请尝试在“选项设置”>“常规设置”>“高级”中点击“选择要监控的网络连接”按钮，在弹出的对话框中只勾选你想监控的网络连接，去掉其他项目的勾选，点击两次“确定”按钮即可。\n\n<img src=\"Screenshots/images/image-20221119094501312.png\" alt=\"image-20221119094501312\" style=\"zoom:80%;\" />\n\n### 如何单独设置任务栏窗口中每个项目的颜色？\n在右键菜单中选择“选项”，切换到“任务栏窗口设置”，勾选“指定每个项目的颜色”，此时再点击“文本颜色”右边的颜色块，就会弹出“任务栏窗口颜色设置”的对话框了。\n\n如果不勾选“指定每个项目的颜色”，则只能为文本设置统一的颜色。\n\n### 设置了开机自动运行仍然无法开机自启。\n从1.80版本开始，标准版和Lite版采用了不同的方式来实现开机自启动。\n\n* Lite版和1.80以前的版本：\n\n  Lite版和1.80以前的版本的开机启动功能是通过在注册表“计算机\\HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run”中创建“TrafficMonitor”的注册表项来实现的，如果你遇到无法开机启动的问题，请先检查该注册表项是否存在，再检查程序的路径是否正确。如果你移动了程序的位置，则会因为路径无效导致开机自启动失效，此时只需要在选项设置中取消“开机自动运行”的勾选，再将其勾选上就可以了。\n\n  注意，某些第三方安全软件可能会阻止TrafficMonitor的开机自启动，请尝试在安全软件中允许TrafficMonitor开机自启动。\n\n  如果设置了以管理员身份运行也会出现开机无法自启动的问题，请尝试去掉以管理员身份运行。\n\n* 标准版：\n\n  标准版是通过创建任务计划来实现开机自启动的。可以通过`控制面板\\系统和安全\\管理工具`来打开任务计划程序。\n\n  如下图所示：\n\n  <img src=\"./Screenshots/images/image3.jpg\"/>\n\n  如果你遇到无法开机自启动的情况，请到“任务计划程序”中检查TrafficMonitor的计划任务是否正常创建，exe文件的路径是否正确。\n\n开机无法自启动的一个常见原因是你可能移动了TrafficMonitor主程序的位置。如果你为TrafficMonitor设置好了开机自动运行，但是你将TrafficMonitor移动到了其他位置，那么开机自启动肯定就失效了。你需要打开TrafficMonitor的“选项设置”——“常规设置”，如果“开机时自动运行”处于勾选状态，先去掉勾选，然后再次打开“选项设置”——“常规设置”，重新勾选“开机时自动运行”即可。\n\n需要注意的是，如果你使用不含温度监控的版本在注册表中创建了开机自启动项，然后再使用包含温度监控的版本开启开机自启动功能，它会自动将注册表中的开机自启动项删除，再在任务计划中创建开机自启动项。反之亦然。\n\n### 程序弹出“无法保存设置”的对话框。\n如果遇到这种情况，说明程序没有向其所在目录下写入数据的权限，导致设置数据无法保存。尝试将程序移动到其他有写入权限的文件夹中可以解决这个问题。\n\n你也可以通过以下步骤将配置文件的保存路径改为C:\\Users\\\\<用户名\\>\\AppData\\Roaming\\TrafficMonitor目录。\n\n* 退出TrafficMonitor，以管理员身份重新启动TrafficMonitor。\n* 在右键菜单中选择“选项”，切换到“常规设置”选项卡，在“数据和配置文件”中选择“保存到Appdata目录”。\n\n如果此时仍然提示“无法保存设置”，请打开应用程序所在目录，打开`global_cfg.ini`文件，如果不存在请新建一个，在里面添加如下内容：\n\n```\n[config]\nportable_mode = false\n```\n\n如果无法新建，可以在其他位置（比如桌面）新建该文件，然后移动到程序所在目录。\n\n如果`global_cfg.ini`文件已存在，就把`portable_mode `的值改成`false`，保存后重新启动TrafficMonitor。\n\n如果`global_cfg.ini`没有写入权限，可以尝试把该文件复制到桌面，改好后复制回原来的路径将原文件覆盖。\n\n执行以上步骤后理论上应该不会出现这种问题了。如果这个问题仍然出现，请尝试把C:\\Users\\\\<用户名\\>\\AppData\\Roaming\\TrafficMonitor\\config.ini删除，该文件会在删除后重新生成。\n\n在1.79以后的版本中，如果程序所在目录无法写入数据，会自动将配置和数据文件保存到C:\\Users\\\\<用户名\\>\\AppData\\Roaming\\TrafficMonitor目录，此时，“选项”——“常规设置”——“数据和配置文件”中“保存到程序所在目录”将不可用。\n\n### 更改设置后下次开机时设置丢失\n\n如果你没有看到“无法保存设置”的对话框，则说明程序的配置文件是能正常保存的。因此这个问题的原因可能是你的电脑中存在了多个TrafficMonitor的程序文件，并且配置文件保存在了程序所在目录下。\n\n例如，你打开了“D:\\software\\TrafficMonitor\\TrafficMonitor.exe”，并且更改了选项设置，但是下次开机时启动的却是“D:\\software1\\TrafficMonitor\\TrafficMonitor.exe”，而你之前修改的配置被保存在了“D:\\software\\TrafficMonitor\\”目录下。\n\n解决这个问题的方法是：\n\n1. 在“选项设置”>“常规设置”>“配置和数据文件”中，将配置文件的保存位置更改为Appdata目录。\n2. 删除你电脑中不需要的TrafficMonitor的程序文件，启动TrafficMonitor后，打开“选项设置”>“常规设置”，点击“重新设置开机自动运行”按钮。\n\n### 网速数值显示不全。\n由于不同字体每个字符的宽度并不一样，在某些情况下，确实会出现网速数值显示不全的问题。如果出现了这样的问题，请打开“选项”——“任务栏窗口设置”，在“数据位数”下拉列表中选择一个更大的值。\n### 设置了鼠标穿透后如何取消？\n在通知区的TrafficMonitor的图标上点击鼠标右键，去掉“鼠标穿透”的勾选即可。\n\n设置了鼠标穿透后，悬浮窗将无法响应任何鼠标消息，也无法弹出右键菜单，但是可以通过通知区图标来弹出右键菜单。主窗口的右键菜单和通知区图标的右键是完全一样的。\n\n另外，即使你之前设置了隐藏通知区图标，开启鼠标穿透后，通知区图标也会自动显示出来，防止无法弹出右键菜单。\n\n说明：以下几种情况下通知区图标会自动显示出来：\n\n* 开启鼠标穿透后；\n* 不显示任务栏窗口的情况下隐藏主窗口后；\n* 隐藏主窗口的情况下关闭任务栏窗口后；\n* 开启鼠标穿透的情况下关闭任务栏窗口后。\n### Windows 10 白色任务栏主题时任务栏窗口颜色的问题\n\n在使用白色任务栏主题时，你可以在在“任务栏窗口设置”点击“预设方案”按钮，选择“浅色模式”，可以一键设置浅色模式任务栏颜色。如图所示：\n\n<img src=\"./Screenshots/images/image2.jpg\" style=\"zoom:80%;\" />\n\n同时，你还可能勾选“自动适应Windows10深色/浅色主题”，程序会在Windows10深色/浅色主题更换时自动切换颜色方案。你可以点击“自动适应设置”按钮来配置在深色和浅色主题时分别使用哪个颜色预设。\n\n### 在Windows7/Windows8/8.1下任务栏窗口有个背景色，无法完全透明\n这个问题确实存在，但是在Win10下是正常的。这个问题暂时无法解决。\n\n在1.79以后的版本中，Windows8/8.1下可以在“选项”——“任务栏窗口设置”中勾选“背景色透明”，再勾选“根据任务栏颜色自动设置背景色”即可获得较好的显示效果。\n\n### 任务栏窗口有时会显示不全，比如单位被覆盖了\n这确实是一个BUG，但是我目前还没有找到一个好的解决方法，这个问题通常出现在任务栏右侧通知区域宽度变化的时候，主要在在切换输入法的时候，如果出现了这个问题，可以将通知区任意一个图标向上拖动将其隐藏，再将其拖下来即可恢复正常。\n出现这个问题原因在于，由于系统任务栏通知区的图标数量可能会发生变化，导致通知区的宽度也会时常变化，当通知区的宽度发生变化时，TrafficMonitor的任务栏窗口需要实时调整其位置。但是由于我无法知道通知区的宽度在什么时候变化，因此只能每隔一段时间判断是否需要调整位置，如果任务栏通知区域的宽度变化得太快，就会导致TrafficMonitor的任务栏无法及时调整其位置，从而导致了这个BUG。\n\n**以下步骤或许可以解决这个问题：**\n\n* 打开“设置”\n* 点击“时间和语言”——“区域和语言”\n* 点击右侧“高级键盘设置”\n* 勾选“使用桌面语言栏”\n* 右键点击任务栏，选择“任务栏设置”\n* 点击“打开或关闭系统图标”，关闭“输入指示”\n方法来自知乎 [win10的任务栏为何一点击就乱动？](https://www.zhihu.com/question/312032145/answer/627965084)\n\n### Windows10中开启HDR后任务栏窗口无法显示\n\n部分用户反馈，在Windows10中开始HDR功能会导致任务栏窗口无法显示。如果遇到这个问题，可以尝试在[“选项设置”——“任务栏窗口设置”](https://github.com/zhongyang219/TrafficMonitor/wiki/选项设置#任务栏窗口设置)中关闭“背景透明”选项的勾选。\n\n在1.85版本以后，可以通过在“选项设置”——“任务栏窗口设置”——“渲染设置”中改成Direct2D渲染来解决这个问题。\n\n### CPU利用率显示和任务管理器不一致\n\n在Windows10及以上操作系统中，如果你需要让TrafficMonitor显示的CPU利用率和任务管理器一致，请到[“选项设置”——“常规设置”——“高级”](https://github.com/zhongyang219/TrafficMonitor/wiki/选项设置#高级)——“CPU使用率获取方式”中选择“使用性能计数器”。\n\n由于Windows10以上操作系统中任务管理器获取CPU利用率的方式发生了改变，因此选择“基于CPU使用时间”的方式获取到的CPU利用率会和任务管理器中显示的不一致。\n\n### 关于TrafficMonitor温度监控的问题\n\n由于温度监控功能在某些电脑中存在一些问题，因此温度监控功能默认是关闭的，如果你要使用TrafficMonitor的温度监控功能，请到[“选项设置”-“常规设置”-“硬件监控”](https://github.com/zhongyang219/TrafficMonitor/wiki/选项设置#硬件监控)中开启。开启后，任务栏右键菜单中的“显示设置”子菜单下才会出现温度相关的项目。\n\nTrafficMonitor的温度监控功能依赖第三方开源库[LibreHardwareMonitor](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor)。如果你遇到硬件温度无法显示，或者显示的温度异常的问题，请先下载LibreHardwareMonitor，并查看LibreHardwareMonitor是否能正常显示对应的温度。如果下载的最新版LibreHardwareMonitor可以正常监控到硬件温度，则将下载的LibreHardwareMonitor文件夹中的LibreHardwareMonitorLib.dll替换掉TrafficMonitor文件夹下的LibreHardwareMonitorLib.dll文件，即可解决温度无法检测的问题。\n\n请不要向我反馈诸如温度显示不准确、显卡利用率不准确之类的问题，此类问题我无法解决。TrafficMonitor不是专业的硬件监控软件，无法保证硬件监控的数据在所有设备上的准确性。\n\n**注意：硬件监控功能（包括温度监控和显卡使用率监控）可能存在一些问题，它可能会占用更多的CPU和内存。据部分用户反馈，开启温度功能后会导致程序崩溃和系统死机等问题，请在知晓以上风险后再决定开启硬件监控功能。否则，请不要使用硬件监控功能。**\n\n### 程序启动时提示找不到“MSVC\\*.dll”、“mfc\\*.dll”、“vc*.dll”\n\n点击以下链接下载并安装Microsoft Visual C++ 运行环境。\n\n[最新支持的 Visual C++ 可再发行程序包下载 | Microsoft Docs](https://docs.microsoft.com/zh-CN/cpp/windows/latest-supported-vc-redist?view=msvc-170)\n\n### 我希望在任务栏上显示更多硬件信息，比如风扇转速、功率等\n\n现在推出了硬件监控插件，可以显示LibreHardwareMonitor中所有监控项目。\n\n![](Screenshots/420555677-53bd3ac9-1c55-4212-aa68-1fe5711e9fbc.png)\n\n使用说明和下载链接请点下方链接转到插件下载页面：\n\n[TrafficMonitorPlugins/download/plugin_download.md at main · zhongyang219/TrafficMonitorPlugins](https://github.com/zhongyang219/TrafficMonitorPlugins/blob/main/download/plugin_download.md)\n\n### 关于程序崩溃问题\n\n如果遇到程序崩溃的问题，重新启动程序后，请先到“选项”——“常规设置”——“硬件监控”中关闭所有项目的硬件监控，因为基于用户提供的dmp文件发现，大多数崩溃问题都和硬件监控功能有关。和硬件监控功能相关的崩溃问题我无法解决，请不要向我发送邮件反馈。如果你排除了硬件监控的问题，但是崩溃问题仍然存在，请先到“选项”——“常规设置”——“高级”——“插件管理”中禁用所有插件，再重新启动程序（如果程序无法启动，请删除TrafficMonitor所在目录下plugins里面的所有dll文件）。如果排除了插件的问题，但是崩溃问题仍然存在，请根据崩溃弹窗中的提示向我发送电子邮件。\n\n如果还遇到其他问题，也可以点击“关于”对话框中的“联系作者”，或者直接[点击此处](mailto:zhongyang219@hotmail.com)向我发送电子邮件。但我由于作者的能力有限，我并不能保证可以解决所有问题，但是你的反馈也许可以帮助我更好的改进这个软件。\n请在邮件中尽可能详细地描述你遇到的问题，出现了什么错误提示，你尝试过哪些操作等，最好能够附上截图和配置文件（“选项”——“常规设置”——“打开配置文件所在路径”）。\n注意，发送前请先确认一下你发送时使用的电子邮件地址，如果你的邮件地址是形如“outlook_随机字符串@outlook.com”的格式，那么这样的邮箱地址是无法回复的。\n这可能是由于你使用了第三方邮箱地址作为Microsoft账号登录Windows导致的。如果有这样的情况，请务必在邮件中附上正确的电子邮件地址。\n"
  },
  {
    "path": "Help_en-us.md",
    "content": "**[简体中文](./Help.md) | English**\n\n# TrafficMonitor Frequently Asked Questions\nThis is the page about the Frequently Asked Questions of TrafficMonitor. If you want to view the detailed introduction of the functions and usage of TrafficMonitor, please [click here](https://github.com/zhongyang219/TrafficMonitor/wiki) to go the the TraffinMonitor Wiki page.\n\n### In Windows 11, the taskbar window overlapped with the windows Widgets\n\nIn Windows 11, this issue can be fixed with the following steps:\n\nOpen \"Option Settings\"-\"Taskbar Window Settings\", click the \"Settings related to Windows 11\" button, and check \"Avoid overlapping with right Widgets\" option. As shown in the picture bellow.\n\n<img src=\"Screenshots/image-20250310121048889.png\" alt=\"image-20250310121048889\" style=\"zoom:80%;\" />\n\nIf the Widgets is not showing on the taskbar, this option is grayed.\n\n### In Windows 11, \"The taskbar window appears to the left of the taskbar\" is grayed\n\nIn Windows 11, this option is only available when the taskbar is align centered.\n\nBecause when the taskbar is displayed on the left, there is no space on the left side for TrafficMonitor to display.\n\n### In Windows 11, the taskbar window of TrafficMonitor overlaps with the taskbar icons when taskbar is full\n\n<img src=\"images/image-20250310173257156.png\" alt=\"image-20250310173257156\" style=\"zoom:80%;\" />\n\nThis problem cannot be fixed at present. It is recommended to try not to fill the taskbar, or change \"Merge taskbar buttons and tabs\" to \"Always\" in the system settings.\n\nPlease do not send feedback to me on this issue.\n\n### How to show the CPU and memory usage?\n\nRight click the main window and check \"Show More Info\". If you also need to display the CPU and memory usage in the taskbar window, right click the taskbar window and select \"Display Settings<img src=\"./Screenshots/images/item.png\" style=\"zoom: 80%;\" />\", check \"CPU and Memory Usage\" in the  pop-up dialog box.\n\n### How do I change the text such as \"CPU\" and \"MEM\" in the taskbar\n\nThe label text in the taskbar window can be customized. Right click on the taskbar window, select \"Options\", click \"Taskbar Windows Settings\", click \"Display Text settings\" button, the text on the right side of the item can be modified by double click. After modified, click \"OK\" button twice.\n\n<img src=\"Screenshots/images/image-20221119093547649.png\" alt=\"image-20221119093547649\" style=\"zoom:80%;\" />\n\nBecause the text is customizable, it does not automatically change when you switch the language. After you swatch the language, you can click \"Restore default\" button in the \"Display Text settings\" dialog box.\n\n### The net speed is always displayed as 0KB\n\nThis may caused by the switch of the network you are using on your computer.\n\nClick \"Refresh connection list\" under \"Select network connections\" in the context menu may solve this problem.\n\n<img src=\"Screenshots/images/image-20221119094324759.png\" alt=\"image-20221119094324759\" style=\"zoom:80%;\" />\n\nIf this problem still exists, please try to select the network connection you want to monitored in the \"Select network connections\" submenu instead of select \"Auto select\".\n\nIf this problem still exists, please try to click the \"Select the connection to monitor\" button in \"Options Settings\" > \"General Settings\" > \"Advanced\", check the network you want to monitored, uncheck other items, and click \"OK\" button twice.\n\n<img src=\"Screenshots/images/image-20221119094501312.png\" alt=\"image-20221119094501312\" style=\"zoom:80%;\" />\n\n### How do I set the color of each item in the taskbar window individually?\n\nSelect \"Options\" In the right-click menu, switch to \"Taskbar Window Settings\" tab, check \"Specify colors for each item\", and then click the color block on the right side of \"Text Color \" to pop up the dialog box for taskbar window color settings. \n\nIf you do not check \"Specify colors for each item\", you can only set the uniform color for the text.\n\n### \"Auto run when Windows start\" dose not work\nStarting from version 1.80, the version with temperature monitoring and the version without temperature monitoring have adopted different methods to realize \"auto run when Windows start\".\n\n* Versions without temperature monitoring and versions before 1.80:\n\n  The auto run function of the versions without temperature monitoring and versions before 1.80 is achieved by creating the \"TrafficMonitor\" key in the registry path of \"Computer\\HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\".\n  If you encounter the problem of auto run dose not work, please check that the registry exists, and then check the program path is correct. If you move the location of the program, the auto run will be invalid because of the program location being invalid. In this case, you only need to uncheck \"Auto run when Windows start\" in the option settings, and then check it on.\n\n  Note that some third-party security software may prevent TrafficMonitor from booting up automatically. Please try to allow TrafficMonitor to boot up automatically in the security software.\n\n  If you set the program to run as an administrator, the auto run function will also not work. Please try to remove running as an administrator.\n\n* Version with temperature monitoring:\n\n  The version that includes temperature monitoring implements auto run function by creating a task plan. The task scheduler can be opened through `Control Panel\\System and Security\\Administrative Tools`.  As shown below:\n\n  <img src=\"./Screenshots/images/image3.jpg\"/>\n\n  If you encounter that situation that the program cannot be started automatically after booting, please go to \"Task Scheduler\" to check whether the scheduled task of TrafficMonitor is created normally and the path of the exe file is correct.\n\nA common reason why the \"Auto run when Windows start\" dose not work is that you may have moved the location of the TrafficMonitor main program. If you have set up TrafficMonitor to run automatically at startup, but you move TrafficMonitor to another location, then the auto run at startup will definitely fail. You need to open \"Option Settings\"-\"General Settings\" of TrafficMonitor, if \"Auto run when Windows start\" is checked, remove the check, then open \"Option Settings\"-\"General Settings\" again, and check again \"Auto run when Windows start\" will be fine.\n\nIt should be noted that if you use the version without temperature monitoring to create a auto-start item in the registry, and then use the version that with temperature monitoring to turn on the \"Auto run when Windows start\" function, it will automatically delete the auto-start item in the registry, and then create a auto-start item in the task plan. vice versa.\n\n### The program pops up the \"Unable to Save Settings\" message box.\nIf you encountered this problem, that means the program does not have permission to write data to its directory, causing the settings data cannot be saved. Try to move the program to another folder that has write permissions will save this problem. \nYou can also change the save path of the configuration and data file to the C:\\Users\\\\<username\\>\\AppData\\Roaming\\TrafficMonitor directory by the following steps. \n\n* Exit TrafficMonitor and restart TrafficMonitor as an administrator.\n* Select \"Options\" in the right-click menu, switch to the \"General Settings\" tab, and select \"Save to AppData Directory\" in \"Configuration and data files\".\n\nIf it still pops up the \"Unable to Save Settings\" message box, open the directory where the application is located, open the `global_cfg.ini` file. If it doesn't exist, create a new one, adding the following:\n\n```\n[config]\nportable_mode = false\n```\n\nIf the file cannot be created, you can create the file in a different location, such as the desktop, and then move to the directory where the program is located.\n\nIf the `global_cfg.ini` file already exists, change the value of `portable_mode` to `false` and save, then restart TrafficMonitor.\n\nIf `global_cfg.ini` does not have write permission, you can try copying the file to the desktop, and then copying it back to the original path to overwrite the original file after modified.\n\nAfter these steps, this problem should not theoretically occur. If this problem still occurs, try to delete the file C:\\Users\\\\<username\\>\\AppData\\Roaming\\TrafficMonitor\\config.ini. This file will be regenerated after it is deleted. \n\nIn version 1.79 and later, if the directory where the program located is not writable, the configuration and data files will be automatically saved to the \"C:\\Users\\\\<username\\>\\AppData\\Roaming\\TrafficMonitor\" directory. At this time, \"Options\" -“General Settings”-“Save to the program directory” in “Configuration and data files” will not be available.\n\n### The configuration is lost after next start up\n\nIf you do not see the \"Unable to Save Settings\" message box, that means the configuration file can be saved normally. The cause of this problem may be that you have multiple TrafficMonitor application files on your computer and the configuration files are saved in the application directory.\n\nFor example, you have open \"D:\\software\\TrafficMonitor\\TrafficMonitor.exe\", and modified the configuration, but next time you start your computer, \"D:\\software1\\TrafficMonitor\\TrafficMonitor.exe\" is started, while the configuration files you modified before is saved in \"D:\\software\\TrafficMonitor\\\\\".\n\nThe method to solve this problem is:\n\n1. Change the save location of the configuration files to AppData directory in \"Option Settings\" > \"General Settings\" > \"Configuration and data file\".\n2. Delete the TrafficMonitor application files you don't need on your computer, start TrafficMonitor, open \"Option Settings\" > \"General Settings\", click \"Reset autorun\" button. \n\n### The net speed value is not fully displayed.\nBecause the width of each character in different fonts is not the same, in some cases, it does appear the problem of the net speed value is not fully displayed. If this problem occurs, open \"Options\"-\"Taskbar Window Settings\", and select a larger value in the \"Number of digits\" drop down list.\n### How to cancel after setting the mouse penetrate?\nRight click the TrafficMonitor icon in the notification area, uncheck the \"Mouse Penetrate\".\nAfter the mouse penetrate is set, the suspension window will not be able to respond to any mouse messages, or pop-up right-click menu. But the menu can be popped up by right click the icon in notification area. The right-click menu of the main window and which of the notification area icon is exactly the same.\nIn addition, even if you have previously set the hidden notify icon, when the \"mouse penetrate\" is set, the notify icon will also automatically appear to prevent the right-click menu cannot be displayed. \nNote: The notification area icon will be automatically displayed in the following situations: \n\n* After the \"Mouse Penetrate\" is set;\n* Hide the main window without displaying the taskbar window;\n* Close the taskbar window when the main window is hidden;\n* Close the taskbar window when the \"Mouse Penetrate\" is set.\n### Problems with the taskbar window color in Windows 10 white taskbar theme\nWhen using the white taskbar theme, you can click the \"Preset\" button in the \"Taskbar Window Settings\" and select \"Light Mode\" to set the taskbar color in light mode. As the picture shows:\n\n<img src=\"./Screenshots/images/image2.jpg\" style=\"zoom:80%;\" />\n\nAt the same time, you may also check \"Auto adapt to Windows 10 dark/light theme\", the program will automatically switch the color preset when Windows 10 dark/light theme is changed. You can click the \"Auto Adapt settings\" button to configure which color preset to use for dark and light themes.\n\n### The taskbar windows cannot be displayed when the HDR is turned on in Windows 10\n\nSome users have reported that turning on the HDR function in Windows 10 will cause the taskbar window to fail to display. If you encounter this problem, you can try turning off the \"Background Transparent\" option in [\"Option Settings\" - \"Taskbar Window Settings\"](https://github.com/zhongyang219/TrafficMonitor/wiki/选项设置#任务栏窗口设置).\n\nSince version 1.85, this can be fixed by changing to Direct2D rendering in \"Options Settings\" - \"Taskbar Window Settings\" - \"Rendering Settings\".\n\n### The CPU usage displayed is inconsistent with Task Manager\n\nSince Windows 10, if you want to make the CPU usage shown by TrafficMonitor consistent with Task Manager, please go to \"Option Settings\"-\"General Settings\"-\"Advanced\"-\"CPU usage acquisition method\", and select \"Use the performance counter\".\n\n### About the temperature monitoring of TrafficMonitor\n\nDue to some problems occurred in some computers caused by the temperature monitoring function, the temperature monitoring function is turned off by default. If you want to use the temperature monitoring function of TrafficMonitor, please go to [\"Option Settings\"-\"General Settings\"-\"Hardware Monitoring\"](https://github.com/zhongyang219/TrafficMonitor/wiki/选项设置#硬件监控) to enable it. After it is turned on, temperature-related items will appear under the \"Display Settings\" submenu in the taskbar right-click menu.\n\nThe temperature monitoring function of TrafficMonitor relies on a third-party open source library [LibreHardwareMonitor](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor). If you encounter the problem that the hardware temperature cannot be displayed, or the displayed temperature is incorrect, then  please download LibreHardwareMonitor first, and check whether LibreHardwareMonitor can display the corresponding temperature normally.\n\nIf LibreHardwareMonitor cannot display the temperature of the corresponding hardware, then I cannot solve this problem. You can report your problem to the author of LibreHardwareMonitor.\n\nIf the latest version of LibreHardwareMonitor can display the hardware temperature normally, replace the LibreHardwareMonitorLib.dll files in the TrafficMonitor folder with the downloaded the LibreHardwareMonitorLib.dll files may solve this problem.\n\n**Note: The hardware monitoring function (including temperature monitoring and GPU usage monitoring) may have some problems, which may cause more CPU and memory usage. According to feedback from some users, turning on the temperature function will cause problems such as program crashes and system crashes. Please decide to turn on the hardware monitoring function after you are aware of the above risks. Otherwise, please do not use the hardware monitoring function.**\n\n## The program prompts that \"MSVC\\*.dll\" or \"mfc\\*.dll\" cannot be found when the program starts\n\nClick the link below to download and install the Microsoft Visual C++ runtime environment.\n\n[Latest supported Visual C++ Redistributable downloads | Microsoft Docs](https://docs.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170)\n\n### I want to have more hardware information on the taskbar, such an fan speed, power, etc\n\nThe Hardware Monitor plug in is now available. It can display all the monitoring items in LibreHardwareMonitor.\n\n![](images/420555677-53bd3ac9-1c55-4212-aa68-1fe5711e9fbc.png)\n\nFor instructions and download links, please click the link below to go to the plug-in download page:\n\n[TrafficMonitorPlugins/download/plugin_download.md at main · zhongyang219/TrafficMonitorPlugins](https://github.com/zhongyang219/TrafficMonitorPlugins/blob/main/download/plugin_download.md)\n\n### About the crash issue\n\nIf you encounter the problem of program crash, please turn off all the items in \"Options\" - \"General Settings\" - \"Hardware Monitoring\" after restarting the program, because based on the DMP file provided by the user, most crash problems are related to the hardware monitoring function. I cannot solve the crash problem related to the hardware monitoring function, please do not send me email feedback. If you have excluded the hardware monitoring problem, but the crash problem still exists, please go to \"Options\" - \"General Settings\" - \"Advanced\" - \"Plug-in Management\" to disable all plugins, and then restart the program. (If the program fails to start, please delete all the `dll` files in the `plugins` in the directory where TrafficMonitor is located). If you have excluded the plugin problem, but the crash problem still exists, please send me the email according to the prompts in the crash window.\n\nIf you have encountered any other problems, you can also click \"Contact Author\" in the \"About\" dialog box, or directly [click here](mailto:zhongyang219@hotmail.com) to send me an email.\nPlease describe the problems you have encountered in detail, the error prompts, what operations you have tried, it is better to attach the screenshots and configuration files (\"Options\"-\"General Settings\"-\"Open configuration file path\"). \nNote: Please confirm the email address that you used before sending the email. If your email address is form like \"Outlook_\\<random string\\>@outlook.com\", then such email address is unable to reply.\nThis may be due to the fact that you are using a third-party e-mail address as the Microsoft account to log on to Windows. If this is the case, be sure to enclose the correct email address in the message.\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) <2019> <copyright zhongyang219>\n\n\"Anti 996\" License Version 1.0 (Draft)\n\nPermission is hereby granted to any individual or legal entity\nobtaining a copy of this licensed work (including the source code,\ndocumentation and/or related items, hereinafter collectively referred\nto as the \"licensed work\"), free of charge, to deal with the licensed\nwork for any purpose, including without limitation, the rights to use,\nreproduce, modify, prepare derivative works of, distribute, publish\nand sublicense the licensed work, subject to the following conditions:\n\n1. The individual or the legal entity must conspicuously display,\nwithout modification, this License and the notice on each redistributed\nor derivative copy of the Licensed Work.\n\n2. The individual or the legal entity must strictly comply with all\napplicable laws, regulations, rules and standards of the jurisdiction\nrelating to labor and employment where the individual is physically\nlocated or where the individual was born or naturalized; or where the\nlegal entity is registered or is operating (whichever is stricter). In\ncase that the jurisdiction has no such laws, regulations, rules and\nstandards or its laws, regulations, rules and standards are\nunenforceable, the individual or the legal entity are required to\ncomply with Core International Labor Standards.\n\n3. The individual or the legal entity shall not induce, suggest or force\nits employee(s), whether full-time or part-time, or its independent\ncontractor(s), in any methods, to agree in oral or written form, to\ndirectly or indirectly restrict, weaken or relinquish his or her\nrights or remedies under such laws, regulations, rules and standards\nrelating to labor and employment as mentioned above, no matter whether\nsuch written or oral agreements are enforceable under the laws of the\nsaid jurisdiction, nor shall such individual or the legal entity\nlimit, in any methods, the rights of its employee(s) or independent\ncontractor(s) from reporting or complaining to the copyright holder or\nrelevant authorities monitoring the compliance of the license about\nits violation(s) of the said license.\n\nTHE LICENSED WORK IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE\nLICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.\n"
  },
  {
    "path": "LICENSE_CN",
    "content": "版权所有（c）<2019> <copyright zhongyang219>\n\n反996许可证版本1.0\n\n在符合下列条件的情况下，特此免费向任何得到本授权作品的副本（包括源代码、文件和/或相关内容，以\n下统称为“授权作品”）的个人和法人实体授权：被授权个人或法人实体有权以任何目的处置授权作品，包括\n但不限于使用、复制，修改，衍生利用、散布，发布和再许可：\n\n1. 个人或法人实体必须在许可作品的每个再散布或衍生副本上包含以上版权声明和本许可证，不得自行修\n改。\n2. 个人或法人实体必须严格遵守与个人实际所在地或个人出生地或归化地、或法人实体注册地或经营地（\n以较严格者为准）的司法管辖区所有适用的与劳动和就业相关法律、法规、规则和标准。如果该司法管辖区\n没有此类法律、法规、规章和标准或其法律、法规、规章和标准不可执行，则个人或法人实体必须遵守国际\n劳工标准的核心公约。\n3. 个人或法人不得以任何方式诱导、暗示或强迫其全职或兼职员工或其独立承包人以口头或书面形式同意\n直接或间接限制、削弱或放弃其所拥有的，受相关与劳动和就业有关的法律、法规、规则和标准保护的权利\n或补救措施，无论该等书面或口头协议是否被该司法管辖区的法律所承认，该等个人或法人实体也不得以任\n何方法限制其雇员或独立承包人向版权持有人或监督许可证合规情况的有关当局报告或投诉上述违反许可证\n的行为的权利。\n\n该授权作品是\"按原样\"提供，不做任何明示或暗示的保证，包括但不限于对适销性、特定用途适用性和非侵\n权性的保证。在任何情况下，无论是在合同诉讼、侵权诉讼或其他诉讼中，版权持有人均不承担因本软件或\n本软件的使用或其他交易而产生、引起或与之相关的任何索赔、损害或其他责任。\n"
  },
  {
    "path": "OpenHardwareMonitorApi/LibreHardwareMonitorLib.xml",
    "content": "<?xml version=\"1.0\"?>\n<doc>\n    <assembly>\n        <name>LibreHardwareMonitorLib</name>\n    </assembly>\n    <members>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Battery.BatteryGroup.Hardware\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Battery.BatteryGroup.Close\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Battery.BatteryGroup.GetReport\">\n            <inheritdoc />\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Computer\">\n            <summary>\n            Stores all hardware groups and decides which devices should be enabled and updated.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Computer.#ctor\">\n            <summary>\n            Creates a new <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\" /> instance with basic initial <see cref=\"T:LibreHardwareMonitor.Hardware.Computer.Settings\" />.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Computer.#ctor(LibreHardwareMonitor.Hardware.ISettings)\">\n            <summary>\n            Creates a new <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\" /> instance with additional <see cref=\"T:LibreHardwareMonitor.Hardware.ISettings\" />.\n            </summary>\n            <param name=\"settings\">Computer settings that will be transferred to each <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\" />.</param>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.Computer.HardwareAdded\">\n            <inheritdoc />\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.Computer.HardwareRemoved\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.Hardware\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsBatteryEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsControllerEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsCpuEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsGpuEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsMemoryEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsMotherboardEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsNetworkEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsPsuEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.IsStorageEnabled\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Computer.SMBios\">\n            <summary>\n            Contains computer information table read in accordance with <see href=\"https://www.dmtf.org/standards/smbios\">System Management BIOS (SMBIOS) Reference Specification</see>.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Computer.Accept(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <summary>\n            Triggers the <see cref=\"M:LibreHardwareMonitor.Hardware.IVisitor.VisitComputer(LibreHardwareMonitor.Hardware.IComputer)\" /> method for the given observer.\n            </summary>\n            <param name=\"visitor\">Observer who call to devices.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Computer.Traverse(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <summary>\n            Triggers the <see cref=\"M:LibreHardwareMonitor.Hardware.IElement.Accept(LibreHardwareMonitor.Hardware.IVisitor)\" /> method with the given visitor for each device in each group.\n            </summary>\n            <param name=\"visitor\">Observer who call to devices.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Computer.Open\">\n            <summary>\n            If hasn't been opened before, opens <see cref=\"P:LibreHardwareMonitor.Hardware.Computer.SMBios\" />, <see cref=\"T:LibreHardwareMonitor.Hardware.Ring0\" />, <see cref=\"T:LibreHardwareMonitor.Hardware.OpCode\" /> and triggers the private <see cref=\"M:LibreHardwareMonitor.Hardware.Computer.AddGroups\" /> method depending on which categories are\n            enabled.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Computer.Close\">\n            <summary>\n            If opened before, removes all <see cref=\"T:LibreHardwareMonitor.Hardware.IGroup\" /> and triggers <see cref=\"M:LibreHardwareMonitor.Hardware.OpCode.Close\" />, <see cref=\"M:LibreHardwareMonitor.Hardware.InpOut.Close\" /> and <see cref=\"M:LibreHardwareMonitor.Hardware.Ring0.Close\" />.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Computer.Reset\">\n            <summary>\n            If opened before, removes all <see cref=\"T:LibreHardwareMonitor.Hardware.IGroup\" /> and recreates it.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Computer.Settings\">\n            <summary>\n            <see cref=\"T:LibreHardwareMonitor.Hardware.Computer\" /> specific additional settings passed to its <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\" />.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Controller.Nzxt.KrakenX3\">\n            Support for the Kraken X3 devices from NZXT\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.CPU.CpuId.#ctor(System.Int32,System.Int32,LibreHardwareMonitor.Hardware.GroupAffinity)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.CPU.CpuId\" /> class.\n            </summary>\n            <param name=\"group\">The group.</param>\n            <param name=\"thread\">The thread.</param>\n            <param name=\"affinity\">The affinity.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.CPU.CpuId.Get(System.Int32,System.Int32)\">\n            <summary>\n            Gets the specified <see cref=\"T:LibreHardwareMonitor.Hardware.CPU.CpuId\" />.\n            </summary>\n            <param name=\"group\">The group.</param>\n            <param name=\"thread\">The thread.</param>\n            <returns><see cref=\"T:LibreHardwareMonitor.Hardware.CPU.CpuId\" />.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.CPU.GenericCpu.CpuId\">\n            <summary>\n            Gets the CPUID.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.CPU.GenericCpu.Index\">\n            <summary>\n            Gets the CPU index.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Gpu.AmdGpu.DeviceId\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Gpu.AmdGpu.SetDefaultFanSpeed\">\n            <summary>\n            Sets the default fan speed.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Gpu.AmdGpu.GetODNTemperature(LibreHardwareMonitor.Interop.AtiAdlxx.ADLODNTemperatureType,LibreHardwareMonitor.Hardware.Sensor,System.Double,System.Double,System.Boolean)\">\n            <summary>\n            Gets the OverdriveN temperature.\n            </summary>\n            <param name=\"type\">The type.</param>\n            <param name=\"sensor\">The sensor.</param>\n            <param name=\"minTemperature\">The minimum temperature.</param>\n            <param name=\"scale\">The scale.</param>\n            <param name=\"reset\">If set to <c>true</c>, resets the sensor value to <c>null</c>.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Gpu.AmdGpu.GetPMLog(LibreHardwareMonitor.Interop.AtiAdlxx.ADLPMLogDataOutput,LibreHardwareMonitor.Interop.AtiAdlxx.ADLSensorType,LibreHardwareMonitor.Hardware.Sensor,System.Single,System.Boolean)\">\n            <summary>\n            Gets a PMLog sensor value.\n            </summary>\n            <param name=\"data\">The data.</param>\n            <param name=\"sensorType\">Type of the sensor.</param>\n            <param name=\"sensor\">The sensor.</param>\n            <param name=\"factor\">The factor.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Gpu.AmdGpu.GetOD6Power(LibreHardwareMonitor.Interop.AtiAdlxx.ADLODNCurrentPowerType,LibreHardwareMonitor.Hardware.Sensor)\">\n            <summary>\n            Gets the Overdrive6 power.\n            </summary>\n            <param name=\"type\">The type.</param>\n            <param name=\"sensor\">The sensor.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Gpu.GenericGpu.#ctor(System.String,LibreHardwareMonitor.Hardware.Identifier,LibreHardwareMonitor.Hardware.ISettings)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.Gpu.GenericGpu\" /> class.\n            </summary>\n            <param name=\"name\">Component name.</param>\n            <param name=\"identifier\">Identifier that will be assigned to the device. Based on <see cref=\"T:LibreHardwareMonitor.Hardware.Identifier\" /></param>\n            <param name=\"settings\">Additional settings passed by the <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\" />.</param>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Gpu.GenericGpu.DeviceId\">\n            <summary>\n            Gets the device identifier.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Gpu.IntelIntegratedGpu.DeviceId\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Gpu.NvidiaGpu.DeviceId\">\n            <inheritdoc />\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.GroupAffinity\">\n            <summary>\n            This structure describes a group-specific affinity.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.GroupAffinity.#ctor(System.UInt16,System.UInt64)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.GroupAffinity\" /> struct.\n            </summary>\n            <param name=\"group\">The group.</param>\n            <param name=\"mask\">The mask.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.GroupAffinity.Single(System.UInt16,System.Int32)\">\n            <summary>\n            Gets a single group affinity.\n            </summary>\n            <param name=\"group\">The group.</param>\n            <param name=\"index\">The index.</param>\n            <returns><see cref=\"T:LibreHardwareMonitor.Hardware.GroupAffinity\" />.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.GroupAffinity.Group\">\n            <summary>\n            Gets the group.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.GroupAffinity.Mask\">\n            <summary>\n            Gets the mask.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.GroupAffinity.Equals(System.Object)\">\n            <summary>\n            Determines whether the specified <see cref=\"T:System.Object\" /> is equal to this instance.\n            </summary>\n            <param name=\"o\">The <see cref=\"T:System.Object\" /> to compare with this instance.</param>\n            <returns><c>true</c> if the specified <see cref=\"T:System.Object\" /> is equal to this instance; otherwise, <c>false</c>.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.GroupAffinity.GetHashCode\">\n            <summary>\n            Returns a hash code for this instance.\n            </summary>\n            <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.GroupAffinity.op_Equality(LibreHardwareMonitor.Hardware.GroupAffinity,LibreHardwareMonitor.Hardware.GroupAffinity)\">\n            <summary>\n            Implements the == operator.\n            </summary>\n            <param name=\"a1\">The a1.</param>\n            <param name=\"a2\">The a2.</param>\n            <returns>The result of the operator.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.GroupAffinity.op_Inequality(LibreHardwareMonitor.Hardware.GroupAffinity,LibreHardwareMonitor.Hardware.GroupAffinity)\">\n            <summary>\n            Implements the != operator.\n            </summary>\n            <param name=\"a1\">The a1.</param>\n            <param name=\"a2\">The a2.</param>\n            <returns>The result of the operator.</returns>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Hardware\">\n            <summary>\n            Object representing a component of the computer.\n            <para>\n            Individual information can be read from the <see cref=\"P:LibreHardwareMonitor.Hardware.Hardware.Sensors\"/>.\n            </para>\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.#ctor(System.String,LibreHardwareMonitor.Hardware.Identifier,LibreHardwareMonitor.Hardware.ISettings)\">\n            <summary>\n            Creates a new <see cref=\"T:LibreHardwareMonitor.Hardware.Hardware\"/> instance based on the data provided.\n            </summary>\n            <param name=\"name\">Component name.</param>\n            <param name=\"identifier\">Identifier that will be assigned to the device. Based on <see cref=\"P:LibreHardwareMonitor.Hardware.Hardware.Identifier\"/></param>\n            <param name=\"settings\">Additional settings passed by the <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\"/>.</param>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.Hardware.Closing\">\n            <summary>\n            Event triggered when <see cref=\"T:LibreHardwareMonitor.Hardware.Hardware\"/> is closing.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Hardware.HardwareType\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Hardware.Identifier\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Hardware.Name\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Hardware.Parent\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Hardware.Properties\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Hardware.Sensors\">\n            <inheritdoc />\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Hardware.SubHardware\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.GetReport\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.Update\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.Accept(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.Traverse(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.ActivateSensor(LibreHardwareMonitor.Hardware.ISensor)\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.DeactivateSensor(LibreHardwareMonitor.Hardware.ISensor)\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Hardware.Close\">\n            <inheritdoc />\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.HardwareType\">\n            <summary>\n            Collection of identifiers representing the purpose of the hardware.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.HardwareEventHandler\">\n            <summary>\n            Handler that will trigger the actions assigned to it when the event occurs.\n            </summary>\n            <param name=\"hardware\">Component returned to the assigned action(s).</param>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.IComputer\">\n            <summary>\n            Basic abstract with methods for the class which can store all hardware and decides which devices are to be checked and updated.\n            </summary>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.IComputer.HardwareAdded\">\n            <summary>\n            Triggered when a new <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\" /> is registered.\n            </summary>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.IComputer.HardwareRemoved\">\n            <summary>\n            Triggered when a <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\" /> is removed.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.Hardware\">\n            <summary>\n            Gets a list of all known <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\" />.\n            <para>Can be updated by <see cref=\"T:LibreHardwareMonitor.Hardware.IVisitor\" />.</para>\n            </summary>\n            <returns>List of all enabled devices.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsBatteryEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Battery\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsControllerEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about:\n            <list>\n                <item>\n                    <see cref=\"T:LibreHardwareMonitor.Hardware.Controller.TBalancer.TBalancerGroup\" />\n                </item>\n                <item>\n                    <see cref=\"T:LibreHardwareMonitor.Hardware.Controller.Heatmaster.HeatmasterGroup\" />\n                </item>\n                <item>\n                    <see cref=\"T:LibreHardwareMonitor.Hardware.Controller.AquaComputer.AquaComputerGroup\" />\n                </item>\n                <item>\n                    <see cref=\"T:LibreHardwareMonitor.Hardware.Controller.AeroCool.AeroCoolGroup\" />\n                </item>\n                <item>\n                    <see cref=\"T:LibreHardwareMonitor.Hardware.Controller.Nzxt.NzxtGroup\" />\n                </item>\n            </list>\n            devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsCpuEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Cpu\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsGpuEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.GpuAmd\" /> or <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.GpuNvidia\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsMemoryEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Memory\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsMotherboardEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Motherboard\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsNetworkEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Network\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsPsuEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Psu\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IComputer.IsStorageEnabled\">\n            <summary>\n            Gets or sets a value indicating whether collecting information about <see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Storage\" /> devices should be enabled and updated.\n            </summary>\n            <returns><see langword=\"true\" /> if a given category of devices is already enabled.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IComputer.GetReport\">\n            <summary>\n            Generates full LibreHardwareMonitor report for devices that have been enabled.\n            </summary>\n            <returns>A formatted text string with library, OS and hardware information.</returns>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Identifier\">\n            <summary>\n            Represents a unique <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\" />/<see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\" /> identifier in text format with a / separator.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Identifier.#ctor(LibreHardwareMonitor.Hardware.Identifier,System.String[])\">\n            <summary>\n            Creates a new identifier instance based on the base <see cref=\"T:LibreHardwareMonitor.Hardware.Identifier\" /> and additional elements.\n            </summary>\n            <param name=\"identifier\">Base identifier being the beginning of the new one.</param>\n            <param name=\"extensions\">Additional parts by which the base <see cref=\"T:LibreHardwareMonitor.Hardware.Identifier\" /> will be extended.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Identifier.CompareTo(LibreHardwareMonitor.Hardware.Identifier)\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Identifier.ToString\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Identifier.Equals(System.Object)\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Identifier.GetHashCode\">\n            <inheritdoc />\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.IElement\">\n            <summary>\n            Abstract parent with logic for the abstract class that stores data.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IElement.Accept(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <summary>\n            Accepts the observer for this instance.\n            </summary>\n            <param name=\"visitor\">Computer observer making the calls.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IElement.Traverse(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <summary>\n            Call the <see cref=\"M:LibreHardwareMonitor.Hardware.IElement.Accept(LibreHardwareMonitor.Hardware.IVisitor)\"/> method for all child instances <c>(called only from visitors).</c>\n            </summary>\n            <param name=\"visitor\">Computer observer making the calls.</param>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.IGroup\">\n            <summary>\n            A group of devices from one category in one list.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IGroup.Hardware\">\n            <summary>\n            Gets a list that stores information about <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/> in a given group.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IGroup.GetReport\">\n            <summary>\n            Report containing most of the known information about all <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/> in this <see cref=\"T:LibreHardwareMonitor.Hardware.IGroup\"/>.\n            </summary>\n            <returns>A formatted text string with hardware information.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IGroup.Close\">\n            <summary>\n            Stop updating this group in the future.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SensorEventHandler\">\n            <summary>\n            Handler that will trigger the actions assigned to it when the event occurs.\n            </summary>\n            <param name=\"sensor\">Component returned to the assigned action(s).</param>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.IHardware\">\n            <summary>\n            Abstract object that stores information about a device. All sensors are available as an array of <see cref=\"P:LibreHardwareMonitor.Hardware.IHardware.Sensors\"/>.\n            <para>\n            Can contain <see cref=\"P:LibreHardwareMonitor.Hardware.IHardware.SubHardware\"/>.\n            Type specified in <see cref=\"P:LibreHardwareMonitor.Hardware.IHardware.HardwareType\"/>.\n            </para>\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IHardware.HardwareType\">\n            <summary>\n            <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.HardwareType\"/>\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IHardware.Identifier\">\n            <summary>\n            Gets a unique hardware ID that represents its location.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IHardware.Name\">\n            <summary>\n            Gets or sets device name.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IHardware.Parent\">\n            <summary>\n            Gets the device that is the parent of the current hardware. For example, the motherboard is the parent of SuperIO.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IHardware.Sensors\">\n            <summary>\n            Gets an array of all sensors such as <see cref=\"F:LibreHardwareMonitor.Hardware.SensorType.Temperature\"/>, <see cref=\"F:LibreHardwareMonitor.Hardware.SensorType.Clock\"/>, <see cref=\"F:LibreHardwareMonitor.Hardware.SensorType.Load\"/> etc.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IHardware.SubHardware\">\n            <summary>\n            Gets child devices, e.g. <see cref=\"T:LibreHardwareMonitor.Hardware.Motherboard.Lpc.LpcIO\"/> of the <see cref=\"T:LibreHardwareMonitor.Hardware.Motherboard.Motherboard\"/>.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IHardware.GetReport\">\n            <summary>\n            Report containing most of the known information about the current device.\n            </summary>\n            <returns>A formatted text string with hardware information.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IHardware.Update\">\n            <summary>\n            Refreshes the information stored in <see cref=\"P:LibreHardwareMonitor.Hardware.IHardware.Sensors\"/> array.\n            </summary>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.IHardware.SensorAdded\">\n            <summary>\n            An <see langword=\"event\"/> that will be triggered when a new sensor appears.\n            </summary>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.IHardware.SensorRemoved\">\n            <summary>\n            An <see langword=\"event\"/> that will be triggered when one of the sensors is removed.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IHardware.Properties\">\n            <summary>\n            Gets rarely changed hardware properties that can't be represented as sensors.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.IParameter\">\n            <summary>\n            Abstract object that represents additional parameters included in <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IParameter.DefaultValue\">\n            <summary>\n            Gets a parameter default value defined by library.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IParameter.Description\">\n            <summary>\n            Gets a parameter description defined by library.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IParameter.Identifier\">\n            <summary>\n            Gets a unique parameter ID that represents its location.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IParameter.IsDefault\">\n            <summary>\n            Gets or sets information whether the given <see cref=\"T:LibreHardwareMonitor.Hardware.IParameter\"/> is the default for <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IParameter.Name\">\n            <summary>\n            Gets a parameter name defined by library.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IParameter.Sensor\">\n            <summary>\n            Gets the sensor that is the data container for the given parameter.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.IParameter.Value\">\n            <summary>\n            Gets or sets the current value.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SensorType\">\n            <summary>\n            Category of what type the selected sensor is.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SensorValue\">\n            <summary>\n            Stores the readed value and the time in which it was recorded.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SensorValue.#ctor(System.Single,System.DateTime)\">\n            <param name=\"value\"><see cref=\"P:LibreHardwareMonitor.Hardware.SensorValue.Value\"/> of the sensor.</param>\n            <param name=\"time\">The time code during which the <see cref=\"P:LibreHardwareMonitor.Hardware.SensorValue.Value\"/> was recorded.</param>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SensorValue.Value\">\n            <summary>\n            Gets the value of the sensor\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SensorValue.Time\">\n            <summary>\n            Gets the time code during which the <see cref=\"P:LibreHardwareMonitor.Hardware.SensorValue.Value\"/> was recorded.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ISensor\">\n            <summary>\n            Stores information about the readed values and the time in which they were collected.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.Hardware\">\n            <summary>\n            <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/>\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.Index\">\n            <summary>\n            Gets the unique identifier of this sensor for a given <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.Max\">\n            <summary>\n            Gets a maximum value recorded for the given sensor.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.Min\">\n            <summary>\n            Gets a minimum value recorded for the given sensor.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.Name\">\n            <summary>\n            Gets or sets a sensor name.\n            <para>By default determined by the library.</para>\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.SensorType\">\n            <summary>\n            <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.SensorType\"/>\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.Value\">\n            <summary>\n            Gets the last recorded value for the given sensor.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensor.Values\">\n            <summary>\n            Gets a list of recorded values for the given sensor.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ISensor.ResetMin\">\n            <summary>\n            Resets a value stored in <see cref=\"P:LibreHardwareMonitor.Hardware.ISensor.Min\"/>.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ISensor.ResetMax\">\n            <summary>\n            Resets a value stored in <see cref=\"P:LibreHardwareMonitor.Hardware.ISensor.Max\"/>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ISensorLimits\">\n            <summary>\n            Abstract object that stores information about the limits of <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensorLimits.HighLimit\">\n            <summary>\n            Upper limit of <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ISensorLimits.LowLimit\">\n            <summary>\n            Lower limit of <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> value.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ICriticalSensorLimits\">\n            <summary>\n            Abstract object that stores information about the critical limits of <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ICriticalSensorLimits.CriticalHighLimit\">\n            <summary>\n            Critical upper limit of <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> value.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ICriticalSensorLimits.CriticalLowLimit\">\n            <summary>\n            Critical lower limit of <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> value.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ISettings\">\n            <summary>\n            Abstract object that stores settings passed to <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\"/>, <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/> and <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ISettings.Contains(System.String)\">\n            <summary>\n            Returns information whether the given collection of settings contains a value assigned to the given key.\n            </summary>\n            <param name=\"name\">Key to which the setting value is assigned.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ISettings.SetValue(System.String,System.String)\">\n            <summary>\n            Assigns a setting option to a given key.\n            </summary>\n            <param name=\"name\">Key to which the setting value is assigned.</param>\n            <param name=\"value\">Text setting value.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ISettings.GetValue(System.String,System.String)\">\n            <summary>\n            Gets a setting option assigned to the given key.\n            </summary>\n            <param name=\"name\">Key to which the setting value is assigned.</param>\n            <param name=\"value\">Default value.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ISettings.Remove(System.String)\">\n            <summary>\n            Removes a setting with the specified key from the settings collection.\n            </summary>\n            <param name=\"name\">Key to which the setting value is assigned.</param>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.IVisitor\">\n            <summary>\n            Base interface for creating observers who call to devices.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IVisitor.VisitComputer(LibreHardwareMonitor.Hardware.IComputer)\">\n            <summary>\n            Refreshes the values of all <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> in all <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/> on selected <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\"/>.\n            </summary>\n            <param name=\"computer\">Instance of the computer to be revisited.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IVisitor.VisitHardware(LibreHardwareMonitor.Hardware.IHardware)\">\n            <summary>\n            Refreshes the values of all <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> on selected <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/>.\n            </summary>\n            <param name=\"hardware\">Instance of the hardware to be revisited.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IVisitor.VisitSensor(LibreHardwareMonitor.Hardware.ISensor)\">\n            <summary>\n            Refreshes the values on selected <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n            <param name=\"sensor\">Instance of the sensor to be revisited.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.IVisitor.VisitParameter(LibreHardwareMonitor.Hardware.IParameter)\">\n            <summary>\n            Refreshes the values on selected <see cref=\"T:LibreHardwareMonitor.Hardware.IParameter\"/>.\n            </summary>\n            <param name=\"parameter\">Instance of the parameter to be revisited.</param>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempChipset\">\n            <summary>Chipset temperature [℃]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempCPU\">\n            <summary>CPU temperature [℃]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempMB\">\n            <summary>motherboard temperature [℃]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempTSensor\">\n            <summary>\"T_Sensor\" temperature sensor reading [℃]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempVrm\">\n            <summary>VRM temperature [℃]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.VoltageCPU\">\n            <summary>CPU Core voltage [mV]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.FanCPUOpt\">\n            <summary>CPU_Opt fan [RPM]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.FanVrmHS\">\n            <summary>VRM heat sink fan [RPM]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.FanChipset\">\n            <summary>Chipset fan [RPM]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.FanWaterPump\">\n            <summary>Water Pump [RPM]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.FanWaterFlow\">\n            <summary>Water flow sensor reading [RPM]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.CurrCPU\">\n            <summary>CPU current [A]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempWaterIn\">\n            <summary>\"Water_In\" temperature sensor reading [℃]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempWaterOut\">\n            <summary>\"Water_Out\" temperature sensor reading [℃]</summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController.ECSensor.TempWaterBlockIn\">\n            <summary>Water block temperature sensor reading [℃]</summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.WindowsEmbeddedControllerIO\">\n            <summary>\n            An unsafe but universal implementation for the ACPI Embedded Controller IO interface for Windows\n            </summary>\n            <remarks>\n            It is unsafe because of possible race condition between this application and the PC firmware when\n            writing to the EC registers. For a safe approach ACPI/WMI methods have to be used, but those are\n            different for each motherboard model.\n            </remarks>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Motherboard.Lpc.IT87XX.SelectBank(System.Byte)\">\n            <summary>\n            Selects another bank. Memory from 0x10-0xAF swaps to data from new bank.\n            Beware to select the default bank 0 after changing.\n            Bank selection is reset after power cycle.\n            </summary>\n            <param name=\"bankIndex\">New bank index. Can be a value of 0-3.</param>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Motherboard.Motherboard\">\n            <summary>\n            Represents the motherboard of a computer with its <see cref=\"T:LibreHardwareMonitor.Hardware.Motherboard.Lpc.LpcIO\"/> and <see cref=\"T:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController\"/> as <see cref=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SubHardware\"/>.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.#ctor(LibreHardwareMonitor.Hardware.SMBios,LibreHardwareMonitor.Hardware.ISettings)\">\n            <summary>\n            Creates motherboard instance by retrieving information from <see cref=\"T:LibreHardwareMonitor.Hardware.SMBios\"/> and creates a new <see cref=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SubHardware\"/> based on data from <see cref=\"T:LibreHardwareMonitor.Hardware.Motherboard.Lpc.LpcIO\"/> and <see cref=\"T:LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC.EmbeddedController\"/>.\n            </summary>\n            <param name=\"smBios\"><see cref=\"T:LibreHardwareMonitor.Hardware.SMBios\"/> table containing motherboard data.</param>\n            <param name=\"settings\">Additional settings passed by <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\"/>.</param>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SensorAdded\">\n            <inheritdoc/>\n        </member>\n        <member name=\"E:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SensorRemoved\">\n            <inheritdoc/>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.HardwareType\">\n            <returns><see cref=\"F:LibreHardwareMonitor.Hardware.HardwareType.Motherboard\"/></returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Identifier\">\n            <inheritdoc/>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Name\">\n            <summary>\n            Gets the name obtained from <see cref=\"T:LibreHardwareMonitor.Hardware.SMBios\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Parent\">\n            <inheritdoc/>\n            <returns>Always <see langword=\"null\"/></returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Properties\">\n            <inheritdoc/>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Sensors\">\n            <inheritdoc/>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SMBios\">\n            <summary>\n            Gets the <see cref=\"T:LibreHardwareMonitor.Hardware.SMBios\"/> information.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SubHardware\">\n            <inheritdoc/>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.GetReport\">\n            <inheritdoc/>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Update\">\n            <summary>\n            Motherboard itself cannot be updated. Update <see cref=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SubHardware\"/> instead.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Accept(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <inheritdoc/>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Traverse(LibreHardwareMonitor.Hardware.IVisitor)\">\n            <inheritdoc/>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.Close\">\n            <summary>\n            Closes <see cref=\"P:LibreHardwareMonitor.Hardware.Motherboard.Motherboard.SubHardware\"/> using <see cref=\"M:LibreHardwareMonitor.Hardware.Hardware.Close\"/>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ParameterDescription\">\n            <summary>\n            Composite class containing information about the selected <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ParameterDescription.#ctor(System.String,System.String,System.Single)\">\n            <summary>\n            Creates a new instance and assigns values.\n            </summary>\n            <param name=\"name\">Name of the selected component.</param>\n            <param name=\"description\">Description of the selected component.</param>\n            <param name=\"defaultValue\">Default value of the selected component.</param>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ParameterDescription.Name\">\n            <summary>\n            Gets a name of the parent <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ParameterDescription.Description\">\n            <summary>\n            Gets a description of the parent <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ParameterDescription.DefaultValue\">\n            <summary>\n            Gets a default value of the parent <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SensorVisitor\">\n            <summary>\n            Observer making calls to selected component <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>'s.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SensorVisitor.#ctor(LibreHardwareMonitor.Hardware.SensorEventHandler)\">\n            <summary>\n            Creates a new observer instance.\n            </summary>\n            <param name=\"handler\">Instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.SensorEventHandler\"/> that triggers events during visiting the <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/>.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SensorVisitor.VisitComputer(LibreHardwareMonitor.Hardware.IComputer)\">\n            <summary>\n            Goes through all the components of the specified <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\"/> with its <see cref=\"M:LibreHardwareMonitor.Hardware.IElement.Traverse(LibreHardwareMonitor.Hardware.IVisitor)\"/>.\n            </summary>\n            <param name=\"computer\">Computer class instance that is derived from the <see cref=\"T:LibreHardwareMonitor.Hardware.IComputer\"/> interface.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SensorVisitor.VisitHardware(LibreHardwareMonitor.Hardware.IHardware)\">\n            <summary>\n            Goes through all the components of the specified <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/> with its <see cref=\"M:LibreHardwareMonitor.Hardware.IElement.Traverse(LibreHardwareMonitor.Hardware.IVisitor)\"/>.\n            </summary>\n            <param name=\"hardware\">Hardware class instance that is derived from the <see cref=\"T:LibreHardwareMonitor.Hardware.IHardware\"/> interface.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SensorVisitor.VisitSensor(LibreHardwareMonitor.Hardware.ISensor)\">\n            <summary>\n            Goes through all the components of the specified <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> using <see cref=\"T:LibreHardwareMonitor.Hardware.SensorEventHandler\"/>.\n            </summary>\n            <param name=\"sensor\">Sensor class instance that is derived from the <see cref=\"T:LibreHardwareMonitor.Hardware.ISensor\"/> interface.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SensorVisitor.VisitParameter(LibreHardwareMonitor.Hardware.IParameter)\">\n            <summary>\n            Goes through all the components of the specified <see cref=\"T:LibreHardwareMonitor.Hardware.IParameter\"/>.\n            <para>\n            <see cref=\"T:System.NotImplementedException\"/>\n            </para>\n            </summary>\n            <param name=\"parameter\">Parameter class instance that is derived from the <see cref=\"T:LibreHardwareMonitor.Hardware.IParameter\"/> interface.</param>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SystemEnclosureSecurityStatus\">\n            <summary>\n            System enclosure security status based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.4.3</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SystemEnclosureState\">\n            <summary>\n            System enclosure state based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.4.2</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SystemEnclosureType\">\n            <summary>\n            System enclosure type based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.4.1</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ProcessorFamily\">\n            <summary>\n            Processor family based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.5.2</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ProcessorCharacteristics\">\n            <summary>\n            Processor characteristics based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.5.9</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ProcessorType\">\n            <summary>\n            Processor type based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.5.1</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ProcessorSocket\">\n            <summary>\n            Processor socket based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.5.5</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SystemWakeUp\">\n            <summary>\n            System wake-up type based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.2.2</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.CacheAssociativity\">\n            <summary>\n            Cache associativity based on <see href=\"https://www.dmtf.org/dsp/DSP0134\">DMTF SMBIOS Reference Specification v.3.3.0, Chapter 7.8.5</see>.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.CacheDesignation\">\n            <summary>\n            Processor cache level.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.MemoryType\">\n            <summary>\n            Memory type.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.InformationBase.#ctor(System.Byte[],System.Collections.Generic.IList{System.String})\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.InformationBase\" /> class.\n            </summary>\n            <param name=\"data\">The data.</param>\n            <param name=\"strings\">The strings.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.InformationBase.GetByte(System.Int32)\">\n            <summary>\n            Gets the byte.\n            </summary>\n            <param name=\"offset\">The offset.</param>\n            <returns><see cref=\"T:System.Byte\" />.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.InformationBase.GetWord(System.Int32)\">\n            <summary>\n            Gets the word.\n            </summary>\n            <param name=\"offset\">The offset.</param>\n            <returns><see cref=\"T:System.UInt16\" />.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.InformationBase.GetDword(System.Int32)\">\n            <summary>\n            Gets the dword.\n            </summary>\n            <param name=\"offset\">The offset.</param>\n            <returns><see cref=\"T:System.UInt16\" />.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.InformationBase.GetQword(System.Int32)\">\n            <summary>\n            Gets the qword.\n            </summary>\n            <param name=\"offset\">The offset.</param>\n            <returns><see cref=\"T:System.UInt64\" />.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.InformationBase.GetString(System.Int32)\">\n            <summary>\n            Gets the string.\n            </summary>\n            <param name=\"offset\">The offset.</param>\n            <returns><see cref=\"T:System.String\" />.</returns>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.BiosInformation\">\n            <summary>\n            Motherboard BIOS information obtained from the SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BiosInformation.Date\">\n            <summary>\n            Gets the BIOS release date.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BiosInformation.Size\">\n            <summary>\n            Gets the size of the physical device containing the BIOS.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BiosInformation.Vendor\">\n            <summary>\n            Gets the string number of the BIOS Vendor’s Name.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BiosInformation.Version\">\n            <summary>\n            Gets the string number of the BIOS Version. This value is a free-form string that may contain Core and OEM version information.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.BiosInformation.GetSize\">\n            <summary>\n            Gets the size.\n            </summary>\n            <returns><see cref=\"T:System.Nullable`1\" />.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.BiosInformation.GetDate(System.String)\">\n            <summary>\n            Gets the date.\n            </summary>\n            <param name=\"date\">The bios date.</param>\n            <returns><see cref=\"T:System.Nullable`1\" />.</returns>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SystemInformation\">\n            <summary>\n            System information obtained from the SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemInformation.Family\">\n            <summary>\n            Gets the family associated with system.\n            <para>\n            This text string identifies the family to which a particular computer belongs. A family refers to a set of computers that are similar but not identical from a hardware or software point of\n            view. Typically, a family is composed of different computer models, which have different configurations and pricing points. Computers in the same family often have similar branding and cosmetic\n            features.\n            </para>\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemInformation.ManufacturerName\">\n            <summary>\n            Gets the manufacturer name associated with system.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemInformation.ProductName\">\n            <summary>\n            Gets the product name associated with system.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemInformation.SerialNumber\">\n            <summary>\n            Gets the serial number string associated with system.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemInformation.Version\">\n            <summary>\n            Gets the version string associated with system.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemInformation.WakeUp\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.SystemWakeUp\" />\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SystemEnclosure\">\n            <summary>\n            System enclosure obtained from the SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.AssetTag\">\n            <summary>\n            Gets the asset tag associated with the enclosure or chassis.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.BootUpState\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.SystemEnclosureState\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.LockDetected\">\n            <summary>\n            Gets or sets the system enclosure lock.\n            </summary>\n            <returns>System enclosure lock is present if <see langword=\"true\" />. Otherwise, either a lock is not present or it is unknown if the enclosure has a lock.</returns>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.ManufacturerName\">\n            <summary>\n            Gets the string describing the chassis or enclosure manufacturer name.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.PowerCords\">\n            <summary>\n            Gets the number of power cords associated with the enclosure or chassis.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.PowerSupplyState\">\n            <summary>\n            Gets the state of the enclosure’s power supply (or supplies) when last booted.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.RackHeight\">\n            <summary>\n            Gets the height of the enclosure, in 'U's. A U is a standard unit of measure for the height of a rack or rack-mountable component and is equal to 1.75 inches or 4.445 cm. A value of <c>0</c>\n            indicates that the enclosure height is unspecified.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.SecurityStatus\">\n            <summary>\n            Gets the physical security status of the enclosure when last booted.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.SerialNumber\">\n            <summary>\n            Gets the string describing the chassis or enclosure serial number.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.SKU\">\n            <summary>\n            Gets the string describing the chassis or enclosure SKU number.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.ThermalState\">\n            <summary>\n            Gets the thermal state of the enclosure when last booted.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.Type\">\n            <summary>\n            Gets <inheritdoc cref=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.Type\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SystemEnclosure.Version\">\n            <summary>\n            Gets the number of null-terminated string representing the chassis or enclosure version.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.BaseBoardInformation\">\n            <summary>\n            Motherboard information obtained from the SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BaseBoardInformation.ManufacturerName\">\n            <summary>\n            Gets the value that represents the manufacturer's name.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BaseBoardInformation.ProductName\">\n            <summary>\n            Gets the value that represents the motherboard's name.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BaseBoardInformation.SerialNumber\">\n            <summary>\n            Gets the value that represents the motherboard's serial number.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.BaseBoardInformation.Version\">\n            <summary>\n            Gets the value that represents the motherboard's revision number.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.ProcessorInformation\">\n            <summary>\n            Processor information obtained from the SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.Characteristics\">\n            <summary>\n            Gets the characteristics of the processor.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.CoreCount\">\n            <summary>\n            Gets the value that represents the number of cores per processor socket.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.CoreEnabled\">\n            <summary>\n            Gets the value that represents the number of enabled cores per processor socket.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.CurrentSpeed\">\n            <summary>\n            Gets the value that represents the current processor speed (in MHz).\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.ExternalClock\">\n            <summary>\n            Gets the external Clock Frequency, in MHz. If the value is unknown, the field is set to 0.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.Family\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.ProcessorFamily\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.Handle\">\n            <summary>\n            Gets the handle.\n            </summary>\n            <value>The handle.</value>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.Id\">\n            <summary>\n            Gets the identifier.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.L1CacheHandle\">\n            <summary>\n            Gets the L1 cache handle.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.L2CacheHandle\">\n            <summary>\n            Gets the L2 cache handle.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.L3CacheHandle\">\n            <summary>\n            Gets the L3 cache handle.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.ManufacturerName\">\n            <summary>\n            Gets the string number of Processor Manufacturer.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.MaxSpeed\">\n            <summary>\n            Gets the value that represents the maximum processor speed (in MHz) supported by the system for this processor socket.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.ProcessorType\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.ProcessorType\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.Serial\">\n            <summary>\n            Gets the value that represents the string number for the serial number of this processor.\n            <para>This value is set by the manufacturer and normally not changeable.</para>\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.Socket\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.ProcessorSocket\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.SocketDesignation\">\n            <summary>\n            Gets the string number for Reference Designation.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.ThreadCount\">\n            <summary>\n            Gets the value that represents the number of threads per processor socket.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ProcessorInformation.Version\">\n            <summary>\n            Gets the value that represents the string number describing the Processor.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.CacheInformation\">\n            <summary>\n            Cache information obtained from the SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.CacheInformation.Associativity\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.CacheAssociativity\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.CacheInformation.Designation\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.CacheDesignation\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.CacheInformation.Handle\">\n            <summary>\n            Gets the handle.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.CacheInformation.Size\">\n            <summary>\n            Gets the value that represents the installed cache size.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.CacheInformation.GetCacheDesignation\">\n            <summary>\n            Gets the cache designation.\n            </summary>\n            <returns><see cref=\"T:LibreHardwareMonitor.Hardware.CacheDesignation\" />.</returns>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.MemoryDevice\">\n            <summary>\n            Memory information obtained from the SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.BankLocator\">\n            <summary>\n            Gets the string number of the string that identifies the physically labeled bank where the memory device is located.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.DeviceLocator\">\n            <summary>\n            Gets the string number of the string that identifies the physically-labeled socket or board position where the memory device is located.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.ManufacturerName\">\n            <summary>\n            Gets the string number for the manufacturer of this memory device.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.PartNumber\">\n            <summary>\n            Gets the string number for the part number of this memory device.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.SerialNumber\">\n            <summary>\n            Gets the string number for the serial number of this memory device.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.Size\">\n            <summary>\n            Gets the size of the memory device. If the value is 0, no memory device is installed in the socket.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.Speed\">\n            <summary>\n            Gets the value that identifies the maximum capable speed of the device, in mega transfers per second (MT/s).\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.MemoryDevice.Type\">\n            <summary>\n            Gets the type of this memory device.\n            </summary>\n            <value>The type.</value>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.SMBios\">\n            <summary>\n            Reads and processes information encoded in an SMBIOS table.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SMBios.#ctor\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.SMBios\" /> class.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SMBios.Bios\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.BiosInformation\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SMBios.Board\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.BaseBoardInformation\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SMBios.MemoryDevices\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.MemoryDevice\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SMBios.ProcessorCaches\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.CacheInformation\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SMBios.Processors\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.ProcessorInformation\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SMBios.System\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.SystemInformation\" />\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.SMBios.SystemEnclosure\">\n            <summary>\n            Gets <inheritdoc cref=\"T:LibreHardwareMonitor.Hardware.SystemEnclosure\" />\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.SMBios.GetReport\">\n            <summary>\n            Report containing most of the information that could be read from the SMBIOS table.\n            </summary>\n            <returns>A formatted text string with computer information and the entire SMBIOS table.</returns>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Storage.AbstractStorage.PerformanceValue\">\n            <summary>\n            Helper to calculate the disk performance with base timestamps\n            https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-perfrawdata\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Storage.AtaStorage.Smart\">\n            <summary>\n            Gets the SMART data.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Storage.AtaStorage.SmartAttributes\">\n            <summary>\n            Gets the SMART attributes.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Storage.NVMeGeneric.Smart\">\n            <summary>\n            Gets the SMART data.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Storage.SmartAttribute.#ctor(System.Byte,System.String)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.Storage.SmartAttribute\" /> class.\n            </summary>\n            <param name=\"id\">The SMART id of the attribute.</param>\n            <param name=\"name\">The name of the attribute.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Storage.SmartAttribute.#ctor(System.Byte,System.String,LibreHardwareMonitor.Hardware.Storage.SmartAttribute.RawValueConversion)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.Storage.SmartAttribute\" /> class.\n            </summary>\n            <param name=\"id\">The SMART id of the attribute.</param>\n            <param name=\"name\">The name of the attribute.</param>\n            <param name=\"rawValueConversion\">\n            A delegate for converting the raw byte\n            array into a value (or null to use the attribute value).\n            </param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Storage.SmartAttribute.#ctor(System.Byte,System.String,LibreHardwareMonitor.Hardware.Storage.SmartAttribute.RawValueConversion,System.Nullable{LibreHardwareMonitor.Hardware.SensorType},System.Int32,System.String,System.Boolean,LibreHardwareMonitor.Hardware.ParameterDescription[])\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Hardware.Storage.SmartAttribute\" /> class.\n            </summary>\n            <param name=\"id\">The SMART id of the attribute.</param>\n            <param name=\"name\">The name of the attribute.</param>\n            <param name=\"rawValueConversion\">\n            A delegate for converting the raw byte\n            array into a value (or null to use the attribute value).\n            </param>\n            <param name=\"sensorType\">\n            Type of the sensor or null if no sensor is to\n            be created.\n            </param>\n            <param name=\"sensorChannel\">\n            If there exists more than one attribute with\n            the same sensor channel and type, then a sensor is created only for the\n            first attribute.\n            </param>\n            <param name=\"sensorName\">\n            The name to be used for the sensor, or null if\n            no sensor is created.\n            </param>\n            <param name=\"defaultHiddenSensor\">True to hide the sensor initially.</param>\n            <param name=\"parameterDescriptions\">\n            Description for the parameters of the sensor\n            (or null).\n            </param>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.Storage.SmartAttribute.Id\">\n            <summary>\n            Gets the SMART identifier.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Hardware.Storage.SmartNames\">\n            <summary>\n            Localization class for SMART attribute names.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Storage.SsdMicron.UpdateAdditionalSensors(LibreHardwareMonitor.Interop.Kernel32.SMART_ATTRIBUTE[])\">\n            <inheritdoc />\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.Storage.WindowsSmart.ReadSmartHealth\">\n            <summary>\n            Reads Smart health status of the drive\n            </summary>\n            <returns>True, if drive is healthy; False, if unhealthy; Null, if it cannot be read</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ThreadAffinity.#cctor\">\n            <summary>\n            Initializes static members of the <see cref=\"T:LibreHardwareMonitor.Hardware.ThreadAffinity\" /> class.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Hardware.ThreadAffinity.ProcessorGroupCount\">\n            <summary>\n            Gets the processor group count.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ThreadAffinity.IsValid(LibreHardwareMonitor.Hardware.GroupAffinity)\">\n            <summary>\n            Returns true if the <paramref name=\"affinity\"/> is valid.\n            </summary>\n            <param name=\"affinity\">The affinity.</param>\n            <returns><c>true</c> if the specified affinity is valid; otherwise, <c>false</c>.</returns>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Hardware.ThreadAffinity.Set(LibreHardwareMonitor.Hardware.GroupAffinity)\">\n            <summary>\n            Sets the processor group affinity for the current thread.\n            </summary>\n            <param name=\"affinity\">The processor group affinity.</param>\n            <returns>The previous processor group affinity.</returns>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_OK_WAIT\">\n            <summary>\n            All OK, but need to wait.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_OK_RESTART\">\n            <summary>\n            All OK, but need restart.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_OK_MODE_CHANGE\">\n            <summary>\n            All OK but need mode change.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_OK_WARNING\">\n            <summary>\n            All OK, but with warning.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_OK\">\n            <summary>\n            ADL function completed successfully.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR\">\n            <summary>\n            Generic Error. Most likely one or more of the Escape calls to the driver\n            failed!\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_NOT_INIT\">\n            <summary>\n            ADL not initialized.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_INVALID_PARAM\">\n            <summary>\n            One of the parameter passed is invalid.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_INVALID_PARAM_SIZE\">\n            <summary>\n            One of the parameter size is invalid.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_INVALID_ADL_IDX\">\n            <summary>\n            Invalid ADL index passed.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_INVALID_CONTROLLER_IDX\">\n            <summary>\n            Invalid controller index passed.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_INVALID_DIPLAY_IDX\">\n            <summary>\n            Invalid display index passed.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_NOT_SUPPORTED\">\n            <summary>\n            Function not supported by the driver.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_NULL_POINTER\">\n            <summary>\n            Null Pointer error.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_DISABLED_ADAPTER\">\n            <summary>\n            Call can't be made due to disabled adapter.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_INVALID_CALLBACK\">\n            <summary>\n            Invalid Callback.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_RESOURCE_CONFLICT\">\n            <summary>\n            Display Resource conflict.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_SET_INCOMPLETE\">\n            <summary>\n            Failed to update some of the values. Can be returned by set request that\n            include multiple values if not all values were successfully committed.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.AtiAdlxx.ADLStatus.ADL_ERR_NO_XDISPLAY\">\n            <summary>\n            There's no Linux XDisplay in Linux Console environment.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_CRITICAL_WARNING.AvailableSpaceLow\">\n            <summary>\n            If set to 1, then the available spare space has fallen below the threshold.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_CRITICAL_WARNING.TemperatureThreshold\">\n            <summary>\n            If set to 1, then a temperature is above an over temperature threshold or below an under temperature threshold.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_CRITICAL_WARNING.ReliabilityDegraded\">\n            <summary>\n            If set to 1, then the device reliability has been degraded due to significant media related errors or any internal error that degrades device reliability.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_CRITICAL_WARNING.ReadOnly\">\n            <summary>\n            If set to 1, then the media has been placed in read only mode\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_CRITICAL_WARNING.VolatileMemoryBackupDeviceFailed\">\n            <summary>\n            If set to 1, then the volatile memory backup device has failed. This field is only valid if the controller has a volatile memory backup solution.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Interop.Kernel32.CreateStruct``1\">\n            <summary>\n            Create a instance from a struct with zero initialized memory arrays\n            no need to init every inner array with the correct sizes\n            </summary>\n            <typeparam name=\"T\">type of struct that is needed</typeparam>\n            <returns></returns>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.ATA_COMMAND.ATA_SMART\">\n            <summary>\n            SMART data requested.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.ATA_COMMAND.ATA_IDENTIFY_DEVICE\">\n            <summary>\n            Identify data is requested.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.SMART_READ_DATA\">\n            <summary>\n            Read SMART data.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.READ_THRESHOLDS\">\n            <summary>\n            Read SMART thresholds.\n            obsolete\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.ENABLE_DISABLE_AUTOSAVE\">\n            <summary>\n            Autosave SMART data.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.SAVE_ATTRIBUTE_VALUES\">\n            <summary>\n            Save SMART attributes.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.EXECUTE_OFFLINE_DIAGS\">\n            <summary>\n            Set SMART to offline immediately.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.SMART_READ_LOG\">\n            <summary>\n            Read SMART log.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.SMART_WRITE_LOG\">\n            <summary>\n            Write SMART log.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.WRITE_THRESHOLDS\">\n            <summary>\n            Write SMART thresholds.\n            obsolete\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.ENABLE_SMART\">\n            <summary>\n            Enable SMART.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.DISABLE_SMART\">\n            <summary>\n            Disable SMART.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.RETURN_SMART_STATUS\">\n            <summary>\n            Get SMART status.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.SMART_FEATURES.ENABLE_DISABLE_AUTO_OFFLINE\">\n            <summary>\n            Set SMART to offline automatically.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.MP\">\n            <summary>\n            bit 0:15 Maximum  Power (MP) in centiwatts\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.Reserved0\">\n            <summary>\n            bit 16:23\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.MPS_NOPS\">\n            <summary>\n            bit 24 Max Power Scale (MPS), bit 25 Non-Operational State (NOPS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.ENLAT\">\n            <summary>\n            bit 32:63 Entry Latency (ENLAT) in microseconds\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.EXLAT\">\n            <summary>\n            bit 64:95 Exit Latency (EXLAT) in microseconds\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.RRT\">\n            <summary>\n            bit 96:100 Relative Read Throughput (RRT)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.RRL\">\n            <summary>\n            bit 104:108 Relative Read Latency (RRL)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.RWT\">\n            <summary>\n            bit 112:116 Relative Write Throughput (RWT)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.RWL\">\n            <summary>\n            bit 120:124 Relative Write Latency (RWL)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.IDLP\">\n            <summary>\n            bit 128:143 Idle Power (IDLP)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.IPS\">\n            <summary>\n            bit 150:151 Idle Power Scale (IPS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.Reserved7\">\n            <summary>\n            bit 152:159\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.ACTP\">\n            <summary>\n            bit 160:175 Active Power (ACTP)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.APW_APS\">\n            <summary>\n            bit 176:178 Active Power Workload (APW), bit 182:183  Active Power Scale (APS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_POWER_STATE_DESC.Reserved9\">\n            <summary>\n            bit 184:255.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.VID\">\n            <summary>\n            byte 0:1 M - PCI Vendor ID (VID)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.SSVID\">\n            <summary>\n            byte 2:3 M - PCI Subsystem Vendor ID (SSVID)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.SN\">\n            <summary>\n            byte 4: 23 M - Serial Number (SN)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.MN\">\n            <summary>\n            byte 24:63 M - Model Number (MN)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.FR\">\n            <summary>\n            byte 64:71 M - Firmware Revision (FR)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.RAB\">\n            <summary>\n            byte 72 M - Recommended Arbitration Burst (RAB)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.IEEE\">\n            <summary>\n            byte 73:75 M - IEEE OUI Identifier (IEEE). Controller Vendor code.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.CMIC\">\n            <summary>\n            byte 76 O - Controller Multi-Path I/O and Namespace Sharing Capabilities (CMIC)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.MDTS\">\n            <summary>\n            byte 77 M - Maximum Data Transfer Size (MDTS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.CNTLID\">\n            <summary>\n            byte 78:79 M - Controller ID (CNTLID)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.VER\">\n            <summary>\n            byte 80:83 M - Version (VER)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.RTD3R\">\n            <summary>\n            byte 84:87 M - RTD3 Resume Latency (RTD3R)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.RTD3E\">\n            <summary>\n            byte 88:91 M - RTD3 Entry Latency (RTD3E)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.OAES\">\n            <summary>\n            byte 92:95 M - Optional Asynchronous Events Supported (OAES)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.Reserved0\">\n            <summary>\n            byte 96:239.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.ReservedForManagement\">\n            <summary>\n            byte 240:255.  Refer to the NVMe Management Interface Specification for definition.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.OACS\">\n            <summary>\n            byte 256:257 M - Optional Admin Command Support (OACS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.ACL\">\n            <summary>\n            byte 258 M - Abort Command Limit (ACL)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.AERL\">\n            <summary>\n            byte 259 M - Asynchronous Event Request Limit (AERL)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.FRMW\">\n            <summary>\n            byte 260 M - Firmware Updates (FRMW)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.LPA\">\n            <summary>\n            byte 261 M - Log Page Attributes (LPA)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.ELPE\">\n            <summary>\n            byte 262 M - Error Log Page Entries (ELPE)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.NPSS\">\n            <summary>\n            byte 263 M - Number of Power States Support (NPSS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.AVSCC\">\n            <summary>\n            byte 264 M - Admin Vendor Specific Command Configuration (AVSCC)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.APSTA\">\n            <summary>\n            byte 265 O - Autonomous Power State Transition Attributes (APSTA)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.WCTEMP\">\n            <summary>\n            byte 266:267 M - Warning Composite Temperature Threshold (WCTEMP)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.CCTEMP\">\n            <summary>\n            byte 268:269 M - Critical Composite Temperature Threshold (CCTEMP)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.MTFA\">\n            <summary>\n            byte 270:271 O - Maximum Time for Firmware Activation (MTFA)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.HMPRE\">\n            <summary>\n            byte 272:275 O - Host Memory Buffer Preferred Size (HMPRE)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.HMMIN\">\n            <summary>\n            byte 276:279 O - Host Memory Buffer Minimum Size (HMMIN)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.TNVMCAP\">\n            <summary>\n            byte 280:295 O - Total NVM Capacity (TNVMCAP)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.UNVMCAP\">\n            <summary>\n            byte 296:311 O - Unallocated NVM Capacity (UNVMCAP)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.RPMBS\">\n            <summary>\n            byte 312:315 O - Replay Protected Memory Block Support (RPMBS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.Reserved1\">\n            <summary>\n            byte 316:511\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.SQES\">\n            <summary>\n            byte 512 M - Submission Queue Entry Size (SQES)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.CQES\">\n            <summary>\n            byte 513 M - Completion Queue Entry Size (CQES)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.Reserved2\">\n            <summary>\n            byte 514:515\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.NN\">\n            <summary>\n            byte 516:519 M - Number of Namespaces (NN)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.ONCS\">\n            <summary>\n            byte 520:521 M - Optional NVM Command Support (ONCS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.FUSES\">\n            <summary>\n            byte 522:523 M - Fused Operation Support (FUSES)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.FNA\">\n            <summary>\n            byte 524 M - Format NVM Attributes (FNA)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.VWC\">\n            <summary>\n            byte 525 M - Volatile Write Cache (VWC)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.AWUN\">\n            <summary>\n            byte 526:527 M - Atomic Write Unit Normal (AWUN)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.AWUPF\">\n            <summary>\n            byte 528:529 M - Atomic Write Unit Power Fail (AWUPF)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.NVSCC\">\n            <summary>\n            byte 530 M - NVM Vendor Specific Command Configuration (NVSCC)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.Reserved3\">\n            <summary>\n            byte 531\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.ACWU\">\n            <summary>\n            byte 532:533 O - Atomic Compare and Write Unit (ACWU)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.Reserved4\">\n            <summary>\n            byte 534:535\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.SGLS\">\n            <summary>\n            byte 536:539 O - SGL Support (SGLS)\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.Reserved5\">\n            <summary>\n            byte 540:703\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.Reserved6\">\n            <summary>\n            byte 704:2047\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.PDS\">\n            <summary>\n            byte 2048:3071 Power State Descriptors\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_IDENTIFY_CONTROLLER_DATA.VS\">\n            <summary>\n            byte 3072:4095 Vendor Specific\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.CriticalWarning\">\n            <summary>\n            This field indicates critical warnings for the state of the  controller.\n            Each bit corresponds to a critical warning type; multiple bits may be set.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.CompositeTemp\">\n            <summary>\n            Composite Temperature:  Contains the temperature of the overall device (controller and NVM included) in units of Kelvin.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.AvailableSpare\">\n            <summary>\n            Available Spare:  Contains a normalized percentage (0 to 100%) of the remaining spare capacity available\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.AvailableSpareThreshold\">\n            <summary>\n            Available Spare Threshold:  When the Available Spare falls below the threshold indicated in this field,\n            an asynchronous event completion may occur. The value is indicated as a normalized percentage (0 to 100%).\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.PercentageUsed\">\n            <summary>\n            Percentage Used:  Contains a vendor specific estimate of the percentage of NVM subsystem life used based on\n            the actual usage and the manufacturer’s prediction of NVM life. A value of 100 indicates that the estimated endurance of\n            the NVM in the NVM subsystem has been consumed, but may not indicate an NVM subsystem failure. The value is allowed to exceed 100.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.DataUnitRead\">\n            <summary>\n            Data Units Read:  Contains the number of 512 byte data units the host has read from the controller;\n            this value does not include metadata. This value is reported in thousands\n            (i.e., a value of 1 corresponds to 1000 units of 512 bytes read) and is rounded up.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.DataUnitWritten\">\n            <summary>\n            Data Units Written:  Contains the number of 512 byte data units the host has written to the controller;\n            this value does not include metadata. This value is reported in thousands\n            (i.e., a value of 1 corresponds to 1000 units of 512 bytes written) and is rounded up.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.HostReadCommands\">\n            <summary>\n            Host Read Commands:  Contains the number of read commands completed by the controller.\n            For the NVM command set, this is the number of Compare and Read commands.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.HostWriteCommands\">\n            <summary>\n            Host Write Commands:  Contains the number of write commands completed by the controller.\n            For the NVM command set, this is the number of Write commands.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.ControllerBusyTime\">\n            <summary>\n            Controller Busy Time:  Contains the amount of time the controller is busy with I/O commands.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.PowerCycles\">\n            <summary>\n            Power Cycles:  Contains the number of power cycles.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.PowerOnHours\">\n            <summary>\n            Power On Hours:  Contains the number of power-on hours.\n            This does not include time that the controller was powered and in a low power state condition.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.UnsafeShutdowns\">\n            <summary>\n            Unsafe Shutdowns:  Contains the number of unsafe shutdowns.\n            This count is incremented when a shutdown notification is not received prior to loss of power.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.MediaAndDataIntegrityErrors\">\n            <summary>\n            Media Errors:  Contains the number of occurrences where the controller detected an unrecoverable data integrity error.\n            Errors such as uncorrectable ECC, CRC checksum failure, or LBA tag mismatch are included in this field.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.NumberErrorInformationLogEntries\">\n            <summary>\n            Number of Error Information Log Entries:  Contains the number of Error Information log entries over the life of the controller\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.WarningCompositeTemperatureTime\">\n            <summary>\n            Warning Composite Temperature Time:  Contains the amount of time in minutes that the controller is operational and the Composite Temperature is greater than or equal to the Warning Composite\n            Temperature Threshold.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.CriticalCompositeTemperatureTime\">\n            <summary>\n            Critical Composite Temperature Time:  Contains the amount of time in minutes that the controller is operational and the Composite Temperature is greater than the Critical Composite Temperature\n            Threshold.\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.Kernel32.NVME_HEALTH_INFO_LOG.TemperatureSensor\">\n            <summary>\n            Contains the current temperature reported by temperature sensor 1-8.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Interop.Kernel32.IOControlCode.Code\">\n            <summary>\n            Gets the resulting IO control code.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Interop.Kernel32.IOControlCode.#ctor(System.UInt32,System.UInt32,LibreHardwareMonitor.Interop.Kernel32.IOControlCode.Access)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Interop.Kernel32.IOControlCode\" /> struct.\n            </summary>\n            <param name=\"deviceType\">Type of the device.</param>\n            <param name=\"function\">The function.</param>\n            <param name=\"access\">The access.</param>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Interop.Kernel32.IOControlCode.#ctor(System.UInt32,System.UInt32,LibreHardwareMonitor.Interop.Kernel32.IOControlCode.Method,LibreHardwareMonitor.Interop.Kernel32.IOControlCode.Access)\">\n            <summary>\n            Initializes a new instance of the <see cref=\"T:LibreHardwareMonitor.Interop.Kernel32.IOControlCode\" /> struct.\n            </summary>\n            <param name=\"deviceType\">Type of the device.</param>\n            <param name=\"function\">The function.</param>\n            <param name=\"method\">The method.</param>\n            <param name=\"access\">The access.</param>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.Success\">\n            <summary>\n            The operation was successful\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.Uninitialized\">\n            <summary>\n            NvidiaML was not first initialized with nvmlInit()\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.InvalidArgument\">\n            <summary>\n            A supplied argument is invalid\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.NotSupported\">\n            <summary>\n            The requested operation is not available on target device\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.NoPermission\">\n            <summary>\n            The current user does not have permission for operation\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.NotFound\">\n            <summary>\n            A query to find an object was unsuccessful\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.InsufficientSize\">\n            <summary>\n            An input argument is not large enough\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.InsufficientPower\">\n            <summary>\n            A device's external power cables are not properly attached\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.DriverNotLoaded\">\n            <summary>\n            NVIDIA driver is not loaded\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.TimeOut\">\n            <summary>\n            User provided timeout passed\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.IRQIssue\">\n            <summary>\n            NVIDIA Kernel detected an interrupt issue with a GPU\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.LibraryNotFound\">\n            <summary>\n            NvidiaML Shared Library couldn't be found or loaded\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.FunctionNotFound\">\n            <summary>\n            Local version of NvidiaML doesn't implement this function\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.CorruptedInfoRom\">\n            <summary>\n            infoROM is corrupted\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.GpuIsLost\">\n            <summary>\n            The GPU has fallen off the bus or has otherwise become inaccessible\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.ResetRequired\">\n            <summary>\n            The GPU requires a reset before it can be used again\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.OperatingSystem\">\n            <summary>\n            The GPU control device has been blocked by the operating system/cgroups\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.LibRmVersionMismatch\">\n            <summary>\n            RM detects a driver/library version mismatch\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.InUse\">\n            <summary>\n            An operation cannot be performed because the GPU is currently in use\n            </summary>\n        </member>\n        <member name=\"F:LibreHardwareMonitor.Interop.NvidiaML.NvmlReturn.Unknown\">\n            <summary>\n            An public driver error occurred\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Interop.Ring0\">\n            <summary>\n            Driver with access at kernel level.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Interop.WinNt\">\n            <summary>\n            Contains Win32 definitions for Windows NT.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Interop.WinNt.LUID\">\n            <summary>\n            Describes a local identifier for an adapter.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Interop.WinNt.LARGE_INTEGER\">\n            <summary>\n            Represents a 64-bit signed integer value.\n            </summary>\n        </member>\n        <member name=\"T:LibreHardwareMonitor.Software.OperatingSystem\">\n            <summary>\n            Contains basic information about the operating system.\n            </summary>\n        </member>\n        <member name=\"M:LibreHardwareMonitor.Software.OperatingSystem.#cctor\">\n            <summary>\n            Statically checks if the current system <see cref=\"P:LibreHardwareMonitor.Software.OperatingSystem.Is64Bit\"/> and <see cref=\"P:LibreHardwareMonitor.Software.OperatingSystem.IsUnix\"/>.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Software.OperatingSystem.Is64Bit\">\n            <summary>\n            Gets information about whether the current system is 64 bit.\n            </summary>\n        </member>\n        <member name=\"P:LibreHardwareMonitor.Software.OperatingSystem.IsUnix\">\n            <summary>\n            Gets information about whether the current system is Unix based.\n            </summary>\n        </member>\n    </members>\n</doc>\n"
  },
  {
    "path": "OpenHardwareMonitorApi/OpenHardwareMonitorApi.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|ARM64EC\">\n      <Configuration>Debug</Configuration>\n      <Platform>ARM64EC</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|ARM64EC\">\n      <Configuration>Release</Configuration>\n      <Platform>ARM64EC</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}</ProjectGuid>\n    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>\n    <Keyword>ManagedCProj</Keyword>\n    <RootNamespace>OpenHardwareMonitorApi</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CLRSupport>true</CLRSupport>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CLRSupport>true</CLRSupport>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CLRSupport>true</CLRSupport>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CLRSupport>true</CLRSupport>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CLRSupport>true</CLRSupport>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CLRSupport>true</CLRSupport>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions);OPENHARDWAREMONITOR_EXPORTS</PreprocessorDefinitions>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies />\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions);OPENHARDWAREMONITOR_EXPORTS</PreprocessorDefinitions>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies />\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions);OPENHARDWAREMONITOR_EXPORTS</PreprocessorDefinitions>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>\n      </AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions);OPENHARDWAREMONITOR_EXPORTS</PreprocessorDefinitions>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies />\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions);OPENHARDWAREMONITOR_EXPORTS</PreprocessorDefinitions>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies />\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions);OPENHARDWAREMONITOR_EXPORTS</PreprocessorDefinitions>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>\n      </AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <Reference Include=\"LibreHardwareMonitorLib\">\n      <HintPath>LibreHardwareMonitorLib.dll</HintPath>\n    </Reference>\n    <Reference Include=\"System\" />\n    <Reference Include=\"System.Data\" />\n    <Reference Include=\"System.Xml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\include\\OpenHardwareMonitor\\OpenHardwareMonitorApi.h\" />\n    <ClInclude Include=\"..\\include\\OpenHardwareMonitor\\OpenHardwareMonitorGlobal.h\" />\n    <ClInclude Include=\"OpenHardwareMonitorImp.h\" />\n    <ClInclude Include=\"resource.h\" />\n    <ClInclude Include=\"Stdafx.h\" />\n    <ClInclude Include=\"UpdateVisitor.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"OpenHardwareMonitorImp.cpp\" />\n    <ClCompile Include=\"Stdafx.cpp\">\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">Create</PrecompiledHeader>\n    </ClCompile>\n    <ClCompile Include=\"UpdateVisitor.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Text Include=\"ReadMe.txt\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"app.rc\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "OpenHardwareMonitorApi/OpenHardwareMonitorApi.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"源文件\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"头文件\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"资源文件\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"Stdafx.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"resource.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"OpenHardwareMonitorImp.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\include\\OpenHardwareMonitor\\OpenHardwareMonitorApi.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"UpdateVisitor.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\include\\OpenHardwareMonitor\\OpenHardwareMonitorGlobal.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"Stdafx.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"OpenHardwareMonitorImp.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"UpdateVisitor.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <Text Include=\"ReadMe.txt\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"app.rc\">\n      <Filter>资源文件</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "OpenHardwareMonitorApi/OpenHardwareMonitorImp.cpp",
    "content": "﻿// 这是主 DLL 文件。\n\n#include \"stdafx.h\"\n\n#include \"OpenHardwareMonitorImp.h\"\n#include <vector>\n\nnamespace OpenHardwareMonitorApi\n{\n    static std::wstring error_message;\n\n    //将CRL的String类型转换成C++的std::wstring类型\n    static std::wstring ClrStringToStdWstring(System::String^ str)\n    {\n        if (str == nullptr)\n        {\n            return std::wstring();\n        }\n        else\n        {\n            const wchar_t* chars = (const wchar_t*)(Runtime::InteropServices::Marshal::StringToHGlobalUni(str)).ToPointer();\n            std::wstring os = chars;\n            Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr((void*)chars));\n            return os;\n        }\n    }\n\n\n    std::shared_ptr<IOpenHardwareMonitor> CreateInstance()\n    {\n        std::shared_ptr<IOpenHardwareMonitor> pMonitor;\n        try\n        {\n            MonitorGlobal::Instance()->Init();\n            pMonitor = std::make_shared<COpenHardwareMonitor>();\n        }\n        catch (System::Exception^ e)\n        {\n            error_message = ClrStringToStdWstring(e->Message);\n        }\n        return pMonitor;\n    }\n\n    std::wstring GetErrorMessage()\n    {\n        return error_message;\n    }\n\n    float COpenHardwareMonitor::CpuTemperature()\n    {\n        return m_cpu_temperature;\n    }\n\n    float COpenHardwareMonitor::GpuTemperature()\n    {\n        if (m_gpu_nvidia_temperature >= 0)\n            return m_gpu_nvidia_temperature;\n        else if (m_gpu_ati_temperature >= 0)\n            return m_gpu_ati_temperature;\n        else\n            return m_gpu_intel_temperature;\n    }\n\n    float COpenHardwareMonitor::HDDTemperature()\n    {\n        return m_hdd_temperature;\n    }\n\n    float COpenHardwareMonitor::MainboardTemperature()\n    {\n        return m_main_board_temperature;\n    }\n\n    float COpenHardwareMonitor::GpuUsage()\n    {\n        if (m_gpu_nvidia_usage >= 0)\n            return m_gpu_nvidia_usage;\n        else if (m_gpu_ati_usage >= 0)\n            return m_gpu_ati_usage;\n        else\n            return m_gpu_intel_usage;\n    }\n\n    float COpenHardwareMonitor::CpuFreq()\n    {\n            return m_cpu_freq;\n    }\n\n    float COpenHardwareMonitor::CpuUsage()\n    {\n        return m_cpu_usage;\n    }\n\n    const std::map<std::wstring, float>& COpenHardwareMonitor::AllHDDTemperature()\n    {\n        return m_all_hdd_temperature;\n    }\n\n    const std::map<std::wstring, float>& COpenHardwareMonitor::AllCpuTemperature()\n    {\n        return m_all_cpu_temperature;\n    }\n\n    const std::map<std::wstring, float>& COpenHardwareMonitor::AllHDDUsage()\n    {\n        return m_all_hdd_usage;\n    }\n\n    void COpenHardwareMonitor::SetCpuEnable(bool enable)\n    {\n        MonitorGlobal::Instance()->computer->IsCpuEnabled = enable;\n    }\n\n    void COpenHardwareMonitor::SetGpuEnable(bool enable)\n    {\n        MonitorGlobal::Instance()->computer->IsGpuEnabled = enable;\n    }\n\n    void COpenHardwareMonitor::SetHddEnable(bool enable)\n    {\n        MonitorGlobal::Instance()->computer->IsStorageEnabled = enable;\n    }\n\n    void COpenHardwareMonitor::SetMainboardEnable(bool enable)\n    {\n        MonitorGlobal::Instance()->computer->IsMotherboardEnabled = enable;\n    }\n\n    bool COpenHardwareMonitor::GetCPUFreq(IHardware^ hardware, float& freq) {\n        for (int i = 0; i < hardware->Sensors->Length; i++)\n        {\n            if (hardware->Sensors[i]->SensorType == SensorType::Clock)\n            {\n                String^ name = hardware->Sensors[i]->Name;\n                if (name != L\"Bus Speed\")\n                    m_all_cpu_clock[ClrStringToStdWstring(name)] = Convert::ToDouble(hardware->Sensors[i]->Value);\n            }\n        }\n        float sum{};\n        for (auto i : m_all_cpu_clock)\n            sum += i.second;\n        freq = sum / m_all_cpu_clock.size() / 1000.0;\n        return true;\n    }\n\n    bool COpenHardwareMonitor::GetCpuUsage(IHardware^ hardware, float& cpu_usage)\n    {\n        for (int i = 0; i < hardware->Sensors->Length; i++)\n        {\n            if (hardware->Sensors[i]->SensorType == SensorType::Load)\n            {\n                String^ name = hardware->Sensors[i]->Name;\n                if (name != L\"CPU Total\")\n                {\n                    cpu_usage = Convert::ToDouble(hardware->Sensors[i]->Value);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    bool COpenHardwareMonitor::GetHardwareTemperature(IHardware^ hardware, float& temperature)\n    {\n        temperature = -1;\n        std::vector<float> all_temperature;\n        float core_temperature{ -1 };\n        System::String^ temperature_name;\n        switch (hardware->HardwareType)\n        {\n        case HardwareType::Cpu:\n            temperature_name = L\"Core Average\";\n            break;\n        case HardwareType::GpuNvidia: case HardwareType::GpuAmd: case HardwareType::GpuIntel:\n            temperature_name = L\"GPU Core\";\n            break;\n        default:\n            break;\n        }\n        for (int i = 0; i < hardware->Sensors->Length; i++)\n        {\n            //找到温度传感器\n            if (hardware->Sensors[i]->SensorType == SensorType::Temperature)\n            {\n                float cur_temperture = Convert::ToDouble(hardware->Sensors[i]->Value);\n                all_temperature.push_back(cur_temperture);\n                if (hardware->Sensors[i]->Name == temperature_name) //如果找到了名称为temperature_name的温度传感器，则将温度保存到core_temperature里\n                    core_temperature = cur_temperture;\n            }\n        }\n        if (core_temperature >= 0)\n        {\n            temperature = core_temperature;\n            return true;\n        }\n        if (!all_temperature.empty())\n        {\n            //如果有多个温度传感器，则取平均值\n            float sum{};\n            for (auto i : all_temperature)\n                sum += i;\n            temperature = sum / all_temperature.size();\n            return true;\n        }\n        //如果没有找到温度传感器，则在SubHardware中寻找\n        for (int i = 0; i < hardware->SubHardware->Length; i++)\n        {\n            if (GetHardwareTemperature(hardware->SubHardware[i], temperature))\n                return true;\n        }\n        return false;\n    }\n\n    bool COpenHardwareMonitor::GetCpuTemperature(IHardware^ hardware, float& temperature)\n    {\n        temperature = -1;\n        m_all_cpu_temperature.clear();\n        for (int i = 0; i < hardware->Sensors->Length; i++)\n        {\n            //找到温度传感器\n            if (hardware->Sensors[i]->SensorType == SensorType::Temperature)\n            {\n                String^ name = hardware->Sensors[i]->Name;\n                //保存每个CPU传感器的温度\n                m_all_cpu_temperature[ClrStringToStdWstring(name)] = Convert::ToDouble(hardware->Sensors[i]->Value);\n            }\n        }\n        //计算平均温度\n        if (!m_all_cpu_temperature.empty())\n        {\n            float sum{};\n            for (const auto& item : m_all_cpu_temperature)\n                sum += item.second;\n            temperature = sum / m_all_cpu_temperature.size();\n        }\n        return temperature > 0;\n    }\n\n    bool COpenHardwareMonitor::GetGpuUsage(IHardware^ hardware, float& gpu_usage)\n    {\n        float usage_max = 0;\n        for (int i = 0; i < hardware->Sensors->Length; i++)\n        {\n            //找到负载\n            if (hardware->Sensors[i]->SensorType == SensorType::Load)\n            {\n                float cur_gpu_usage = Convert::ToDouble(hardware->Sensors[i]->Value);\n                if (hardware->Sensors[i]->Name == L\"GPU Core\")\n                {\n                    gpu_usage = cur_gpu_usage;\n                    return true;\n                }\n\n                //计算最大值\n                if (cur_gpu_usage > usage_max)\n                    usage_max = cur_gpu_usage;\n            }\n        }\n        gpu_usage = usage_max;\n        return true;\n    }\n\n    bool COpenHardwareMonitor::GetHddUsage(IHardware^ hardware, float& hdd_usage)\n    {\n        for (int i = 0; i < hardware->Sensors->Length; i++)\n        {\n            //找到负载\n            if (hardware->Sensors[i]->SensorType == SensorType::Load)\n            {\n                if (hardware->Sensors[i]->Name == L\"Total Activity\")\n                {\n                    hdd_usage = Convert::ToDouble(hardware->Sensors[i]->Value);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    COpenHardwareMonitor::COpenHardwareMonitor()\n    {\n        ResetAllValues();\n    }\n\n    COpenHardwareMonitor::~COpenHardwareMonitor()\n    {\n        MonitorGlobal::Instance()->UnInit();\n    }\n\n    void COpenHardwareMonitor::ResetAllValues()\n    {\n        m_cpu_temperature = -1;\n        m_gpu_nvidia_temperature = -1;\n        m_gpu_ati_temperature = -1;\n        m_gpu_intel_temperature = -1;\n        m_hdd_temperature = -1;\n        m_main_board_temperature = -1;\n        m_gpu_nvidia_usage = -1;\n        m_gpu_ati_usage = -1;\n        m_gpu_intel_usage = -1;\n        m_all_hdd_temperature.clear();\n        m_all_hdd_usage.clear();\n        m_cpu_freq = -1;\n        m_cpu_usage = -1;\n    }\n\n    void COpenHardwareMonitor::InsertValueToMap(std::map<std::wstring, float>& value_map, const std::wstring& key, float value)\n    {\n        auto iter = value_map.find(key);\n        if (iter == value_map.end())\n        {\n            value_map[key] = value;\n        }\n        else\n        {\n            std::wstring key_exist = iter->first;\n            size_t index = key_exist.rfind(L'#');   //查找字符串是否含有#号\n            if (index != std::wstring::npos)\n            {\n                //取到#号后面的数字，将其加1\n                int num = _wtoi(key_exist.substr(index + 1).c_str());\n                num++;\n                key_exist = key_exist.substr(0, index + 1);\n                key_exist += std::to_wstring(num);\n            }\n            else //没有#号则在末尾添加\" #1\"\n            {\n                key_exist += L\" #1\";\n            }\n            value_map[key_exist] = value;\n        }\n    }\n\n    void COpenHardwareMonitor::GetHardwareInfo()\n    {\n        ResetAllValues();\n        error_message.clear();\n        try\n        {\n            auto computer = MonitorGlobal::Instance()->computer;\n            computer->Accept(MonitorGlobal::Instance()->updateVisitor);\n            for (int i = 0; i < computer->Hardware->Count; i++)\n            {\n                //查找硬件类型\n                switch (computer->Hardware[i]->HardwareType)\n                {\n                case HardwareType::Cpu:\n                    if (m_cpu_temperature < 0)\n                        GetCpuTemperature(computer->Hardware[i], m_cpu_temperature);\n                    if (m_cpu_freq < 0)\n                        GetCPUFreq(computer->Hardware[i], m_cpu_freq);\n                    if (m_cpu_usage < 0)\n                        GetCpuUsage(computer->Hardware[i], m_cpu_usage);\n                    break;\n                case HardwareType::GpuNvidia:\n                    if (m_gpu_nvidia_temperature < 0)\n                        GetHardwareTemperature(computer->Hardware[i], m_gpu_nvidia_temperature);\n                    if (m_gpu_nvidia_usage < 0)\n                        GetGpuUsage(computer->Hardware[i], m_gpu_nvidia_usage);\n                    break;\n                case HardwareType::GpuAmd:\n                    if (m_gpu_ati_temperature < 0)\n                        GetHardwareTemperature(computer->Hardware[i], m_gpu_ati_temperature);\n                    if (m_gpu_ati_usage < 0)\n                        GetGpuUsage(computer->Hardware[i], m_gpu_ati_usage);\n                    break;\n                case HardwareType::GpuIntel:\n                    if (m_gpu_intel_temperature < 0)\n                        GetHardwareTemperature(computer->Hardware[i], m_gpu_intel_temperature);\n                    if (m_gpu_intel_usage < 0)\n                        GetGpuUsage(computer->Hardware[i], m_gpu_intel_usage);\n                    break;\n                case HardwareType::Storage:\n                {\n                    float cur_hdd_temperature = -1;\n                    GetHardwareTemperature(computer->Hardware[i], cur_hdd_temperature);\n                    //m_all_hdd_temperature[ClrStringToStdWstring(computer->Hardware[i]->Name)] = cur_hdd_temperature;\n                    InsertValueToMap(m_all_hdd_temperature, ClrStringToStdWstring(computer->Hardware[i]->Name), cur_hdd_temperature);\n                    float cur_hdd_usage = -1;\n                    GetHddUsage(computer->Hardware[i], cur_hdd_usage);\n                    //m_all_hdd_usage[ClrStringToStdWstring(computer->Hardware[i]->Name)] = cur_hdd_usage;\n                    InsertValueToMap(m_all_hdd_usage, ClrStringToStdWstring(computer->Hardware[i]->Name), cur_hdd_usage);\n                    if (m_hdd_temperature < 0)\n                        m_hdd_temperature = cur_hdd_temperature;\n                }\n                break;\n                case HardwareType::Motherboard:\n                    if (m_main_board_temperature < 0)\n                        GetHardwareTemperature(computer->Hardware[i], m_main_board_temperature);\n                    break;\n                default:\n                    break;\n                }\n            }\n        }\n        catch (System::Exception^ e)\n        {\n            error_message = ClrStringToStdWstring(e->Message);\n        }\n    }\n\n    ////////////////////////////////////////////////////////////////////////////////////\n    MonitorGlobal::MonitorGlobal()\n    {\n\n    }\n\n    MonitorGlobal::~MonitorGlobal()\n    {\n\n    }\n\n    void MonitorGlobal::Init()\n    {\n        updateVisitor = gcnew UpdateVisitor();\n        computer = gcnew Computer();\n        computer->Open();\n    }\n\n    void MonitorGlobal::UnInit()\n    {\n        computer->Close();\n    }\n\n}\n"
  },
  {
    "path": "OpenHardwareMonitorApi/OpenHardwareMonitorImp.h",
    "content": "﻿// OpenHardwareMonitorApi.h\n\n#pragma once\n#include <string>\n#include \"OpenHardwareMonitor/OpenHardwareMonitorApi.h\"\n#include \"UpdateVisitor.h\"\n#include <map>\n\nusing namespace System;\nusing namespace LibreHardwareMonitor::Hardware;\n\nnamespace OpenHardwareMonitorApi {\n\n    public class COpenHardwareMonitor : public IOpenHardwareMonitor\n\t{\n    public:\n        COpenHardwareMonitor();\n        virtual ~COpenHardwareMonitor();\n\n        virtual void GetHardwareInfo() override;\n        virtual float CpuTemperature() override;\n        virtual float GpuTemperature() override;\n        virtual float HDDTemperature() override;\n        virtual float MainboardTemperature() override;\n        virtual float GpuUsage() override;\n        virtual float CpuFreq() override;\n        virtual float CpuUsage() override;\n        virtual const std::map<std::wstring, float>& AllHDDTemperature() override;\n        virtual const std::map<std::wstring, float>& AllCpuTemperature() override;\n        virtual const std::map<std::wstring, float>& AllHDDUsage() override;\n\n        virtual void SetCpuEnable(bool enable) override;\n        virtual void SetGpuEnable(bool enable) override;\n        virtual void SetHddEnable(bool enable) override;\n        virtual void SetMainboardEnable(bool enable) override;\n\n    private:\n        bool GetHardwareTemperature(IHardware^ hardware, float& temperature);\n        bool GetCpuTemperature(IHardware^ hardware, float& temperature);\n        bool GetGpuUsage(IHardware^ hardware, float& gpu_usage);\n        bool GetHddUsage(IHardware^ hardware, float& hdd_usage);\n        bool GetCPUFreq(IHardware^ hardware, float& freq);\n        bool GetCpuUsage(IHardware^ hardware, float& cpu_usage);\n        void ResetAllValues();\n        //向map中插入一个数值，如果key已经存在，则自动对新插入的key重命名\n        static void InsertValueToMap(std::map<std::wstring, float>& value_map, const std::wstring& key, float value);\n\n    private:\n        float m_cpu_temperature{};\n        float m_gpu_nvidia_temperature{};\n        float m_gpu_ati_temperature{};\n        float m_gpu_intel_temperature{};\n        float m_hdd_temperature{};\n        float m_main_board_temperature{};\n        float m_gpu_nvidia_usage{};\n        float m_gpu_ati_usage{};\n        float m_gpu_intel_usage{};\n        float m_cpu_freq{};\n        float m_cpu_usage{};\n        std::map<std::wstring, float> m_all_hdd_temperature;\n        std::map<std::wstring, float> m_all_cpu_temperature;\n        std::map<std::wstring, float> m_all_cpu_clock;\n        std::map<std::wstring, float> m_all_hdd_usage;\n    };\n\n    //一个单实例类\n    //由于COpenHardwareMonitor是非托管类，不能将托管类的对象作为成员变量，此类用于保存托管类的对象\n    public ref class MonitorGlobal\n    {\n    public:\n        MonitorGlobal();\n        ~MonitorGlobal();\n        static MonitorGlobal^ Instance()\n        {\n            if (m_instance == nullptr)\n            {\n                m_instance = gcnew MonitorGlobal();\n            }\n            return m_instance;\n        }\n\n        void Init();\n        void UnInit();\n\n        Computer^ computer;\n        UpdateVisitor^ updateVisitor{};\n\n    private:\n        static MonitorGlobal^ m_instance{};\n    };\n}\n"
  },
  {
    "path": "OpenHardwareMonitorApi/ReadMe.txt",
    "content": "========================================================================\n    DYNAMIC LINK LIBRARY : OpenHardwareMonitorApi Project Overview\n========================================================================\n\nAppWizard has created this OpenHardwareMonitorApi DLL for you.  \n\nThis file contains a summary of what you will find in each of the files that\nmake up your OpenHardwareMonitorApi application.\n\nOpenHardwareMonitorApi.vcxproj\n    This is the main project file for VC++ projects generated using an Application Wizard. \n    It contains information about the version of Visual C++ that generated the file, and \n    information about the platforms, configurations, and project features selected with the\n    Application Wizard.\n\nOpenHardwareMonitorApi.vcxproj.filters\n    This is the filters file for VC++ projects generated using an Application Wizard. \n    It contains information about the association between the files in your project \n    and the filters. This association is used in the IDE to show grouping of files with\n    similar extensions under a specific node (for e.g. \".cpp\" files are associated with the\n    \"Source Files\" filter).\n\nOpenHardwareMonitorApi.cpp\n    This is the main DLL source file.\n\nOpenHardwareMonitorApi.h\n    This file contains a class declaration.\n\nAssemblyInfo.cpp\n\tContains custom attributes for modifying assembly metadata.\n\n/////////////////////////////////////////////////////////////////////////////\nOther notes:\n\nAppWizard uses \"TODO:\" to indicate parts of the source code you\nshould add to or customize.\n\n/////////////////////////////////////////////////////////////////////////////\n"
  },
  {
    "path": "OpenHardwareMonitorApi/Stdafx.cpp",
    "content": "// stdafx.cpp : ֻ׼ļԴļ\n// OpenHardwareMonitorApi.pch ΪԤͷ\n// stdafx.obj ԤϢ\n\n#include \"stdafx.h\"\n"
  },
  {
    "path": "OpenHardwareMonitorApi/Stdafx.h",
    "content": "// stdafx.h : ׼ϵͳļİļ\n// Ǿʹõĵ\n// ضĿİļ\n\n#pragma once\n\n\n"
  },
  {
    "path": "OpenHardwareMonitorApi/UpdateVisitor.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"UpdateVisitor.h\"\n\nnamespace OpenHardwareMonitorApi\n{\n    void UpdateVisitor::VisitComputer(IComputer ^ computer)\n    {\n        computer->Traverse(this);\n    }\n\n    void UpdateVisitor::VisitHardware(IHardware ^ hardware)\n    {\n        hardware->Update();\n        for each (IHardware^ subHardware in hardware->SubHardware)\n        {\n            subHardware->Accept(this);\n        }\n    }\n\n    void UpdateVisitor::VisitSensor(ISensor ^ sensor)\n    {\n    }\n\n    void UpdateVisitor::VisitParameter(IParameter ^ parameter)\n    {\n    }\n\n}\n"
  },
  {
    "path": "OpenHardwareMonitorApi/UpdateVisitor.h",
    "content": "﻿#pragma once\n\nusing namespace LibreHardwareMonitor::Hardware;\n\nnamespace OpenHardwareMonitorApi\n{\n    public ref class UpdateVisitor : IVisitor\n    {\n    public:\n        virtual void VisitComputer(IComputer^ computer);\n        virtual void VisitHardware(IHardware^ hardware);\n        virtual void VisitSensor(ISensor^ sensor);\n        virtual void VisitParameter(IParameter^ parameter);\n    };\n\n}\n"
  },
  {
    "path": "OpenHardwareMonitorApi/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by app.rc\n"
  },
  {
    "path": "PluginDemo/CustomDrawItem.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"CustomDrawItem.h\"\n#include \"DataManager.h\"\n\nconst wchar_t* CCustomDrawItem::GetItemName() const\n{\n    return CDataManager::Instance().StringRes(IDS_CUSTOM_DRAW_ITEM);\n}\n\nconst wchar_t* CCustomDrawItem::GetItemId() const\n{\n    return L\"4Tc21hGS\";\n}\n\nconst wchar_t* CCustomDrawItem::GetItemLableText() const\n{\n    return L\"\";\n}\n\nconst wchar_t* CCustomDrawItem::GetItemValueText() const\n{\n    return L\"\";\n}\n\nconst wchar_t* CCustomDrawItem::GetItemValueSampleText() const\n{\n    return L\"\";\n}\n\nbool CCustomDrawItem::IsCustomDraw() const\n{\n    return true;\n}\n\nint CCustomDrawItem::GetItemWidth() const\n{\n    return 50;\n}\n\nstatic void DrawLine(CDC* pDC, CPoint point1, CPoint point2, COLORREF color)\n{\n    CPen aPen, * pOldPen;\n    aPen.CreatePen(PS_SOLID, 1, color);\n    pOldPen = pDC->SelectObject(&aPen);\n    pDC->MoveTo(point1);\n    pDC->LineTo(point2);\n    pDC->SelectObject(pOldPen);\n}\n\nvoid CCustomDrawItem::DrawItem(void* hDC, int x, int y, int w, int h, bool dark_mode)\n{\n    //绘图句柄\n    CDC* pDC = CDC::FromHandle((HDC)hDC);\n    //矩形区域\n    CRect rect(CPoint(x, y), CSize(w, h));\n    //设置颜色\n    COLORREF color1{ dark_mode ? RGB(255, 143, 107) : RGB(227, 81, 16) };\n    COLORREF color2{ dark_mode ? RGB(183, 241, 96) : RGB(83, 131, 11) };\n    COLORREF color3{ dark_mode ? RGB(158, 218, 251) : RGB(6, 111, 168) };\n    //显示时、分、秒的矩形区域\n    CRect rect1{ rect }, rect2{ rect }, rect3{ rect };\n    rect1.bottom = rect.top + rect.Height() / 3;\n    rect2 = rect1;\n    rect2.MoveToY(rect1.bottom);\n    rect3.top = rect2.bottom;\n    rect1.DeflateRect(1, 1);\n    rect2.DeflateRect(1, 1);\n    rect3.DeflateRect(1, 1);\n    //根据当前时间计算矩形的宽度\n    SYSTEMTIME& time{ CDataManager::Instance().m_system_time };\n    int hour_width{ static_cast<int>((time.wHour + time.wMinute / 60.0) * w / 24) };\n    int min_width{ static_cast<int>((time.wMinute + time.wSecond / 60.0) * w / 60) };\n    int sec_width{ time.wSecond * w / 60 };\n    rect1.right = rect1.left + hour_width;\n    rect2.right = rect2.left + min_width;\n    rect3.right = rect3.left + sec_width;\n    //填充矩形\n    pDC->FillSolidRect(rect1, color1);\n    pDC->FillSolidRect(rect2, color2);\n    pDC->FillSolidRect(rect3, color3);\n    //绘制刻度\n    COLORREF color_scale{ dark_mode ? RGB(225, 225, 225) : RGB(45, 45, 45) };\n    for (int i{}; i < 24; i++)\n    {\n        int x_pos{ i * w / 24 + rect1.left };\n        DrawLine(pDC, CPoint(x_pos, rect1.top), CPoint(x_pos, i % 6 == 0 ? rect1.bottom : rect1.top + rect1.Height() / 2), color_scale);\n    }\n}\n"
  },
  {
    "path": "PluginDemo/CustomDrawItem.h",
    "content": "﻿#pragma once\n#include \"PluginInterface.h\"\n\nclass CCustomDrawItem : public IPluginItem\n{\n    // 通过 IPluginItem 继承\n    virtual const wchar_t* GetItemName() const override;\n    virtual const wchar_t* GetItemId() const override;\n    virtual const wchar_t* GetItemLableText() const override;\n    virtual const wchar_t* GetItemValueText() const override;\n    virtual const wchar_t* GetItemValueSampleText() const override;\n    virtual bool IsCustomDraw() const override;\n    virtual int GetItemWidth() const override;\n    virtual void DrawItem(void* hDC, int x, int y, int w, int h, bool dark_mode) override;\n};\n"
  },
  {
    "path": "PluginDemo/DataManager.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"DataManager.h\"\n\nCDataManager CDataManager::m_instance;\n\nCDataManager::CDataManager()\n{\n}\n\nCDataManager::~CDataManager()\n{\n    SaveConfig();\n}\n\nCDataManager& CDataManager::Instance()\n{\n    return m_instance;\n}\n\nvoid CDataManager::LoadConfig(const std::wstring& config_dir)\n{\n    //获取模块的路径\n    HMODULE hModule = reinterpret_cast<HMODULE>(&__ImageBase);\n    wchar_t path[MAX_PATH];\n    GetModuleFileNameW(hModule, path, MAX_PATH);\n    std::wstring module_path = path;\n    m_config_path = module_path;\n    if (!config_dir.empty())\n    {\n        size_t index = module_path.find_last_of(L\"\\\\/\");\n        //模块的文件名\n        std::wstring module_file_name = module_path.substr(index + 1);\n        m_config_path = config_dir + module_file_name;\n    }\n    m_config_path += L\".ini\";\n    m_setting_data.show_second = GetPrivateProfileInt(_T(\"config\"), _T(\"show_second\"), 0, m_config_path.c_str());\n    //m_setting_data.show_label_text = GetPrivateProfileInt(_T(\"config\"), _T(\"show_label_text\"), 1, config_path.c_str());\n}\n\nstatic void WritePrivateProfileInt(const wchar_t* app_name, const wchar_t* key_name, int value, const wchar_t* file_path)\n{\n    wchar_t buff[16];\n    swprintf_s(buff, L\"%d\", value);\n    WritePrivateProfileString(app_name, key_name, buff, file_path);\n}\n\nvoid CDataManager::SaveConfig() const\n{\n    WritePrivateProfileInt(_T(\"config\"), _T(\"show_second\"), m_setting_data.show_second, m_config_path.c_str());\n    //WritePrivateProfileInt(_T(\"config\"), _T(\"show_label_text\"), m_setting_data.show_label_text, config_path.c_str());\n}\n\nconst CString& CDataManager::StringRes(UINT id)\n{\n    auto iter = m_string_table.find(id);\n    if (iter != m_string_table.end())\n    {\n        return iter->second;\n    }\n    else\n    {\n        AFX_MANAGE_STATE(AfxGetStaticModuleState());\n        m_string_table[id].LoadString(id);\n        return m_string_table[id];\n    }\n}\n"
  },
  {
    "path": "PluginDemo/DataManager.h",
    "content": "﻿#pragma once\n#include <string>\n#include <map>\n\n#define g_data CDataManager::Instance()\n\nstruct SettingData\n{\n    bool show_second{};\n    //bool show_label_text{};\n};\n\nclass CDataManager\n{\nprivate:\n    CDataManager();\n    ~CDataManager();\n\npublic:\n    static CDataManager& Instance();\n\n    void LoadConfig(const std::wstring& config_dir);\n    void SaveConfig() const;\n    const CString& StringRes(UINT id);      //根据资源id获取一个字符串资源\n\npublic:\n    std::wstring m_cur_time;\n    std::wstring m_cur_date;\n    SYSTEMTIME m_system_time;\n    SettingData m_setting_data;\n\nprivate:\n    static CDataManager m_instance;\n    std::wstring m_config_path;\n    std::map<UINT, CString> m_string_table;\n};\n"
  },
  {
    "path": "PluginDemo/OptionsDlg.cpp",
    "content": "﻿// OptionsDlg.cpp: 实现文件\n//\n\n#include \"pch.h\"\n#include \"PluginDemo.h\"\n#include \"OptionsDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// COptionsDlg 对话框\n\nIMPLEMENT_DYNAMIC(COptionsDlg, CDialog)\n\nCOptionsDlg::COptionsDlg(CWnd* pParent /*=nullptr*/)\n\t: CDialog(IDD_OPTIONS_DIALOG, pParent)\n{\n\n}\n\nCOptionsDlg::~COptionsDlg()\n{\n}\n\nvoid COptionsDlg::DoDataExchange(CDataExchange* pDX)\n{\n\tCDialog::DoDataExchange(pDX);\n}\n\n\nBEGIN_MESSAGE_MAP(COptionsDlg, CDialog)\n    ON_BN_CLICKED(IDC_SHOW_SECOND_CHECK, &COptionsDlg::OnBnClickedShowSecondCheck)\nEND_MESSAGE_MAP()\n\n\n// COptionsDlg 消息处理程序\n\n\nBOOL COptionsDlg::OnInitDialog()\n{\n    CDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    //初始化控件状态\n    CheckDlgButton(IDC_SHOW_SECOND_CHECK, m_data.show_second);\n    //CheckDlgButton(IDC_SHOW_LABEL_CHECK, m_data.show_label_text);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid COptionsDlg::OnBnClickedShowSecondCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.show_second = (IsDlgButtonChecked(IDC_SHOW_SECOND_CHECK) != 0);\n}\n"
  },
  {
    "path": "PluginDemo/OptionsDlg.h",
    "content": "﻿#pragma once\n#include \"DataManager.h\"\n\n// COptionsDlg 对话框\n\nclass COptionsDlg : public CDialog\n{\n\tDECLARE_DYNAMIC(COptionsDlg)\n\npublic:\n\tCOptionsDlg(CWnd* pParent = nullptr);   // 标准构造函数\n\tvirtual ~COptionsDlg();\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_OPTIONS_DIALOG };\n#endif\n\n    SettingData m_data;\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n\tDECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    afx_msg void OnBnClickedShowSecondCheck();\n};\n"
  },
  {
    "path": "PluginDemo/PluginDemo.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"PluginDemo.h\"\n#include \"DataManager.h\"\n#include \"OptionsDlg.h\"\n\nCPluginDemo CPluginDemo::m_instance;\n\nCPluginDemo::CPluginDemo()\n{\n}\n\nCPluginDemo& CPluginDemo::Instance()\n{\n    return m_instance;\n}\n\nIPluginItem* CPluginDemo::GetItem(int index)\n{\n    switch (index)\n    {\n    case 0:\n        return &m_system_date;\n    case 1:\n        return &m_system_time;\n    case 2:\n        return &m_custom_draw_item;\n    default:\n        break;\n    }\n    return nullptr;\n}\n\nvoid CPluginDemo::DataRequired()\n{\n    //获取时间和日期\n    SYSTEMTIME& system_time{ CDataManager::Instance().m_system_time };\n    GetLocalTime(&system_time);\n    wchar_t buff[128];\n    swprintf_s(buff, L\"%d/%.2d/%.2d\", system_time.wYear, system_time.wMonth, system_time.wDay);\n    CDataManager::Instance().m_cur_date = buff;\n\n    if (CDataManager::Instance().m_setting_data.show_second)\n        swprintf_s(buff, L\"%.2d:%.2d:%.2d\", system_time.wHour, system_time.wMinute, system_time.wSecond);\n    else\n        swprintf_s(buff, L\"%.2d:%.2d\", system_time.wHour, system_time.wMinute);\n    CDataManager::Instance().m_cur_time = buff;\n}\n\nconst wchar_t* CPluginDemo::GetInfo(PluginInfoIndex index)\n{\n    AFX_MANAGE_STATE(AfxGetStaticModuleState());\n    static CString str;\n    switch (index)\n    {\n    case TMI_NAME:\n        str.LoadString(IDS_PLUGIN_NAME);\n        return str.GetString();\n    case TMI_DESCRIPTION:\n        str.LoadString(IDS_PLUGIN_DESCRIPTION);\n        return str.GetString();\n    case TMI_AUTHOR:\n        return L\"zhongyang219\";\n    case TMI_COPYRIGHT:\n        return L\"Copyright (C) by Zhong Yang 2021\";\n    case TMI_VERSION:\n        return L\"1.0\";\n    case ITMPlugin::TMI_URL:\n        return L\"https://github.com/zhongyang219/TrafficMonitor\";\n        break;\n    default:\n        break;\n    }\n    return L\"\";\n}\n\nITMPlugin::OptionReturn CPluginDemo::ShowOptionsDialog(void* hParent)\n{\n    AFX_MANAGE_STATE(AfxGetStaticModuleState());\n    COptionsDlg dlg(CWnd::FromHandle((HWND)hParent));\n    dlg.m_data = CDataManager::Instance().m_setting_data;\n    if (dlg.DoModal() == IDOK)\n    {\n        CDataManager::Instance().m_setting_data = dlg.m_data;\n        return ITMPlugin::OR_OPTION_CHANGED;\n    }\n    return ITMPlugin::OR_OPTION_UNCHANGED;\n}\n\n\nvoid CPluginDemo::OnExtenedInfo(ExtendedInfoIndex index, const wchar_t* data)\n{\n    switch (index)\n    {\n    case ITMPlugin::EI_CONFIG_DIR:\n        //从配置文件读取配置\n        g_data.LoadConfig(std::wstring(data));\n\n        break;\n    default:\n        break;\n    }\n}\n\nvoid CPluginDemo::OnInitialize(ITrafficMonitor* pApp)\n{\n    m_app = pApp;\n    std::wstring str = m_app->GetStringRes(L\"IDS_MEMORY_USAGE\", L\"text\");\n    std::wstring str1 = m_app->GetStringRes(L\"BCP_47\", L\"general\");\n    int a = 0;\n}\n\nITMPlugin* TMPluginGetInstance()\n{\n    AFX_MANAGE_STATE(AfxGetStaticModuleState());\n    return &CPluginDemo::Instance();\n}\n"
  },
  {
    "path": "PluginDemo/PluginDemo.h",
    "content": "﻿#pragma once\n#include \"PluginInterface.h\"\n#include \"PluginSystemDate.h\"\n#include \"PluginSystemTime.h\"\n#include \"CustomDrawItem.h\"\n\nclass CPluginDemo : public ITMPlugin\n{\nprivate:\n    CPluginDemo();\n\npublic:\n    static CPluginDemo& Instance();\n\n    // 通过 ITMPlugin 继承\n    virtual IPluginItem* GetItem(int index) override;\n    virtual void DataRequired() override;\n    virtual const wchar_t* GetInfo(PluginInfoIndex index) override;\n    virtual OptionReturn ShowOptionsDialog(void* hParent) override;\n    virtual void OnExtenedInfo(ExtendedInfoIndex index, const wchar_t* data) override;\n    virtual void OnInitialize(ITrafficMonitor* pApp) override;\n\nprivate:\n    CPluginSystemDate m_system_date;\n    CPluginSystemTime m_system_time;\n    CCustomDrawItem m_custom_draw_item;\n    ITrafficMonitor* m_app{};\n\n    static CPluginDemo m_instance;\n};\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n    __declspec(dllexport) ITMPlugin* TMPluginGetInstance();\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "PluginDemo/PluginDemo.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"winres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// (壬й) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\nLANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED\n#pragma code_page(936)\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE \nBEGIN\n    \"#include \"\"winres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_OPTIONS_DIALOG DIALOGEX 0, 0, 165, 77\nSTYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"ʱں\"\nFONT 9, \"΢ź\", 400, 0, 0x0\nBEGIN\n    DEFPUSHBUTTON   \"ȷ\",IDOK,50,56,50,14\n    PUSHBUTTON      \"ȡ\",IDCANCEL,108,56,50,14\n    GROUPBOX        \"ʽ\",IDC_STATIC,7,7,151,45\n    CONTROL         \"ʾ\",IDC_SHOW_SECOND_CHECK,\"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,15,21,63,10\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// DESIGNINFO\n//\n\n#ifdef APSTUDIO_INVOKED\nGUIDELINES DESIGNINFO\nBEGIN\n    IDD_OPTIONS_DIALOG, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 158\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 70\n    END\nEND\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// AFX_DIALOG_LAYOUT\n//\n\nIDD_OPTIONS_DIALOG AFX_DIALOG_LAYOUT\nBEGIN\n    0\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION 1,0,0,1\n PRODUCTVERSION 1,0,0,1\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x2L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"080404b0\"\n        BEGIN\n            VALUE \"CompanyName\", \"By ZhongYang\"\n            VALUE \"FileDescription\", \"Plugin Demo for TrafficMonitor\"\n            VALUE \"FileVersion\", \"1.0.0.1\"\n            VALUE \"InternalName\", \"PluginDe.dll\"\n            VALUE \"LegalCopyright\", \"Copyright (C) 2021 By ZhongYang\"\n            VALUE \"OriginalFilename\", \"PluginDe.dll\"\n            VALUE \"ProductName\", \"Plugin Demo for TrafficMonitor\"\n            VALUE \"ProductVersion\", \"1.0.0.1\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x804, 1200\n    END\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// String Table\n//\n\nSTRINGTABLE\nBEGIN\n    IDS_PLUGIN_NAME         \"TrafficMonitorʾ\"\n    IDS_PLUGIN_DESCRIPTION  \"TrafficMonitorʾΪ߿TrafficMonitorṩ\"\n    IDS_TIME                \"ʱ\"\n    IDS_DATE                \"\"\n    IDS_CUSTOM_DRAW_ITEM    \"Իʾ\"\nEND\n\n#endif    // (壬й) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////\n// Ӣ() resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n#pragma code_page(1252)\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_OPTIONS_DIALOG DIALOGEX 0, 0, 165, 74\nSTYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Time and date settings\"\nFONT 9, \"Segoe UI\", 400, 0, 0x0\nBEGIN\n    DEFPUSHBUTTON   \"OK\",IDOK,50,53,50,14\n    PUSHBUTTON      \"Cancel\",IDCANCEL,108,53,50,14\n    GROUPBOX        \"Format\",IDC_STATIC,7,7,151,42\n    CONTROL         \"Show seconds\",IDC_SHOW_SECOND_CHECK,\"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,15,21,63,10\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// DESIGNINFO\n//\n\n#ifdef APSTUDIO_INVOKED\nGUIDELINES DESIGNINFO\nBEGIN\n    IDD_OPTIONS_DIALOG, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 158\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 67\n    END\nEND\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// AFX_DIALOG_LAYOUT\n//\n\nIDD_OPTIONS_DIALOG AFX_DIALOG_LAYOUT\nBEGIN\n    0\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// String Table\n//\n\nSTRINGTABLE\nBEGIN\n    IDS_PLUGIN_NAME         \"A sample plug-in for TrafficMonitor.\"\n    IDS_PLUGIN_DESCRIPTION  \"A sample plug-in for TrafficMonitor, providing an example for developers to develop TrafficMonitor plug-ins.\"\n    IDS_TIME                \"Time\"\n    IDS_DATE                \"Date\"\n    IDS_CUSTOM_DRAW_ITEM    \"Custom draw example\"\nEND\n\n#endif    // Ӣ() resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "PluginDemo/PluginDemo.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|ARM64EC\">\n      <Configuration>Debug</Configuration>\n      <Platform>ARM64EC</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|ARM64EC\">\n      <Configuration>Release</Configuration>\n      <Platform>ARM64EC</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>16.0</VCProjectVersion>\n    <Keyword>Win32Proj</Keyword>\n    <ProjectGuid>{d1ca3ecc-dc32-445a-b734-c4db08d4ba34}</ProjectGuid>\n    <RootNamespace>PluginDemo</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n    <UseOfMfc>Dynamic</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <UseOfMfc>Dynamic</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n    <UseOfMfc>Dynamic</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n    <UseOfMfc>Dynamic</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <UseOfMfc>Dynamic</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <UseOfMfc>Dynamic</UseOfMfc>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\plugins\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\plugins\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\plugins\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\plugins\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\plugins\\</OutDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\plugins\\</OutDir>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;PLUGINDEMO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;PLUGINDEMO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;PLUGINDEMO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;PLUGINDEMO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;PLUGINDEMO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;PLUGINDEMO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableUAC>false</EnableUAC>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\include\\PluginInterface.h\" />\n    <ClInclude Include=\"CustomDrawItem.h\" />\n    <ClInclude Include=\"DataManager.h\" />\n    <ClInclude Include=\"framework.h\" />\n    <ClInclude Include=\"OptionsDlg.h\" />\n    <ClInclude Include=\"pch.h\" />\n    <ClInclude Include=\"PluginDemo.h\" />\n    <ClInclude Include=\"PluginSystemDate.h\" />\n    <ClInclude Include=\"PluginSystemTime.h\" />\n    <ClInclude Include=\"resource.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"CustomDrawItem.cpp\" />\n    <ClCompile Include=\"DataManager.cpp\" />\n    <ClCompile Include=\"OptionsDlg.cpp\" />\n    <ClCompile Include=\"pch.cpp\">\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">Create</PrecompiledHeader>\n    </ClCompile>\n    <ClCompile Include=\"PluginDemo.cpp\" />\n    <ClCompile Include=\"PluginSystemDate.cpp\" />\n    <ClCompile Include=\"PluginSystemTime.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"PluginDemo.rc\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "PluginDemo/PluginDemo.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"源文件\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"头文件\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"资源文件\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"framework.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"pch.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PluginSystemTime.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PluginSystemDate.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"PluginDemo.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"DataManager.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\include\\PluginInterface.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"resource.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"OptionsDlg.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n    <ClInclude Include=\"CustomDrawItem.h\">\n      <Filter>头文件</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"pch.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PluginSystemTime.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PluginSystemDate.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"DataManager.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"OptionsDlg.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"PluginDemo.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n    <ClCompile Include=\"CustomDrawItem.cpp\">\n      <Filter>源文件</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"PluginDemo.rc\">\n      <Filter>资源文件</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "PluginDemo/PluginSystemDate.cpp",
    "content": "﻿#include \"pch.h\"\n#include <wchar.h>\n#include \"PluginSystemDate.h\"\n#include \"DataManager.h\"\n\nCPluginSystemDate::CPluginSystemDate()\n{\n}\n\nconst wchar_t* CPluginSystemDate::GetItemName() const\n{\n    return CDataManager::Instance().StringRes(IDS_DATE);\n}\n\nconst wchar_t* CPluginSystemDate::GetItemId() const\n{\n    return L\"uQI0sH6a\";\n}\n\nconst wchar_t* CPluginSystemDate::GetItemLableText() const\n{\n    return CDataManager::Instance().StringRes(IDS_DATE);\n}\n\nconst wchar_t* CPluginSystemDate::GetItemValueText() const\n{\n    return CDataManager::Instance().m_cur_date.c_str();\n}\n\nconst wchar_t* CPluginSystemDate::GetItemValueSampleText() const\n{\n    return L\"2022/08/08\";\n}\n"
  },
  {
    "path": "PluginDemo/PluginSystemDate.h",
    "content": "﻿#pragma once\n#include \"PluginInterface.h\"\n\nclass CPluginSystemDate : public IPluginItem\n{\npublic:\n    CPluginSystemDate();\n\n    // 通过 IPluginItem 继承\n    virtual const wchar_t* GetItemName() const override;\n    virtual const wchar_t* GetItemId() const override;\n    virtual const wchar_t* GetItemLableText() const override;\n    virtual const wchar_t* GetItemValueText() const override;\n    virtual const wchar_t* GetItemValueSampleText() const override;\n\nprivate:\n};\n"
  },
  {
    "path": "PluginDemo/PluginSystemTime.cpp",
    "content": "﻿#include \"pch.h\"\n#include <wchar.h>\n#include \"PluginSystemTime.h\"\n#include \"DataManager.h\"\n\nCPluginSystemTime::CPluginSystemTime()\n{\n}\n\nconst wchar_t* CPluginSystemTime::GetItemName() const\n{\n    return CDataManager::Instance().StringRes(IDS_TIME);\n}\n\nconst wchar_t* CPluginSystemTime::GetItemId() const\n{\n    return L\"B3tkxi5d\";\n}\n\nconst wchar_t* CPluginSystemTime::GetItemLableText() const\n{\n    return CDataManager::Instance().StringRes(IDS_TIME);\n}\n\nconst wchar_t* CPluginSystemTime::GetItemValueText() const\n{\n    return CDataManager::Instance().m_cur_time.c_str();\n}\n\nconst wchar_t* CPluginSystemTime::GetItemValueSampleText() const\n{\n    if (CDataManager::Instance().m_setting_data.show_second)\n        return L\"12:00:00\";\n    else\n        return L\"12:00\";\n}\n\nint CPluginSystemTime::IsDrawResourceUsageGraph() const\n{\n    return 1;\n}\n\nfloat CPluginSystemTime::GetResourceUsageGraphValue() const\n{\n    float value = CDataManager::Instance().m_system_time.wSecond / 60.0f;\n    return value;\n}\n"
  },
  {
    "path": "PluginDemo/PluginSystemTime.h",
    "content": "﻿#pragma once\n#include \"PluginInterface.h\"\n\nclass CPluginSystemTime : public IPluginItem\n{\npublic:\n    CPluginSystemTime();\n\npublic:\n    // 通过 IPluginItem 继承\n    virtual const wchar_t* GetItemName() const override;\n    virtual const wchar_t* GetItemId() const override;\n    virtual const wchar_t* GetItemLableText() const override;\n    virtual const wchar_t* GetItemValueText() const override;\n    virtual const wchar_t* GetItemValueSampleText() const override;\n    virtual int IsDrawResourceUsageGraph() const override;\n    virtual float GetResourceUsageGraphValue() const override;\n\nprivate:\n};\n"
  },
  {
    "path": "PluginDemo/framework.h",
    "content": "﻿#pragma once\n\n#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容\n//// Windows 头文件\n//#include <windows.h>\n\n#include <SDKDDKVer.h>\n\n#include <afxwin.h>         // MFC 核心组件和标准组件\n#include <afxext.h>         // MFC 扩展\n#include <afxdisp.h>        // MFC 自动化类\n\n#ifdef _UNICODE\n#if defined _M_IX86\n#pragma comment(linker,\"/manifestdependency:\\\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\\\"\")\n#elif defined _M_X64\n#pragma comment(linker,\"/manifestdependency:\\\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\\\"\")\n#else\n#pragma comment(linker,\"/manifestdependency:\\\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\\\"\")\n#endif\n#endif\n"
  },
  {
    "path": "PluginDemo/pch.cpp",
    "content": "﻿// pch.cpp: 与预编译标头对应的源文件\n\n#include \"pch.h\"\n\n// 当使用预编译的头时，需要使用此源文件，编译才能成功。\n"
  },
  {
    "path": "PluginDemo/pch.h",
    "content": "﻿// pch.h: 这是预编译标头文件。\n// 下方列出的文件仅编译一次，提高了将来生成的生成性能。\n// 这还将影响 IntelliSense 性能，包括代码完成和许多代码浏览功能。\n// 但是，如果此处列出的文件中的任何一个在生成之间有更新，它们全部都将被重新编译。\n// 请勿在此处添加要频繁更新的文件，这将使得性能优势无效。\n\n#ifndef PCH_H\n#define PCH_H\n\n// 添加要在此处预编译的标头\n#include \"framework.h\"\n\n#include \"resource.h\"\n\n#endif //PCH_H\n"
  },
  {
    "path": "PluginDemo/resource.h",
    "content": "﻿//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ 生成的包含文件。\n// 供 PluginDemo.rc 使用\n//\n#define IDD_DIALOG1                     101\n#define IDD_OPTIONS_DIALOG              101\n#define IDS_PLUGIN_NAME                 103\n#define IDS_PLUGIN_DESCRIPTION          104\n#define IDS_TIME                        105\n#define IDS_DATE                        106\n#define IDS_CUSTOM_DRAW_ITEM            107\n#define IDC_SHOW_SECOND_CHECK           1001\n#define IDC_SHOW_LABEL_CHECK            1002\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        104\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1003\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "README.md",
    "content": "**简体中文 | [English](./README_en-us.md)**\n\n[![Badge](https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg?style=flat-square)](https://996.icu/#/en_US)\n[![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg?style=flat-square)](https://github.com/996icu/996.ICU/blob/master/LICENSE)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/zhongyang219/TrafficMonitor/main.yml?branch=master&label=Release%20CI&logo=github&style=flat-square)](https://github.com/zhongyang219/TrafficMonitor/actions?query=workflow:\"Release+CI\")\n[![GitHub release](https://img.shields.io/github/release/zhongyang219/TrafficMonitor.svg?style=flat-square)](https://github.com/zhongyang219/TrafficMonitor/releases/latest)\n\n<a href=\"https://hellogithub.com/repository/5ef48af2b2794d4798b17d6539ec7305\" target=\"_blank\"><img src=\"https://api.hellogithub.com/v1/widgets/recommend.svg?rid=5ef48af2b2794d4798b17d6539ec7305&claim_uid=CeVqou2T1dIvfQP\" alt=\"Featured｜HelloGitHub\" style=\"width: 250px; height: 54px;\" width=\"250\" height=\"54\" /></a>\n\n# TrafficMonitor 简介\n\nTraffic Monitor是一款用于Windows平台的网速监控悬浮窗软件，可以显示当前网速、CPU及内存利用率，支持嵌入到任务栏显示，支持更换皮肤、历史流量统计等功能。\n\n# 相关链接：\n\n请[点击此处](https://github.com/zhongyang219/TrafficMonitor/releases/latest)下载TrafficMonitor的最新版本。\n\n备用链接：[百度网盘下载](https://pan.baidu.com/s/15PMt7s-ASpyDwtS__4cUhg) 提取码：`ou0m`\n\n国内用户如果遇到Github下载缓慢的问题，可以[点击此处](https://gitee.com/zhongyang219/TrafficMonitor)转到此项目在Gitee上的页面。\n\n如果遇到问题，请[点击此处](./Help.md)查看常见问题。\n\n你也可以[点击此处](https://github.com/zhongyang219/TrafficMonitor/actions?query=workflow:\"Release+CI\")下载TrafficMonitor的预发行构建版本。\n\n从1.80版本开始，TrafficMonitor加入了温度监控功能，如果你不需要温度监控功能，并且在使用1.80以上版本中遇到了问题，建议下载不含温度监控的版本（Lite版本）。（在Release页面找到文件名包含`Lite`的版本。）\n\nTrafficMonitor依赖于Microsoft Visual C++ 运行环境，如果程序启动时提示“找不到MSVC*.dll”，请点击以下链接下载并安装Microsoft Visual C++ 运行环境。\n\n[最新支持的 Visual C++ 可再发行程序包下载 | Microsoft Docs](https://docs.microsoft.com/zh-CN/cpp/windows/latest-supported-vc-redist?view=msvc-170)\n\n# 版本说明\n\nTrafficMonitor提供了标准版和Lite版两种版本可用。标准版包含了所有的功能，Lite版本则不包含温度监控、显卡利用率、硬盘利用率等硬件监控功能。标准版运行需要管理员权限，而Lite版本则不需要。\n\n如果没有监控温度等硬件信息的需要，建议使用Lite版。\n\n以下是两个版本功能对比。\n\n| 功能                          | 标准版 | Lite版 |\n| ----------------------------- | ------ | ------ |\n| 网速监控                      | ✔      | ✔      |\n| CPU、内存利用率          | ✔      | ✔      |\n| CPU、显卡、硬盘、主板温度监控  | ✔      | ❌      |\n| CPU频率监控 | ✔ | ✔ |\n| 显卡利用率监控                | ✔      | ❌      |\n| 硬盘利用率监控                | ✔      | ❌      |\n| 网络详细信息                  | ✔      | ✔      |\n| 插件系统                      | ✔      | ✔      |\n| 主窗口更换皮肤                | ✔      | ✔      |\n| 需要管理员权限                | 是     | 否     |\n\n# 主要特性\n\n* 显示当前实现网络传输速率、CPU和内存占用率\n* 如果电脑有多个网卡，支持自动和手动选择网络连接\n* 查看网络详细信息\n* 支持嵌入到任务栏显示\n* 支持更换皮肤和自定义皮肤\n* 历史流量统计\n* 硬件信息监控\n* 插件系统\n# 使用说明\n\n**[点击这里](https://github.com/zhongyang219/TrafficMonitor/wiki)转到Wiki页面查看关于TrafficMonitor的详细说明文档。**\n\n# 截图\n\n主悬浮窗：\n![](./Screenshots/main1.png)\n\n右键菜单：\n![](./Screenshots/main.png)\n\n任务栏窗口：\n\n![](./Screenshots/taskbar.PNG)\n\n多彩皮肤：\n<img src=\"./Screenshots/skins.PNG\" style=\"zoom:80%;\" />\n\n# 如何使用\n程序启动后在会在屏幕中显示一个显示网速的悬浮窗。在悬浮窗上点击鼠标右键可以弹出右键菜单。\n\nTrafficMonitor支持将信息显示到任务栏。但是TrafficMonitor默认只显示主窗口（悬浮窗），如果需要让它嵌入到任务栏显示，请在右键菜单中选择“显示任务栏窗口”命令。\n\n任务栏窗口支持自定义显示项目，默认情况下只显示网速，如果需要显示CPU和内存利用率等其他信息，请在任务栏窗口右键菜单中选择“显示设置”，在弹出的“显示设置”对话框中勾选需要显示的项目，如下图所示：\n\n<img src=\"./Screenshots/taskbar_item_settings.png\" style=\"zoom:80%;\" />\n\n# 自定义皮肤\n<img src=\"./Screenshots/selecte_skin.png\" style=\"zoom:80%;\" />\n\n在主窗口或通知区图标右键菜单上选择“其他功能”——“更换皮肤”可以打开更换皮肤界面。[点击此处](https://github.com/zhongyang219/TrafficMonitorSkin/blob/master/皮肤下载.md)可以下载更多皮肤。用户还可以根据自己的需要编辑自己的皮肤。\n\n皮肤文件放在程序所在目录的`skins`目录下，每个皮肤被放到单独的文件夹下，文件夹的名称就是皮肤的名称。\n\n其中`background.bmp`和`background_l.bmp`是背景图片，`skin.ini`是皮肤的配置文件，可以通过`skin.ini`指定文本颜色、字体、皮肤作者、每个项目的大小和位置等信息。\n\n从1.80版本开始增加了xml格式的皮肤配置文件`skin.xml`，只有xml格式的皮肤配置文件才支持温度和显卡使用率显示。\n\n从1.85版本开始增加了对png格式背景图片的支持，你可以使用png格式来制作带透明背景的皮肤，背景图片的文件名为`background.png`和`background_l.png`。\n\n详细的皮肤制作教程请点击以下链接：\n\n[皮肤制作教程 · zhongyang219/TrafficMonitor Wiki (github.com)](https://github.com/zhongyang219/TrafficMonitor/wiki/皮肤制作教程)\n\n# 选项设置\n<img src=\"./Screenshots/option.jpg\" style=\"zoom:80%;\" />\n\n在右键菜单选择“选项...”可以进入选项设置。在选项设置对话框中，可以单独设置主窗口和任务栏窗口的文本颜色、字体、背景颜色、网速单位、显示的文本等。\n\n在“常规设置”选项卡中，可以设置是否在程序时自动检查更新，以及是否需要在开机是自动运行。可以设置在什么时候需要发出消息通知。\n\n从1.72版本开始，支持每个项目文本颜色单独设置。勾选“指定每个项目的颜色”后，点击“文本颜色”右边的颜色框，会弹出详细颜色设置的对话框，可以在这里单独指定每个项目的颜色。\n\n# 插件系统\n\n从1.82版本开始增加了插件系统，插件dll必须放在“TrafficMonitor.exe”同级目录的“plugins”目录下。程序启动后，插件会自动加载。你可以在右键菜单“更多功能”——“插件管理”中查看并管理已加载的插件。\n\n关于如何开发TrafficMonitor的说明，请参见[插件开发指南 · zhongyang219/TrafficMonitor Wiki (github.com)](https://github.com/zhongyang219/TrafficMonitor/wiki/插件开发指南)。\n\n要下载TrafficMonitor插件，请[点击这里](https://github.com/zhongyang219/TrafficMonitorPlugins/blob/main/download/plugin_download.md)。\n\n# 关于硬件监控功能\n\n从1.80版本开始，TrafficMonitor加入了硬件监控功能（包括温度监控和显卡使用率监控、CPU频率监控），它使用了第三方开源库[LibreHardwareMonitor](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor)。如果你在使用温度监控功能时遇到了问题，请[点击这里](./Help.md#13-关于trafficmonitor温度监控的问题)。\n\n需要注意的是，温度监控功能默认是关闭的，如果你要使用TrafficMonitor的温度监控功能，请到[“选项设置”-“常规设置”-“硬件监控”](https://github.com/zhongyang219/TrafficMonitor/wiki/选项设置#硬件监控)中开启。\n\n**注意：硬件监控功能（包括温度监控和显卡使用率监控）可能存在一些问题，它可能会占用更多的CPU和内存。据部分用户反馈，开启温度功能后会导致程序崩溃和系统死机等问题，请在知晓以上风险后再决定开启硬件监控功能。否则，请不要使用硬件监控功能。**\n\n# 更新日志\n\n**[点击此处查看更新日志](./UpdateLog/update_log.md)**\n"
  },
  {
    "path": "README_en-us.md",
    "content": "**[简体中文](./README.md) | English**\n\n[![Badge](https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg?style=flat-square)](https://996.icu/#/en_US)\n[![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg?style=flat-square)](https://github.com/996icu/996.ICU/blob/master/LICENSE)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/zhongyang219/TrafficMonitor/main.yml?branch=master&label=Release%20CI&logo=github&style=flat-square)](https://github.com/zhongyang219/TrafficMonitor/actions?query=workflow:\"Release+CI\")\n[![GitHub release](https://img.shields.io/github/release/zhongyang219/TrafficMonitor.svg?style=flat-square)](https://github.com/zhongyang219/TrafficMonitor/releases/latest)\n\n<a href=\"https://hellogithub.com/repository/5ef48af2b2794d4798b17d6539ec7305\" target=\"_blank\"><img src=\"https://api.hellogithub.com/v1/widgets/recommend.svg?rid=5ef48af2b2794d4798b17d6539ec7305&claim_uid=CeVqou2T1dIvfQP\" alt=\"Featured｜HelloGitHub\" style=\"width: 250px; height: 54px;\" width=\"250\" height=\"54\" /></a>\n\n# TrafficMonitor Introduction\n\nTrafficMonitor is a network monitoring software with floating window feature for Windows. It displays the current internet speed and CPU and RAM usage. There are also other capabilities like an embedded display in the taksbar, changeable display skins, and historical traffic statistics. \n\n# Related Links\n\nPlease [click here](https://github.com/zhongyang219/TrafficMonitor/releases/latest) to download the latest version of TrafficMonitor. \n\nAlternate link: Download from [Baidu Netdisk](https://pan.baidu.com/s/15PMt7s-ASpyDwtS__4cUhg). Access code: `ou0m`  \n\nYou can find the project page on Gitee by [clicking here](https://gitee.com/zhongyang219/TrafficMonitor)\n\nIf you encounter any problems, please [click here](./Help_en-us.md) for frequently asked questions.  \n\nYou can also [click here](https://github.com/zhongyang219/TrafficMonitor/actions?query=workflow:\"Release+CI\") to download the pre-release build version of TrafficMonitor.\n\nFor version 1.80 and later, the temperature monitoring function has been added. If the user does not need the temperature monitoring function and encounters problems with version 1.80 or later, it is recommended to download the earlier version without the temperature monitor (Lite version). (You can find the `Lite` version on the Release page.)\n\nTrafficMonitor relies on the Microsoft Visual C++ operrating environment. If an error prompts \"Cannot find MSVC*.dll\" when the program starts, please click the link below to download and install the Microsoft Visual C++ operating environment.\n\n[Download the latest supported version of Visual C++ Redistributable Package | Microsoft Docs](https://docs.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170)\n\n# Version description\n\nThere are two versions of TrafficMonitor, the standard version and the Lite version. The standard version includes all the functions, while the Lite version does not include hardware monitoring functions such as temperature monitoring, GPU usage, and hard disk usage. The standard version requires administrator privilege to run, while the Lite version does not. \n\nIf there is no need to monitor the temperature and other hardware information, it is recommended to use the Lite version.\n\nSee below for the functions comparison of the two versions.\n\n| Functions                                     | Standard Version | Lite Version |\n| --------------------------------------------- | ---------------- | ------------ |\n| Internet speed monitoring                     | ✔                | ✔            |\n| CPU and RAM usage monitoring                  | ✔                | ✔            |\n| CPU, GPU, hard disk, mother board temperature | ✔                | ❌            |\n| CPU frequency monitoring                      | ✔                | ✔            |\n| GPU usage monitoring                          | ✔                | ❌            |\n| Hard disk usage monitoring                    | ✔                | ❌            |\n| Network connection details                    | ✔                | ✔            |\n| Plug-in system                                | ✔                | ✔            |\n| Change the skin of the main window            | ✔                | ✔            |\n| Administrator privilege required              | Yes              | No           |\n\n# Main Features\n\n* Displays current network transmission speed and CPU and RAM usage\n* If multiple network adapters are available, users can automatically or manually select networks to connect \n* Display network connection details\n* Support embedded display in taskbar\n* Support skin change and customizable skins\n* Historical traffic statistics\n* Hardware information monitoring\n* Plug-in system\n\n# Instructions for use\n\n**[Click here](https://github.com/zhongyang219/TrafficMonitor/wiki) to go to the Wiki page to view detailed documentation on TrafficMonitor (Only Available in Chinese).**\n\n# Screenshots\n\nMain Floating Window:  \n![](./Screenshots/en_us/main1.png)  \nRight-Click Menu:  \n![](./Screenshots/en_us/main.png)  \nTaskbar Window  \n\n![](./Screenshots/en_us/taskbar.png)  \n\nColorful Skins:  \n\n![](./Screenshots/skins.PNG)  \n\nChange Skins:  \n\n![](./Screenshots/en_us/selecte_skin.png)  \n\nOptions:  \n\n<img src=\"./Screenshots/en_us/option.jpg\" style=\"zoom:80%;\" />  \n\n# How to Use\n\nAs the program starts, a floating window showing network speed will appear on the screen. Right click on the floating window to open up the pop-up menu.\n\nTrafficMonitor can display information on the taskbar. However, the default setting for TrafficMonitor shows only the main window (floating window), in order to show embedded display on the taskbar, right click the window and select \"Show Taskbar Window\" in the pop-up menu.\n\nUsers can customize displayed items on the embedded taskbar window. By default, only the network speed is displayed. In order to display CPU and RAM usage, or other informations, please select “Display Settings” in the right-click menu of the taskbar window, and check the items you want to display in the “Display Settings” dialog box, as shown below:\n\n<img src=\"./Screenshots/en_us/taskbar_item_settings.png\" style=\"zoom:80%;\" />\n\n# Customizable Skin\n<img src=\"./Screenshots/en_us/selecte_skin.png\" style=\"zoom:80%;\" />\n\nYou can select “Other Functions”-“Change Skin” on the right-click menu of the main window or notification area icon to open the interface of changing skin. Users can also download more skins and customize the skins [here](https://github.com/zhongyang219/TrafficMonitorSkin/blob/master/皮肤下载.md) according to their own needs.\n\nSkin files are stored under the `skins` directory within the directory where the app is located. Each skin is stored in its individual folder and the name of the folder is the name of the skin. \n\nAmong the files, `background.bmp` and `background_l.bmp` are background pictures，`skin.ini` is the configuration document for the skin, users can customize text colors, fonts, skin creator, and the size and location of each items etc. \n\nSince version 1.80, an xml format of skin configuration file `skin.xml` has been added. Without the xml skin configuration document, TrafficMonitor will not be able to display temperature and GUP usage.\n\nSince version 1.85, support for background images in png format has been added, you can use the png format to create skins with transparent backgrounds. The file names of the background image files are `background.png` and `background_l.png`.\n\nClick the link below for detailed instruction on skin making: \n\n[皮肤制作教程 · zhongyang219/TrafficMonitor Wiki (github.com)](https://github.com/zhongyang219/TrafficMonitor/wiki/皮肤制作教程)\n\n# Configuring Options\n<img src=\"./Screenshots/en_us/option.jpg\" style=\"zoom:80%;\" /><br>\nChoosing \"Options...\" in the pop-up menu allows users to access the options configuration. In the dialog box of options configuration, the user can set the text color, text font, background color, net speed unit, and displayed text etc. for the main window and task window separately. \n\nIn \"Regular Configurations\", users can change the settings on whether the program conducts auto-update and whether the program runs automatically when the computer starts up. Users can also configure when notifications need to be sent. \n\nFor version 1.72 and later, users can configure text colors for each item individually. Check the option to \"Designate Colors for Each Items\", click the color box on the right of \"text colors\" to prompt a pop-up dialog box for detailed color configuration where users can designate colors for each items inidividually. \n\n# Plug-in system\n\nFor version 1.82 and later, plug-in system has been added. The plug-in dll must be placed in the \"plugins\" directory, at the same level directory with \"TrafficMonitor.exe\". The plug-in should load automatically as the program starts up. Users can view and manage the loaded plugins in the pop-up menu \"More Functions\"-\"Plugin Management\".\n\nFor instructions on how to develop the plugins for TrafficMonitor, please see [Plugin Development Guide · zhongyang219/TrafficMonitor Wiki (github.com)](https://github.com/zhongyang219/TrafficMonitor/wiki/Plugin-Development-Guide).\n\nTo download the TrafficMonitor plugins, please [click here](https://github.com/zhongyang219/TrafficMonitorPlugins/blob/main/download/plugin_download.md).\n\n# About the hardware monitoring function\n\nFor version 1.80 or later, the hardware monitoring functions (including temperature, CPU frequency, and GPU usage monitoring) have been added to TrafficMonitor. It relies on the open source library [LibreHardwareMonitor](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor). If you encounter issues using the temperature monitoring function, please [click here](./Help_en-us.md#13-about-the-temperature-monitoring-of-trafficmonitor). \n\nIt should also be noted that the temperature monitoring function is turned off by default. If users want to use the temperature monitoring function in TrafficMonitor, please go to [\"Option Settings\"-\"General Settings\"-\"Hardware Monitoring\"](https://github.com/zhongyang219/TrafficMonitor/wiki/选项设置#硬件监控) to enable it.\n\n**Note: The hardware monitoring function (including temperature monitoring and GPU usage monitoring) may still have some issues, which might consume more CPU and RAM. According to the feedback from some users, turning on the temperature function causes issues such as program crashing and system crashing, etc. Please consider the above risks before turning on the hardware monitoring function. Otherwise, please do not use the hardware monitoring function.**\n\n# Update log\n\n**[Click here to view the update log.](./UpdateLog/update_log_en-us.md)**\n\n"
  },
  {
    "path": "TrafficMonitor/AboutDlg.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"AboutDlg.h\"\n#include \"MessageDlg.h\"\n#include \"DrawCommon.h\"\n\nBEGIN_MESSAGE_MAP(CAboutDlg, CBaseDialog)\n    //ON_STN_CLICKED(IDC_STATIC_DONATE, &CAboutDlg::OnStnClickedStaticDonate)\n    ON_MESSAGE(WM_LINK_CLICKED, &CAboutDlg::OnLinkClicked)\n    ON_WM_PAINT()\n    ON_WM_ERASEBKGND()\n    ON_WM_CTLCOLOR()\nEND_MESSAGE_MAP()\n\nCAboutDlg::CAboutDlg() : CBaseDialog(IDD_ABOUTBOX)\n{\n}\n\nvoid CAboutDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_STATIC_MAIL, m_mail);\n    DDX_Control(pDX, IDC_STATIC_ACKNOWLEDGEMENT, m_acknowledgement);\n    DDX_Control(pDX, IDC_STATIC_GITHUB, m_github);\n    DDX_Control(pDX, IDC_TRANSLATOR_STATIC, m_translator_static);\n    DDX_Control(pDX, IDC_STATIC_LICENSE, m_license);\n    DDX_Control(pDX, IDC_OPENHARDWAREMONITOR_LINK, m_openhardwaremonitor_link);\n    DDX_Control(pDX, IDC_TINYXML2_LINK, m_tinyxml2_link);\n    DDX_Control(pDX, IDC_MUSICPLAYER2_LINK, m_musicplayer2_link);\n    DDX_Control(pDX, IDC_SIMPLENOTEPAD_LINK, m_simplenotepad_link);\n    DDX_Control(pDX, IDC_STATIC_GITEE, m_gitee);\n}\n\nCString CAboutDlg::GetDonateList()\n{\n    return CCommon::GetTextResource(IDR_ACKNOWLEDGEMENT_TEXT, 2);\n}\n\nCString CAboutDlg::GetDialogName() const\n{\n    return _T(\"AboutDlg\");\n}\n\nbool CAboutDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_STATIC_MAIL },\n        { CtrlTextInfo::L3, IDC_STATIC_GITHUB },\n        { CtrlTextInfo::L2, IDC_STATIC_GITEE },\n        { CtrlTextInfo::L4, IDC_STATIC_LICENSE },\n        { CtrlTextInfo::L3, IDC_STATIC_DONATE },\n        { CtrlTextInfo::L2, IDC_STATIC_ACKNOWLEDGEMENT }\n        });\n    return true;\n}\n\nCRect CAboutDlg::CalculatePicRect()\n{\n    CRect rect;\n    GetClientRect(rect);\n    CRect rc_pic = rect;\n    ::GetWindowRect(GetDlgItem(IDC_STATIC_VERSION)->GetSafeHwnd(), rect);\n    ScreenToClient(rect);\n    rc_pic.bottom = rect.top - theApp.DPI(6);\n    if (rc_pic.Height() <= 0)\n        rc_pic.bottom = rc_pic.top + theApp.DPI(50);\n    return rc_pic;\n}\n\nBOOL CAboutDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetRememberDlgSize(false);\n\n    m_mail.SetURL(_T(\"mailto:zhongyang219@hotmail.com\"));   //设置超链接\n    //m_check_update.SetURL(_T(\"http://pan.baidu.com/s/1c1LkPQ4\"));\n    m_github.SetURL(_T(\"https://github.com/zhongyang219/TrafficMonitor\"));\n    m_gitee.SetURL(_T(\"https://gitee.com/zhongyang219/TrafficMonitor\"));\n    m_acknowledgement.SetLinkIsURL(false);\n    m_license.SetLinkIsURL(false);\n\n    m_openhardwaremonitor_link.SetURL(_T(\"https://github.com/LibreHardwareMonitor/LibreHardwareMonitor\"));\n    m_tinyxml2_link.SetURL(_T(\"https://github.com/leethomason/tinyxml2\"));\n    m_musicplayer2_link.SetURL(_T(\"https://github.com/zhongyang219/MusicPlayer2\"));\n    m_simplenotepad_link.SetURL(_T(\"https://github.com/zhongyang219/SimpleNotePad\"));\n    m_openhardwaremonitor_link.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_tinyxml2_link.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_musicplayer2_link.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_simplenotepad_link.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_mail.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_acknowledgement.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_github.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_gitee.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n    m_license.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n\n    //设置版本信息\n    CString version_info;\n    GetDlgItemText(IDC_STATIC_VERSION, version_info);\n    CString str_lite;\n#ifdef WITHOUT_TEMPERATURE\n    str_lite = CCommon::LoadText(_T(\" (\"), IDS_WITHOUT_TEMPERATURE, _T(\")\"));\n#endif\n    version_info = CCommon::StringFormat(version_info, { str_lite, VERSION });\n\n#ifdef COMPILE_FOR_WINXP\n    version_info += _T(\" (For WinXP)\");\n#endif // COMPILE_FOR_WINXP\n\n#ifdef _M_ARM64EC\n    version_info += _T(\" (Arm64EC)\");\n#elif _M_X64\n    version_info += _T(\" (x64)\");\n#endif\n\n#ifdef _DEBUG\n    version_info += _T(\" (Debug)\");\n#endif\n\n    SetDlgItemText(IDC_STATIC_VERSION, version_info);\n\n    //设置最后编译日期\n    CString temp_str;\n    GetDlgItemText(IDC_STATIC_COPYRIGHT, temp_str);\n    CString str_compile_time = CCommon::GetLastCompileTime();\n    temp_str.Replace(_T(\"<compile_date>\"), str_compile_time);\n    SetDlgItemText(IDC_STATIC_COPYRIGHT, temp_str);\n\n    m_tool_tip.Create(this, TTS_ALWAYSTIP | TTS_NOPREFIX);\n    m_tool_tip.AddTool(&m_mail, CCommon::LoadText(IDS_SEND_EMAIL_TO_ATHOUR, _T(\"\\r\\nmailto:zhongyang219@hotmail.com\")));\n    //m_tool_tip.AddTool(&m_check_update, _T(\"到百度网盘链接查看是否有更新\\r\\nhttp://pan.baidu.com/s/1c1LkPQ4\"));\n    m_tool_tip.AddTool(&m_github, CCommon::LoadText(IDS_GOTO_GITHUB, _T(\"\\r\\nhttps://github.com/zhongyang219/TrafficMonitor\")));\n    m_tool_tip.AddTool(&m_gitee, CCommon::LoadText(IDS_GOTO_GITEE, _T(\"\\r\\nhttps://gitee.com/zhongyang219/TrafficMonitor\")));\n    m_tool_tip.AddTool(&m_openhardwaremonitor_link, m_openhardwaremonitor_link.GetURL());\n    m_tool_tip.AddTool(&m_tinyxml2_link, m_tinyxml2_link.GetURL());\n    m_tool_tip.AddTool(&m_musicplayer2_link, CCommon::LoadText(IDS_MUSICPLAYER2_DESCRIPTION) + _T(\"\\r\\n\") + m_musicplayer2_link.GetURL());\n    m_tool_tip.AddTool(&m_simplenotepad_link, CCommon::LoadText(IDS_SIMPLENOTEPAD_DESCRIPTION) + _T(\"\\r\\n\") + m_simplenotepad_link.GetURL());\n\n    m_tool_tip.SetDelayTime(300);   //设置延迟\n    m_tool_tip.SetMaxTipWidth(800);\n\n    //设置翻译者信息\n    const auto& language_info{ theApp.m_str_table.GetLanguageInfo() };\n    wstring language_tag{ language_info.bcp_47 };\n    if (language_info.translator.empty())           //没有翻译者时不显示翻译者信息\n    {\n        m_translator_static.ShowWindow(SW_HIDE);\n    }\n    m_translator_static.SetWindowTextW(theApp.m_str_table.LoadTextFormat(L\"TXT_ABOUT_TRANSLATOR\", { language_info.display_name, language_info.translator }).c_str());\n    std::wstring translator_url{ language_info.translator_url };\n    if (!translator_url.empty())     //显示翻译者的信息\n    {\n        //如果url中包含“@”但是前面没有“mailto:”，则在前面加上“mailto:”\n        if (translator_url.find(L'@') != std::wstring::npos && (translator_url.size() < 7 || translator_url.substr(0, 7) != L\"mailto:\"))\n            translator_url = L\"mailto:\" + translator_url;\n        m_translator_static.SetURL(translator_url.c_str());\n        CString str_tool_tip = CCommon::LoadText(IDS_CONTACT_TRANSLATOR);\n        str_tool_tip += _T(\"\\r\\n\");\n        str_tool_tip += translator_url.c_str();\n        m_tool_tip.AddTool(&m_translator_static, str_tool_tip);\n    }\n    m_translator_static.SetBackgroundColor(GetSysColor(COLOR_WINDOW));\n\n    //加载图片\n    m_about_pic.LoadBitmap(IDB_ABOUT_BACKGROUND_HD);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\nBOOL CAboutDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    if (pMsg->message == WM_MOUSEMOVE)\n        m_tool_tip.RelayEvent(pMsg);\n\n    return CBaseDialog::PreTranslateMessage(pMsg);\n}\n\n//void CAboutDlg::OnStnClickedStaticDonate()\n//{\n//  CDonateDlg donateDlg;\n//  donateDlg.DoModal();\n//}\n\nafx_msg LRESULT CAboutDlg::OnLinkClicked(WPARAM wParam, LPARAM lParam)\n{\n    CWnd* pCtrl = (CWnd*)wParam;\n    if (pCtrl == &m_acknowledgement)\n    {\n        CString strContent = GetDonateList();\n        //strContent += _T(\"\\r\\n\");\n        //strContent += CCommon::LoadText(IDS_ACKNOWLEDGEMENT_EXPLAIN);\n        CMessageDlg dlg;\n        dlg.SetWindowTitle(CCommon::LoadText(IDS_TITLE_ACKNOWLEDGEMENT));\n        //dlg.SetInfoText(CCommon::LoadText(IDS_THANKS_DONORS));\n        dlg.SetMessageText(strContent);\n        dlg.DoModal();\n    }\n    else if (pCtrl == &m_license)\n    {\n        CMessageDlg dlg;\n        dlg.SetWindowTitle(CCommon::LoadText(IDS_LICENSE));\n        dlg.SetInfoText(CCommon::LoadText(IDS_LICENSE_EXPLAIN));\n        dlg.SetMessageText(CCommon::GetTextResource(IDR_LICENSE, 1));\n        dlg.DoModal();\n    }\n\n    return 0;\n}\n\nvoid CAboutDlg::OnPaint()\n{\n    CPaintDC dc(this); // device context for painting\n                       // TODO: 在此处添加消息处理程序代码\n                       // 不为绘图消息调用 CBaseDialog::OnPaint()\n    CDrawCommon draw;\n    draw.Create(&dc, this);\n    CRect rc_pic = CalculatePicRect();\n    draw.GetDC()->FillSolidRect(rc_pic, RGB(161, 200, 255));\n    draw.DrawBitmap(m_about_pic, rc_pic.TopLeft(), rc_pic.Size(), CDrawCommon::StretchMode::FIT);\n}\n\n\nBOOL CAboutDlg::OnEraseBkgnd(CDC* pDC)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    CRect draw_rect;\n    GetClientRect(draw_rect);\n    pDC->FillSolidRect(draw_rect, GetSysColor(COLOR_WINDOW));\n\n    //绘制白色背景\n    int white_height;       //白色区域的高度\n    CRect rc_copyright{};\n    ::GetWindowRect(GetDlgItem(IDOK)->GetSafeHwnd(), rc_copyright);\n    ScreenToClient(rc_copyright);\n    white_height = rc_copyright.top - theApp.DPI(6);\n\n    //绘制“确定”按钮上方的分割线\n    CRect rc_line{ draw_rect };\n    rc_line.top = white_height;\n    rc_line.bottom = white_height + theApp.DPI(1);\n    pDC->FillSolidRect(rc_line, RGB(210, 210, 210));\n\n    //绘制灰色背景\n    CRect rc_gray{ rc_line };\n    rc_gray.top = rc_line.bottom;\n    rc_gray.bottom = draw_rect.bottom;\n    pDC->FillSolidRect(rc_gray, GetSysColor(COLOR_BTNFACE));\n\n    return TRUE;\n    //return CBaseDialog::OnEraseBkgnd(pDC);\n}\n\n\nHBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)\n{\n    HBRUSH hbr = CBaseDialog::OnCtlColor(pDC, pWnd, nCtlColor);\n\n    // TODO:  在此更改 DC 的任何特性\n    //去掉static控件的灰色灰色背景\n    UINT ctrl_id = pWnd->GetDlgCtrlID();\n    if (ctrl_id == IDC_STATIC_VERSION || ctrl_id == IDC_STATIC_COPYRIGHT || ctrl_id == IDC_STATIC)\n    {\n        static HBRUSH hBackBrush{};\n        if (hBackBrush == NULL)\n            hBackBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));\n        pDC->SetBkColor(GetSysColor(COLOR_WINDOW));\n        return hBackBrush;\n    }\n\n    // TODO:  如果默认的不是所需画笔，则返回另一个画笔\n    return hbr;\n}\n"
  },
  {
    "path": "TrafficMonitor/AboutDlg.h",
    "content": "﻿#pragma once\n#include \"LinkStatic.h\"\n#include \"BaseDialog.h\"\n\n// 用于应用程序“关于”菜单项的 CAboutDlg 对话框\n\nclass CAboutDlg : public CBaseDialog\n{\npublic:\n    CAboutDlg();\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_ABOUTBOX };\n#endif\n\nprotected:\n    CLinkStatic m_mail;             //“联系作者”超链接\n    CLinkStatic m_acknowledgement;  //“鸣谢”超链接\n    CLinkStatic m_github;           //“GitHub”超链接\n    CLinkStatic m_gitee;            //“Gitee”超链接\n    CLinkStatic m_license;          //“开源协议”超链接\n    CToolTipCtrl m_tool_tip;            //鼠标指向时的工具提示\n    CLinkStatic m_translator_static;\n    CLinkStatic m_openhardwaremonitor_link;\n    CLinkStatic m_tinyxml2_link;\n    CLinkStatic m_musicplayer2_link;\n    CLinkStatic m_simplenotepad_link;\n\n    CBitmap m_about_pic;\n\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    CString GetDonateList();        //从资源文件加载捐赠人员名单\n    virtual CString GetDialogName() const override;\n    virtual bool InitializeControls() override;\n    CRect CalculatePicRect();       //计算图片的位置\n\n    // 实现\nprotected:\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    //  afx_msg void OnStnClickedStaticDonate();\nprotected:\n    afx_msg LRESULT OnLinkClicked(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnPaint();\n    afx_msg BOOL OnEraseBkgnd(CDC* pDC);\n    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);\n};\n"
  },
  {
    "path": "TrafficMonitor/AdapterCommon.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"AdapterCommon.h\"\n\n\nCAdapterCommon::CAdapterCommon()\n{\n}\n\n\nCAdapterCommon::~CAdapterCommon()\n{\n}\n\nvoid CAdapterCommon::GetAdapterInfo(vector<NetWorkConection>& adapters)\n{\n\tadapters.clear();\n\tPIP_ADAPTER_INFO pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[sizeof(IP_ADAPTER_INFO)];\t\t//PIP_ADAPTER_INFO结构体指针存储本机网卡信息\n\tunsigned long stSize = sizeof(IP_ADAPTER_INFO);\t\t//得到结构体大小,用于GetAdaptersInfo参数\n\tint nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);\t//调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量\n\n\tif (ERROR_BUFFER_OVERFLOW == nRel)\n\t{\n\t\t//如果函数返回的是ERROR_BUFFER_OVERFLOW\n\t\t//则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小\n\t\t//这也是说明为什么stSize既是一个输入量也是一个输出量\n\t\tdelete[] (BYTE*)pIpAdapterInfo;\t//释放原来的内存空间\n\t\tpIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];\t//重新申请内存空间用来存储所有网卡信息\n\t\tnRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);\t\t//再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量\n\t}\n\n\tPIP_ADAPTER_INFO pIpAdapterInfoHead = pIpAdapterInfo;\t//保存pIpAdapterInfo链表中第一个元素的地址\n\tif (ERROR_SUCCESS == nRel)\n\t{\n\t\twhile (pIpAdapterInfo)\n\t\t{\n\t\t\tNetWorkConection connection;\n\t\t\tconnection.description = pIpAdapterInfo->Description;\n\t\t\tconnection.ip_address = CCommon::StrToUnicode(pIpAdapterInfo->IpAddressList.IpAddress.String);\n\t\t\tconnection.subnet_mask = CCommon::StrToUnicode(pIpAdapterInfo->IpAddressList.IpMask.String);\n\t\t\tconnection.default_gateway = CCommon::StrToUnicode(pIpAdapterInfo->GatewayList.IpAddress.String);\n\n\t\t\tadapters.push_back(connection);\n\t\t\tpIpAdapterInfo = pIpAdapterInfo->Next;\n\t\t}\n\t}\n\t//释放内存空间\n\tif (pIpAdapterInfoHead)\n\t{\n\t\tdelete[] (BYTE*)pIpAdapterInfoHead;\n\t}\n\tif (adapters.empty())\n\t{\n\t\tNetWorkConection connection{};\n\t\tconnection.description = CCommon::UnicodeToStr(CCommon::LoadText(L\"<\", IDS_NO_CONNECTION, L\">\"));\n\t\tadapters.push_back(connection);\n\t}\n}\n\nvoid CAdapterCommon::RefreshIpAddress(vector<NetWorkConection>& adapters)\n{\n\tvector<NetWorkConection> adapters_tmp;\n\tGetAdapterInfo(adapters_tmp);\n\tfor (const auto& adapter_tmp : adapters_tmp)\n\t{\n\t\tfor (auto& adapter : adapters)\n\t\t{\n\t\t\tif (adapter_tmp.description == adapter.description)\n\t\t\t{\n\t\t\t\tadapter.ip_address = adapter_tmp.ip_address;\n\t\t\t\tadapter.subnet_mask = adapter_tmp.subnet_mask;\n\t\t\t\tadapter.default_gateway = adapter_tmp.default_gateway;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CAdapterCommon::GetIfTableInfo(vector<NetWorkConection>& adapters, MIB_IFTABLE* pIfTable)\n{\n\t//依次在IfTable里查找每个连接\n\tfor (size_t i{}; i < adapters.size(); i++)\n\t{\n\t\tif (adapters[i].description.empty())\n\t\t\tcontinue;\n\t\tint index;\n\t\tindex = FindConnectionInIfTable(adapters[i].description, pIfTable);\n\t\tif (index == -1)\t\t//如果使用精确匹配的方式没有找到，则采用模糊匹配的方式再查找一次\n\t\t\tindex = FindConnectionInIfTableFuzzy(adapters[i].description, pIfTable);\n\t\t//if (index != -1)\n\t\t//{\n\t\tadapters[i].index = index;\n\t\tadapters[i].in_bytes = pIfTable->table[index].dwInOctets;\n\t\tadapters[i].out_bytes = pIfTable->table[index].dwOutOctets;\n\t\tadapters[i].description_2 = (const char*)pIfTable->table[index].bDescr;\n\t\t//}\n\t}\n}\n\nvoid CAdapterCommon::GetAllIfTableInfo(vector<NetWorkConection>& adapters, MIB_IFTABLE * pIfTable)\n{\n\tvector<NetWorkConection> adapters_tmp;\n\tGetAdapterInfo(adapters_tmp);\t\t//获取IP地址\n\tadapters.clear();\n\tfor (size_t i{}; i < pIfTable->dwNumEntries; i++)\n\t{\n\t\tNetWorkConection connection;\n\t\tconnection.description = connection.description_2 = (const char*)pIfTable->table[i].bDescr;\n\t\tconnection.index = i;\n\t\tconnection.in_bytes = pIfTable->table[i].dwInOctets;\n\t\tconnection.out_bytes = pIfTable->table[i].dwOutOctets;\n\t\tfor (size_t j{}; j < adapters_tmp.size(); j++)\n\t\t{\n\t\t\tif (connection.description.find(adapters_tmp[j].description) != string::npos)\n\t\t\t{\n\t\t\t\tconnection.ip_address = adapters_tmp[j].ip_address;\n\t\t\t\tconnection.subnet_mask = adapters_tmp[j].subnet_mask;\n\t\t\t\tconnection.default_gateway = adapters_tmp[j].default_gateway;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tadapters.push_back(connection);\n\t}\n}\n\nint CAdapterCommon::FindConnectionInIfTable(string connection, MIB_IFTABLE* pIfTable)\n{\n\tfor (size_t i{}; i < pIfTable->dwNumEntries; i++)\n\t{\n\t\tstring descr = (const char*)pIfTable->table[i].bDescr;\n\t\tif (descr == connection)\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\nint CAdapterCommon::FindConnectionInIfTableFuzzy(string connection, MIB_IFTABLE* pIfTable)\n{\n\tfor (size_t i{}; i < pIfTable->dwNumEntries; i++)\n\t{\n\t\tstring descr = (const char*)pIfTable->table[i].bDescr;\n\t\tsize_t index;\n\t\t//在较长的字符串里查找较短的字符串\n\t\tif (descr.size() >= connection.size())\n\t\t\tindex = descr.find(connection);\n\t\telse\n\t\t\tindex = connection.find(descr);\n\t\tif (index != wstring::npos)\n\t\t\treturn i;\n\t}\n\t//如果还是没有找到，则使用字符串匹配算法查找\n\tdouble max_degree{};\n\tint best_index{};\n\tfor (size_t i{}; i < pIfTable->dwNumEntries; i++)\n\t{\n\t\tstring descr = (const char*)pIfTable->table[i].bDescr;\n\t\tdouble degree = CCommon::StringSimilarDegree_LD(descr, connection);\n\t\tif (degree > max_degree)\n\t\t{\n\t\t\tmax_degree = degree;\n\t\t\tbest_index = i;\n\t\t}\n\t}\n\treturn best_index;\n}\n"
  },
  {
    "path": "TrafficMonitor/AdapterCommon.h",
    "content": "#pragma once\n#include \"Common.h\"\n\n//һϢ\nstruct NetWorkConection\n{\n\tint index{};\t\t\t//MIB_IFTABLEе\n\tstring description;\t\t//ȡGetAdapterInfo\n\tstring description_2;\t//ȡGetIfTable\n\tunsigned int in_bytes;\t//ʼʱѽֽ\n\tunsigned int out_bytes;\t//ʼʱѷֽ\n\twstring ip_address{ L\"-.-.-.-\" };\t//IPַ\n\twstring subnet_mask{ L\"-.-.-.-\" };\t//\n\twstring default_gateway{ L\"-.-.-.-\" };\t//Ĭ\n};\n\nclass CAdapterCommon\n{\npublic:\n\tCAdapterCommon();\n\t~CAdapterCommon();\n\n\t//ȡбIPַ롢ĬϢ\n\tstatic void GetAdapterInfo(vector<NetWorkConection>& adapters);\n\n\t//ˢбеIPַ롢ĬϢ\n\tstatic void RefreshIpAddress(vector<NetWorkConection>& adapters);\n\n\t//ȡбÿӵMIB_IFTABLEеʼʱѽ/ֽϢ\n\tstatic void GetIfTableInfo(vector<NetWorkConection>& adapters, MIB_IFTABLE* pIfTable);\n\n\t//ֱӽMIB_IFTABLEеӵadapters\n\tstatic void GetAllIfTableInfo(vector<NetWorkConection>& adapters, MIB_IFTABLE* pIfTable);\nprivate:\n\t//һжǷIfTableбҲ򷵻-1\n\tstatic int FindConnectionInIfTable(string connection, MIB_IFTABLE* pIfTable);\n\n\t//һжǷIfTableбҲ򷵻-1ֻҪƥ\n\tstatic int FindConnectionInIfTableFuzzy(string connection, MIB_IFTABLE* pIfTable);\n};\n\n"
  },
  {
    "path": "TrafficMonitor/AppAlreadyRuningDlg.cpp",
    "content": "﻿// AppAlreadyRuningDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"AppAlreadyRuningDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// CAppAlreadyRuningDlg 对话框\n\nIMPLEMENT_DYNAMIC(CAppAlreadyRuningDlg, CBaseDialog)\n\nCAppAlreadyRuningDlg::CAppAlreadyRuningDlg(HWND handel, CWnd* pParent /*=nullptr*/)\n    : CBaseDialog(IDD_APP_ALREAD_RUNING_DIALOG, pParent), m_handle(handel)\n{\n\n}\n\nCAppAlreadyRuningDlg::~CAppAlreadyRuningDlg()\n{\n}\n\nvoid CAppAlreadyRuningDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n}\n\nCString CAppAlreadyRuningDlg::GetDialogName() const\n{\n    return _T(\"AppAlreadyRuningDlg\");\n}\n\n\nBEGIN_MESSAGE_MAP(CAppAlreadyRuningDlg, CBaseDialog)\n    ON_BN_CLICKED(IDC_EXIT_INST_BUTTON, &CAppAlreadyRuningDlg::OnBnClickedExitInstButton)\n    ON_BN_CLICKED(IDC_OPEN_SETTINGS_BUTTON, &CAppAlreadyRuningDlg::OnBnClickedOpenSettingsButton)\n    ON_BN_CLICKED(IDC_SHOW_HIDE_MAIN_WINDOW_BUTTON, &CAppAlreadyRuningDlg::OnBnClickedShowHideMainWindowButton)\n    ON_BN_CLICKED(IDC_SHOW_HIDE_TASKBAR_WINDOW_BUTTON, &CAppAlreadyRuningDlg::OnBnClickedShowHideTaskbarWindowButton)\nEND_MESSAGE_MAP()\n\n\n// CAppAlreadyRuningDlg 消息处理程序\n\n\nBOOL CAppAlreadyRuningDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), FALSE);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CAppAlreadyRuningDlg::OnBnClickedExitInstButton()\n{\n    ::PostMessage(m_handle, WM_COMMAND, ID_APP_EXIT, 0);\n}\n\n\nvoid CAppAlreadyRuningDlg::OnBnClickedOpenSettingsButton()\n{\n    ::PostMessage(m_handle, WM_COMMAND, ID_OPTIONS, 0);\n}\n\n\nvoid CAppAlreadyRuningDlg::OnBnClickedShowHideMainWindowButton()\n{\n    ::PostMessage(m_handle, WM_COMMAND, ID_SHOW_MAIN_WND, 0);\n}\n\n\nvoid CAppAlreadyRuningDlg::OnBnClickedShowHideTaskbarWindowButton()\n{\n    ::PostMessage(m_handle, WM_COMMAND, ID_SHOW_TASK_BAR_WND, 0);\n}\n"
  },
  {
    "path": "TrafficMonitor/AppAlreadyRuningDlg.h",
    "content": "﻿#pragma once\n#include \"BaseDialog.h\"\n\n// CAppAlreadyRuningDlg 对话框\n\nclass CAppAlreadyRuningDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CAppAlreadyRuningDlg)\n\npublic:\n    CAppAlreadyRuningDlg(HWND handel, CWnd* pParent = nullptr);   // 标准构造函数\n    virtual ~CAppAlreadyRuningDlg();\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_APP_ALREAD_RUNING_DIALOG };\n#endif\n\nprivate:\n    HWND m_handle{};        //正在运行的TrafficMonitor进程主窗口的句柄\n\nprotected:\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    virtual CString GetDialogName() const override;\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    afx_msg void OnBnClickedExitInstButton();\n    afx_msg void OnBnClickedOpenSettingsButton();\n    afx_msg void OnBnClickedShowHideMainWindowButton();\n    afx_msg void OnBnClickedShowHideTaskbarWindowButton();\n};\n"
  },
  {
    "path": "TrafficMonitor/BaseDialog.cpp",
    "content": "﻿// BaseDialog.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"BaseDialog.h\"\n#include \"afxdialogex.h\"\n#include \"IniHelper.h\"\n#include \"TrafficMonitor.h\"\n#include \"TrafficMonitorDlg.h\"\n\n// CBaseDialog 对话框\nstd::map<CString, HWND> CBaseDialog::m_unique_hwnd;\n\nIMPLEMENT_DYNAMIC(CBaseDialog, CDialog)\n\nCBaseDialog::CBaseDialog(UINT nIDTemplate, CWnd* pParent /*=NULL*/)\n    : CDialog(nIDTemplate, pParent)\n{\n    m_nDialogID = nIDTemplate;\n    m_dpi = theApp.GetDpi();\n}\n\nCBaseDialog::~CBaseDialog()\n{\n}\n\nvoid CBaseDialog::SetBackgroundColor(COLORREF color, BOOL bRepaint)\n{\n    if (m_brBkgr.GetSafeHandle() != NULL)\n    {\n        m_brBkgr.DeleteObject();\n    }\n\n    if (color != (COLORREF)-1)\n    {\n        m_brBkgr.CreateSolidBrush(color);\n    }\n\n    if (bRepaint && GetSafeHwnd() != NULL)\n    {\n        Invalidate();\n        UpdateWindow();\n    }\n}\n\nvoid CBaseDialog::SetMinSize(int cx, int cy)\n{\n    m_min_size.cx = cx;\n    m_min_size.cy = cy;\n}\n\nHWND CBaseDialog::GetUniqueHandel(LPCTSTR dlg_name)\n{\n    return m_unique_hwnd[dlg_name];\n}\n\nconst std::map<CString, HWND>& CBaseDialog::AllUniqueHandels()\n{\n    return m_unique_hwnd;\n}\n\nbool CBaseDialog::IsAllDialogClosed()\n{\n    for (const auto& hwnd : m_unique_hwnd)\n    {\n        if (hwnd.second != nullptr)\n            return false;\n    }\n    return true;\n}\n\nvoid CBaseDialog::LoadConfig()\n{\n    if (!GetDialogName().IsEmpty() && m_remember_dlg_size)\n    {\n        CIniHelper ini{ theApp.m_config_path };\n        //载入窗口大小设置\n        m_window_size.cx = ini.GetInt(_T(\"window_size\"), GetDialogName() + _T(\"_width\"), -1);\n        m_window_size.cy = ini.GetInt(_T(\"window_size\"), GetDialogName() + _T(\"_height\"), -1);\n    }\n}\n\nvoid CBaseDialog::SaveConfig() const\n{\n    if (!GetDialogName().IsEmpty() && m_remember_dlg_size)\n    {\n        CIniHelper ini{ theApp.m_config_path };\n        //保存窗口大小设置\n        ini.WriteInt(_T(\"window_size\"), GetDialogName() + _T(\"_width\"), m_window_size.cx);\n        ini.WriteInt(_T(\"window_size\"), GetDialogName() + _T(\"_height\"), m_window_size.cy);\n        ini.Save();\n    }\n}\n\nvoid CBaseDialog::IterateControls(CWnd* pParent, std::function<void(CWnd*)> func)\n{\n    if (pParent == nullptr)\n        return;\n\n    // 获取第一个子控件\n    CWnd* pChild = pParent->GetWindow(GW_CHILD);\n\n    // 遍历所有子控件\n    while (pChild != nullptr)\n    {\n        func(pChild);\n\n        // 递归遍历子控件的子控件（处理嵌套控件）\n        IterateControls(pChild, func);\n\n        // 获取下一个兄弟控件\n        pChild = pChild->GetWindow(GW_HWNDNEXT);\n    }\n}\n\nvoid CBaseDialog::ReLoadLayoutResource()\n{\n    ASSERT(m_nDialogID);\n    CMFCDynamicLayout* pDynamicLayout = GetDynamicLayout();\n    if (pDynamicLayout)\n    {\n        HRSRC layoutRes = ::FindResourceW(NULL, MAKEINTRESOURCEW(m_nDialogID), RT_DIALOG_LAYOUT);\n        if (layoutRes)\n        {\n            HGLOBAL hResData = ::LoadResource(NULL, layoutRes);\n            if (hResData)\n            {\n                LPVOID layoutResData = ::LockResource(hResData);\n                DWORD layoutResSize = ::SizeofResource(NULL, layoutRes);\n                // std::wstring data(static_cast<wchar_t*>(layoutResData), layoutResSize / sizeof(wchar_t));\n                pDynamicLayout->LoadResource(this, layoutResData, layoutResSize);\n            }\n        }\n    }\n}\n\nint CBaseDialog::DPI(int pixel) const\n{\n    return m_dpi * pixel / 96;\n}\n\nCRect CBaseDialog::GetTextExtent(const CString& text)\n{\n    ASSERT(m_pDC != nullptr);   // m_pDC由OnInitDialog负责申请释放\n    if (m_pDC == nullptr)\n        return CRect();\n    if (text.IsEmpty())\n        return CRect();\n    CRect text_size;\n    m_pDC->DrawTextW(text, &text_size, DT_CALCRECT);    // 使用CDC::DrawTextW测量文本宽度（CDC::GetTextExtent是理论宽度，不准确）\n    return text_size;\n}\n\nvoid CBaseDialog::RepositionTextBasedControls(const vector<CtrlTextInfo>& items, CtrlTextInfo::Width center_min_width)\n{\n    ASSERT(m_pDC != nullptr);   // 此方法仅在InitializeControls期间可用\n    if (m_pDC == nullptr)\n        return;\n    int center_width = theApp.DPI(center_min_width);\n    std::map<int, std::pair<int, int>> col_info;\n    struct itemInfo\n    {\n        int col_index;\n        CWnd* p;\n        CRect rect;\n    };\n    vector<itemInfo> items_info;\n    int center_left{ 0 }, center_right{ INT_MAX };\n\n    for (const auto& item : items)\n    {\n        ASSERT(item.col_index != CtrlTextInfo::UN_USE);\n        ASSERT(item.id != 0);\n        // 获取所有列所需dx，以及左贴靠元素的右边缘center_left，右贴靠元素的左边缘center_right\n        CWnd* pItem = GetDlgItem(item.id);\n        if (pItem == nullptr)\n            continue;\n        CRect rect{};\n        pItem->GetWindowRect(&rect);\n        ScreenToClient(&rect);\n        CString text;\n        pItem->GetWindowTextW(text);\n        int dx = GetTextExtent(text).Width() + theApp.DPI(item.ext_width) - rect.Width();\n        if (dx < 0) dx = 0;                                     // 文字只增加控件宽度\n        if (col_info[item.col_index].first < dx)                // 取此列元素中宽度增长最多的\n            col_info[item.col_index].first = dx;\n        if (item.col_index < 0 && center_left < rect.right)\n            center_left = rect.right;\n        if (item.col_index > 0 && center_right > rect.left)\n            center_right = rect.left;\n        if (item.col_index == 0)    // col_index为0的控件可能有多个\n        {\n            if (center_left < rect.left)\n                center_left = rect.left;\n            if (center_right > rect.right)\n                center_right = rect.right;\n        }\n        items_info.emplace_back(itemInfo{ item.col_index, pItem, std::move(rect) });\n    }\n\n    if (center_right == INT_MAX)    // 如果控件全部都是左贴靠的那么以窗口右边缘作为剩余空间的右边缘\n    {\n        CRect dlg_rect{};\n        GetClientRect(&dlg_rect);\n        center_right = dlg_rect.Width();\n    }\n    // 此断言触发说明资源文件中的原始布局没有给中间控件/空闲空间留够宽度\n    ASSERT(center_right - center_left >= center_width);\n    int dx_sum_left{}, dx_sum_right{};\n    // 因为同一col_index可以有多个控件&没有要求顺序所以控件的最终位置必须可以无状态的计算出来\n    for (auto& a : col_info)\n    {\n        if (a.first < 0)\n        {\n            a.second.second = dx_sum_left;    // 存储此列之前控件的总dx，即此列控件的右移距离\n            dx_sum_left += a.second.first;\n        }\n        else if (a.first > 0)\n        {\n            a.second.second = dx_sum_right;\n            dx_sum_right += a.second.first;\n        }\n    }\n    float scale{ 1.0f };\n    if (center_right - center_left - dx_sum_left - dx_sum_right < center_width)\n    {\n        // ASSERT(false);\n        // 现在加载的文本使此行的中间控件/空闲空间被挤压的太小\n        // 这需要重新设计窗口控件排布以适应当前翻译长度，这里先简单的把缺少的空间分摊给各dx\n        scale = static_cast<float>(center_right - center_left - center_width) / (dx_sum_left + dx_sum_right);\n        dx_sum_left = static_cast<int>(dx_sum_left * scale + 0.5f);\n        dx_sum_right = static_cast<int>(dx_sum_right * scale + 0.5f);\n    }\n    for (const auto& item : items_info)\n    {\n        const auto& rect = item.rect;\n        int dx = static_cast<int>(col_info[item.col_index].first * scale + 0.5f);\n        int sum_dx = static_cast<int>(col_info[item.col_index].second * scale + 0.5f);\n        if (item.col_index < 0)\n            item.p->SetWindowPos(nullptr, rect.left + sum_dx, rect.top, rect.Width() + dx, rect.Height(), SWP_NOZORDER);\n        else if (item.col_index > 0)\n            item.p->SetWindowPos(nullptr, rect.left + sum_dx - dx_sum_right, rect.top, rect.Width() + dx, rect.Height(), SWP_NOZORDER);\n        else if (item.col_index == 0)\n            item.p->SetWindowPos(nullptr, rect.left + dx_sum_left, rect.top, rect.Width() - dx_sum_left - dx_sum_right, rect.Height(), SWP_NOZORDER);\n    }\n}\n\nvoid CBaseDialog::EnableDlgCtrl(UINT id, bool enable)\n{\n    CWnd* pWnd = GetDlgItem(id);\n    if (pWnd != nullptr)\n        pWnd->EnableWindow(enable);\n}\n\nvoid CBaseDialog::SetButtonIcon(UINT id, HICON hIcon)\n{\n    CWnd* dlgItem = GetDlgItem(id);\n    CButton* btn = static_cast<CButton*>(dlgItem);\n    if (btn != nullptr)\n        btn->SetIcon(hIcon);\n}\n\nCRect CBaseDialog::GetControlRect(CWnd* pCtrl)\n{\n    if (pCtrl != nullptr)\n    {\n        CRect rect;\n        pCtrl->GetWindowRect(rect);\n        ScreenToClient(rect);\n        return rect;\n    }\n    return CRect();\n}\n\nCRect CBaseDialog::GetControlRect(UINT id)\n{\n    CWnd* pCtrl = GetDlgItem(id);\n    return GetControlRect(pCtrl);\n}\n\nvoid CBaseDialog::IterateControls(std::function<void(CWnd*)> func)\n{\n    func(this);\n    IterateControls(this, func);\n}\n\nvoid CBaseDialog::DoDataExchange(CDataExchange* pDX)\n{\n    CDialog::DoDataExchange(pDX);\n}\n\n\nBEGIN_MESSAGE_MAP(CBaseDialog, CDialog)\n    ON_WM_DESTROY()\n    ON_WM_GETMINMAXINFO()\n    ON_WM_SIZE()\n    ON_WM_ERASEBKGND()\n    ON_WM_CTLCOLOR()\nEND_MESSAGE_MAP()\n\n\n// CBaseDialog 消息处理程序\n\n\nBOOL CBaseDialog::OnInitDialog()\n{\n    m_unique_hwnd[GetDialogName()] = m_hWnd;\n    CDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n\n    //初始化字体\n    CRect rect;\n    GetWindowRect(rect);\n    FontInfo font_info;\n    font_info.name = theApp.m_str_table.GetLanguageInfo().default_font_name.c_str();\n    font_info.size = 9;\n    UINT dpi_x{}, dpi_y{};\n    if (theApp.DPIFromRect(rect, &dpi_x, &dpi_y))\n        m_dpi = dpi_x;\n\n    font_info.Create(m_dlg_font, m_dpi);\n\n    //获取初始时窗口的大小\n    if (m_min_size.cx <= 0 || m_min_size.cy <= 0)\n    {\n        CRect rect;\n        GetWindowRect(rect);\n        m_min_size.cx = rect.Width() * 96 / theApp.GetDpi();\n        m_min_size.cy = rect.Height() * 96 / theApp.GetDpi();\n    }\n\n    //载入设置\n    LoadConfig();\n\n    SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);       //取消置顶\n\n    //处理对话框中的文本翻译 \n    IterateControls([&](CWnd* pWnd) {\n        //设置控件字体\n        if (m_dlg_font.GetSafeHandle() != NULL)\n            pWnd->SetFont(&m_dlg_font);\n        //获取控件文本\n        CString str;\n        pWnd->GetWindowText(str);\n        UINT id = pWnd->GetDlgCtrlID();\n        if (str.Left(4) == _T(\"TXT_\"))\n        {\n            //设置控件文本\n            const std::wstring& str_translated = theApp.m_str_table.LoadText(str.GetString());\n            if (!str_translated.empty())\n                pWnd->SetWindowTextW(str_translated.c_str());\n        }\n        //处理标准按钮\n        else\n        {\n            if (id == IDOK)\n                pWnd->SetWindowTextW(theApp.m_str_table.LoadText(TXT_OK).c_str());\n            else if (id == IDCANCEL)\n                pWnd->SetWindowTextW(theApp.m_str_table.LoadText(TXT_CANCEL).c_str());\n            else if (id == IDCLOSE)\n                pWnd->SetWindowTextW(theApp.m_str_table.LoadText(TXT_CLOSE).c_str());\n        }\n    });\n\n    // 在还原窗口大小之前（当前窗口状态与资源一致），派生类执行控件文本初始化及调整控件排布\n    // 与实际窗口大小相关的初始化（比如表格列宽）应在派生类的OnInitDialog进行\n    m_pDC = GetDC();\n    m_pDC->SelectObject(&m_dlg_font);\n    bool rtn = InitializeControls();\n    ReleaseDC(m_pDC);\n    m_pDC = nullptr;\n    // 如果更改了控件排布那么应当返回true以向布局管理器应用控件调整（重新加载动态布局设置）\n    if (rtn)\n        ReLoadLayoutResource();\n\n\n    //初始化窗口大小\n    if (m_window_size.cx > 0 && m_window_size.cy > 0)\n    {\n        SetWindowPos(nullptr, 0, 0, m_window_size.cx, m_window_size.cy, SWP_NOZORDER | SWP_NOMOVE);\n    }\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CBaseDialog::OnDestroy()\n{\n    CDialog::OnDestroy();\n\n    // TODO: 在此处添加消息处理程序代码\n    m_unique_hwnd[GetDialogName()] = NULL;\n    SaveConfig();\n\n    //当所有对话框关闭时重新设置主窗口置顶\n    CTrafficMonitorDlg* pDlg = dynamic_cast<CTrafficMonitorDlg*>(theApp.m_pMainWnd);\n    if (pDlg != nullptr && IsAllDialogClosed())\n        pDlg->SetAlwaysOnTop();\n}\n\n\nvoid CBaseDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    //限制窗口最小大小\n    lpMMI->ptMinTrackSize.x = theApp.DPI(m_min_size.cx);\t\t//设置最小宽度\n    lpMMI->ptMinTrackSize.y = theApp.DPI(m_min_size.cy);\t\t//设置最小高度\n\n    CDialog::OnGetMinMaxInfo(lpMMI);\n}\n\n\nvoid CBaseDialog::OnSize(UINT nType, int cx, int cy)\n{\n    CDialog::OnSize(nType, cx, cy);\n\n    // TODO: 在此处添加消息处理程序代码\n    if (nType != SIZE_MAXIMIZED && nType != SIZE_MINIMIZED)\n    {\n        //m_window_width = cx;\n        //m_window_hight = cy;\n        CRect rect;\n        GetWindowRect(&rect);\n        m_window_size.cx = rect.Width();\n        m_window_size.cy = rect.Height();\n    }\n\n}\n\n\nINT_PTR CBaseDialog::DoModal()\n{\n    HWND unique_hwnd{ m_unique_hwnd[GetDialogName()] };\n    if (unique_hwnd != NULL && !GetDialogName().IsEmpty())      ///如果对话框已存在，则显示已存在的对话框\n    {\n        ::ShowWindow(unique_hwnd, SW_RESTORE);\n        ::SetForegroundWindow(unique_hwnd);\n        return 0;\n    }\n    return CDialog::DoModal();\n}\n\n\nBOOL CBaseDialog::OnEraseBkgnd(CDC* pDC)\n{\n    // 修改窗口背景（CDialogEx）\n    if (m_brBkgr.GetSafeHandle() != NULL)\n    {\n        ASSERT_VALID(pDC);\n        CRect rectClient;\n        GetClientRect(rectClient);\n        pDC->FillRect(rectClient, &m_brBkgr);\n        return TRUE;\n    }\n    return CDialog::OnEraseBkgnd(pDC);\n}\n\n\nHBRUSH CBaseDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)\n{\n    // 修改窗口背景（CDialogEx）\n    if (m_brBkgr.GetSafeHandle() != NULL)\n    {\n#define AFX_MAX_CLASS_NAME 255\n#define AFX_STATIC_CLASS _T(\"Static\")\n#define AFX_BUTTON_CLASS _T(\"Button\")\n#define AFX_SLIDER_CLASS _T(\"msctls_trackbar32\")    // 滑动条控件CSliderCtrl及其派生类\n#define AFX_SYSLINK_CLASS _T(\"SysLink\")             // 超链接控件CSysLink及其派生类\n\n        if (nCtlColor == CTLCOLOR_STATIC)\n        {\n            TCHAR lpszClassName[AFX_MAX_CLASS_NAME + 1];\n\n            ::GetClassName(pWnd->GetSafeHwnd(), lpszClassName, AFX_MAX_CLASS_NAME);\n            CString strClass = lpszClassName;\n\n            if (strClass == AFX_BUTTON_CLASS || strClass == AFX_STATIC_CLASS || strClass == AFX_SLIDER_CLASS || strClass == AFX_SYSLINK_CLASS)\n            {\n                pDC->SetBkMode(TRANSPARENT);\n\n                if (m_brBkgr.GetSafeHandle() != NULL && IsAppThemed())\n                {\n                    return (HBRUSH)m_brBkgr.GetSafeHandle();\n                }\n                else\n                {\n                    return (HBRUSH)::GetStockObject(HOLLOW_BRUSH);\n                }\n            }\n        }\n    }\n\n    return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);\n}\n"
  },
  {
    "path": "TrafficMonitor/BaseDialog.h",
    "content": "﻿#pragma once\n#include <functional>\n\n// CBaseDialog 对话框\n//用于实现记住对话框大小\n//并将窗口初始大小设置为最小大小\n\nclass CBaseDialog : public CDialog\n{\n    DECLARE_DYNAMIC(CBaseDialog)\n\npublic:\n    CBaseDialog(UINT nIDTemplate, CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~CBaseDialog();\n\n    // 复制自CDialogEx，与其功能相同（新增滑动条控件和超链接控件的处理）\n    void SetBackgroundColor(COLORREF color, BOOL bRepaint = TRUE);\n\n    // 对话框数据\n    //#ifdef AFX_DESIGN_TIME\n    //\tenum { IDD = IDD_BASEDIALOG };\n    //#endif\n\n    void SetMinSize(int cx, int cy);\t\t//设置窗口的最小大小，如果未设置，则使用窗口的初始大小作为最小大小\n    static HWND GetUniqueHandel(LPCTSTR dlg_name);          //获指定窗口唯一的句柄\n    static const std::map<CString, HWND>& AllUniqueHandels();   //获取所有窗口的句柄\n    static bool IsAllDialogClosed();\n\nprivate:\n    void LoadConfig();\n    void SaveConfig() const;\n    void IterateControls(CWnd* pParent, std::function<void(CWnd*)> func);\n    // 重新应用布局管理器参数，这会使控件的基础大小/位置以当前为准\n    void ReLoadLayoutResource();\n\nprivate:\n    UINT m_nDialogID;                                   // 成员变量用于保存资源 ID\n    CSize m_min_size{};     //窗口的最小大小（以 96dpi 的大小保存）\n    CSize m_window_size{ -1, -1 };\n    CBrush m_brBkgr;\n    CDC* m_pDC = nullptr;                               // InitializeControls期间有效，用于测量文本长度\n    static std::map<CString, HWND> m_unique_hwnd;       //针对每一个基类的唯一的窗口句柄\n    bool m_remember_dlg_size{ true };                   //是否记住窗口大小（当此标志为true且GetDialogName返回字符串不为空时会记住窗口大小）\n    CFont m_dlg_font;\n    int m_dpi;              //窗口自己的DPI\n\nprotected:\n    int DPI(int pixel) const;\n\n    // 仅在InitializeControls期间可用，测量控件文本长度\n    CRect GetTextExtent(const CString& text);\n\n    struct CtrlTextInfo\n    {\n        // 这里的枚举作为能够类型检查的int使用\n        // Col具体值大小无意义，只表示列之间的相对顺序以及哪些控件同一列，实际上没有数量限制，需要的话可以增加\n        enum Col { L4 = -4, L3 = -3, L2 = -2, L1 = -1, C0 = 0, R1 = 1, R2 = 2, R3 = 3, R4 = 4, UN_USE = 100 };\n        // 控件除去文本后剩余的宽度。\n        // Static静态文本推荐W0，按钮因为可能有图标推荐W32\n        enum Width { W_50 = -50, W0 = 0, W16 = 16, W24 = 24, W32 = 32, W40 = 40, W60 = 60, W64 = 64, W96 = 96, W128 = 128, W256 = 256 };\n\n        Col col_index{ UN_USE };    // 指示控件的位置 ，从左向右递增，小于0左贴靠，大于0右贴靠，等于0使用剩余空间\n        UINT id{ 0 };               // 控件ID\n        Width ext_width{ W0 };      // 控件宽度至少需要“文字宽度+ext_width”（内部会执行DPI转换 theApp.DPI(ext_width)）\n    };\n    // 仅在InitializeControls期间可用，根据文本长度重排控件，不会进行任何垂直方向调整，不会改变控件间距\n    // 只会增加控件宽度故推荐在资源中设置更小的宽度，使用此方法调整到合适的状态\n    // 优先保证中间的剩余宽度（或col_index为0的控件宽度）至少为center_min_width\n    // 空间不足时其他控件文字会无法完全显示（此时应重新设计窗口）（此方法仅适用于文字不可能太长的情况）\n    void RepositionTextBasedControls(const vector<CtrlTextInfo>& items, CtrlTextInfo::Width center_min_width = CtrlTextInfo::W16);\n    \n    // 由CBaseDialog::OnInitDialog在还原配置中窗口大小前调用\n    // 派生类执行部分控件初始化，比如设置控件文本，重排控件RepositionTextBasedControls\n    // 返回true会重新应用布局管理器参数，这会使控件动态布局管理器的基础大小/位置以当前为准\n    // 与实际窗口大小相关的初始化（比如表格列宽）应在派生类的OnInitDialog进行\n    virtual bool InitializeControls() { return false; };\n\n    virtual CString GetDialogName() const { return CString(); }\n    void EnableDlgCtrl(UINT id, bool enable);\n    void SetButtonIcon(UINT id, HICON hIcon);\n    void SetRememberDlgSize(bool enable) { m_remember_dlg_size = enable; }\n    CRect GetControlRect(CWnd* pCtrl);\n    CRect GetControlRect(UINT id);\n\n    //遍历所有子控件\n    void IterateControls(std::function<void(CWnd*)> func);\n\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    afx_msg void OnDestroy();\n    afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);\n    afx_msg void OnSize(UINT nType, int cx, int cy);\n    virtual INT_PTR DoModal();\n    afx_msg BOOL OnEraseBkgnd(CDC* pDC);\n    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);\n};\n"
  },
  {
    "path": "TrafficMonitor/CAutoAdaptSettingsDlg.cpp",
    "content": "﻿// CAutoAdaptSettingsDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"CAutoAdaptSettingsDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// CAutoAdaptSettingsDlg 对话框\n\nIMPLEMENT_DYNAMIC(CAutoAdaptSettingsDlg, CBaseDialog)\n\nCAutoAdaptSettingsDlg::CAutoAdaptSettingsDlg(TaskBarSettingData& data, CWnd* pParent /*=nullptr*/)\n\t: CBaseDialog(IDD_ATUO_ADAPT_SETTING_DIALOG, pParent), m_data(data)\n{\n\n}\n\nCAutoAdaptSettingsDlg::~CAutoAdaptSettingsDlg()\n{\n}\n\nvoid CAutoAdaptSettingsDlg::InitComboBox(CComboBox& combo_box, int style_sel)\n{\n\tfor (int i = 0; i < TASKBAR_DEFAULT_STYLE_NUM; i++)\n\t\tcombo_box.AddString(CCommon::LoadText(IDS_PRESET, std::to_wstring(i + 1).c_str()));\n\tif (style_sel >= 0 && style_sel < TASKBAR_DEFAULT_STYLE_NUM)\n\t\tcombo_box.SetCurSel(style_sel);\n\telse\n\t\tcombo_box.SetCurSel(0);\n}\n\nint CAutoAdaptSettingsDlg::GetComboBoxSel(const CComboBox& combo_box)\n{\n\tint sel = combo_box.GetCurSel();\n\tif (sel >= 0 && sel < TASKBAR_DEFAULT_STYLE_NUM)\n\t\treturn sel;\n\telse\n\t\treturn 0;\n}\n\nvoid CAutoAdaptSettingsDlg::DoDataExchange(CDataExchange* pDX)\n{\n\tCBaseDialog::DoDataExchange(pDX);\n\tDDX_Control(pDX, IDC_DARK_MODE_DEFAULT_STYLE_COMBO, m_dark_mode_default_style_combo);\n\tDDX_Control(pDX, IDC_LIGHT_MODE_DEFAULT_STYLE_COMBO, m_light_mode_default_style_combo);\n}\n\nCString CAutoAdaptSettingsDlg::GetDialogName() const\n{\n    return _T(\"AutoAdaptSettingsDlg\");\n}\n\nbool CAutoAdaptSettingsDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_DARK_MODE_STATIC },\n        { CtrlTextInfo::C0, IDC_DARK_MODE_DEFAULT_STYLE_COMBO },\n        { CtrlTextInfo::L1, IDC_LIGHT_MODE_STATIC },\n        { CtrlTextInfo::C0, IDC_LIGHT_MODE_DEFAULT_STYLE_COMBO }\n    });\n    return true;\n}\n\n\nBEGIN_MESSAGE_MAP(CAutoAdaptSettingsDlg, CBaseDialog)\nEND_MESSAGE_MAP()\n\n\n// CAutoAdaptSettingsDlg 消息处理程序\n\n\nBOOL CAutoAdaptSettingsDlg::OnInitDialog()\n{\n\tCBaseDialog::OnInitDialog();\n\n\t// TODO:  在此添加额外的初始化\n\tInitComboBox(m_dark_mode_default_style_combo, m_data.dark_default_style);\n\tInitComboBox(m_light_mode_default_style_combo, m_data.light_default_style);\n    CheckDlgButton(IDC_AUTO_SAVE_TO_PRESET_CHECK, m_data.auto_save_taskbar_color_settings_to_preset);\n\n    m_toolTip.Create(this);\n    m_toolTip.SetMaxTipWidth(theApp.DPI(300));\n    m_toolTip.AddTool(GetDlgItem(IDC_AUTO_SAVE_TO_PRESET_CHECK), CCommon::LoadText(IDS_AUTO_SAVE_TO_PRESET_TIP));\n\n\treturn TRUE;  // return TRUE unless you set the focus to a control\n\t\t\t\t  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CAutoAdaptSettingsDlg::OnOK()\n{\n\t// TODO: 在此添加专用代码和/或调用基类\n\n\t//获取控件中的设置\n\tm_data.dark_default_style = GetComboBoxSel(m_dark_mode_default_style_combo);\n\tm_data.light_default_style = GetComboBoxSel(m_light_mode_default_style_combo);\n    m_data.auto_save_taskbar_color_settings_to_preset = (IsDlgButtonChecked(IDC_AUTO_SAVE_TO_PRESET_CHECK) != 0);\n\n\tCBaseDialog::OnOK();\n}\n\n\nBOOL CAutoAdaptSettingsDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    if (pMsg->message == WM_MOUSEMOVE)\n        m_toolTip.RelayEvent(pMsg);\n\n    return CBaseDialog::PreTranslateMessage(pMsg);\n}\n"
  },
  {
    "path": "TrafficMonitor/CAutoAdaptSettingsDlg.h",
    "content": "﻿#pragma once\n#include \"BaseDialog.h\"\n\n// CAutoAdaptSettingsDlg 对话框\n\nclass CAutoAdaptSettingsDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CAutoAdaptSettingsDlg)\n\npublic:\n\tCAutoAdaptSettingsDlg(TaskBarSettingData& data, CWnd* pParent = nullptr);   // 标准构造函数\n\tvirtual ~CAutoAdaptSettingsDlg();\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_ATUO_ADAPT_SETTING_DIALOG };\n#endif\n\nprivate:\n\tCComboBox m_dark_mode_default_style_combo;\n\tCComboBox m_light_mode_default_style_combo;\n\tTaskBarSettingData& m_data;\n    CToolTipCtrl m_toolTip;\n\nprivate:\n\tvoid InitComboBox(CComboBox& combo_box, int style_sel);\n\tint GetComboBoxSel(const CComboBox& combo_box);\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    virtual CString GetDialogName() const override;\n    virtual bool InitializeControls() override;\n\n\tDECLARE_MESSAGE_MAP()\npublic:\n\tvirtual BOOL OnInitDialog();\n\tvirtual void OnOK();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n};\n"
  },
  {
    "path": "TrafficMonitor/CMFCColorDialogEx.cpp",
    "content": "﻿// CMFCColorDialogEx.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"CMFCColorDialogEx.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n\n// CMFCColorDialogEx\n\n//IMPLEMENT_DYNAMIC(CMFCColorDialogEx, CMFCColorDialog)\n\nCMFCColorDialogEx::CMFCColorDialogEx(COLORREF clrInit, DWORD dwFlags, CWnd* pParentWnd, HPALETTE hPal)\n\t:CMFCColorDialog(clrInit, dwFlags, pParentWnd, hPal)\n{\n\n}\n\nCMFCColorDialogEx::~CMFCColorDialogEx()\n{\n}\n\n\nBEGIN_MESSAGE_MAP(CMFCColorDialogEx, CMFCColorDialog)\nEND_MESSAGE_MAP()\n\n\n\n// CMFCColorDialogEx 消息处理程序\n\nBOOL CMFCColorDialogEx::OnInitDialog()\n{\n\tCMFCColorDialog::OnInitDialog();\n\n\t// TODO:  在此添加额外的初始化\n\n\t//初始化字体\n\tCRect rect;\n\tGetWindowRect(rect);\n\tFontInfo font_info;\n\tfont_info.name = theApp.m_str_table.GetLanguageInfo().default_font_name.c_str();\n\tfont_info.size = 9;\n\tUINT dpi_x{}, dpi_y{};\n\tint dpi = theApp.GetDpi();\n\tif (theApp.DPIFromRect(rect, &dpi_x, &dpi_y))\n\t\tdpi = dpi_x;\n\tfont_info.Create(m_dlg_font, dpi);\n\n\tCCommon::SetDialogFont(this, &m_dlg_font);\n\n\tCWnd* pPropSheet = m_pColourSheetOne->GetParent();\n\tif (pPropSheet != nullptr)\n\t\tCCommon::SetDialogFont(pPropSheet, &m_dlg_font);\n\n\treturn TRUE;  // return TRUE unless you set the focus to a control\n\t\t\t\t  // 异常: OCX 属性页应返回 FALSE\n}\n\n"
  },
  {
    "path": "TrafficMonitor/CMFCColorDialogEx.h",
    "content": "﻿#pragma once\n\n\n// CMFCColorDialogEx\n\nclass CMFCColorDialogEx : public CMFCColorDialog\n{\n\t//DECLARE_DYNAMIC(CMFCColorDialogEx)\n\npublic:\n\tCMFCColorDialogEx(COLORREF clrInit = 0, DWORD dwFlags = 0 /* reserved */, CWnd* pParentWnd = NULL, HPALETTE hPal = NULL);\n\tvirtual ~CMFCColorDialogEx();\n\nprotected:\n\tCFont m_dlg_font;\n\nprotected:\n\tDECLARE_MESSAGE_MAP()\n\n\tvirtual BOOL OnInitDialog();\n\n};\n\n\n"
  },
  {
    "path": "TrafficMonitor/CSkinPreviewView.cpp",
    "content": "﻿// CSkinPreviewView.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"CSkinPreviewView.h\"\n\n\n// CSkinPreviewView\n\nIMPLEMENT_DYNCREATE(CSkinPreviewView, CScrollView)\n\nCSkinPreviewView::CSkinPreviewView()\n{\n\n}\n\nCSkinPreviewView::~CSkinPreviewView()\n{\n}\n\n\nBEGIN_MESSAGE_MAP(CSkinPreviewView, CScrollView)\nEND_MESSAGE_MAP()\n\n\n// CSkinPreviewView 绘图\n\nvoid CSkinPreviewView::OnInitialUpdate()\n{\n\tCScrollView::OnInitialUpdate();\n\n\tCSize sizeTotal;\n\t// TODO:  计算此视图的合计大小\n\tm_size.cx = 0;\n\tm_size.cy = 0;\n\tSetScrollSizes(MM_TEXT, m_size);\n\n\n}\n\nvoid CSkinPreviewView::OnDraw(CDC* pDC)\n{\n    CDrawCommon drawer;\n    drawer.Create(pDC, nullptr);\n    CRect view_rect;\n    GetClientRect(view_rect);\n    view_rect.right = (std::max)(view_rect.Width(), static_cast<int>(m_size.cx));\n    view_rect.bottom = (std::max)(view_rect.Height(), static_cast<int>(m_size.cy));\n\n    //如果皮肤是png格式，绘制10x10的棋盘背景\n    if (m_skin_data->IsPNG())\n    {\n        int grid_size = theApp.DPI(10);\n\n        // 检查画布大小\n        int rows = view_rect.Height() / grid_size + 1;  // 行数\n        int cols = view_rect.Width() / grid_size + 1;  // 列数\n\n        // 遍历每个网格\n        for (int row = 0; row < rows; ++row)\n        {\n            for (int col = 0; col < cols; ++col)\n            {\n                // 计算当前网格的矩形区域\n                CRect rect(col * grid_size, row * grid_size,\n                    (col + 1) * grid_size, (row + 1) * grid_size);\n\n                // 判断当前网格颜色（交替填充）\n                COLORREF color = ((row + col) % 2 == 0) ? RGB(204, 204, 204) : RGB(254, 254, 254);\n\n                // 填充矩形\n                drawer.FillRect(rect, color);\n            }\n        }\n    }\n    //绘制纯色背景\n    else\n    {\n        drawer.FillRect(view_rect, GetSysColor(COLOR_WINDOW));\n    }\n\n    //绘制预览图\n    CRect draw_rect(CPoint(0, 0), m_size);\n    m_skin_data->DrawPreview(pDC, draw_rect);\n}\n\n\n// CSkinPreviewView 诊断\n\n//#ifdef _DEBUG\n//void CSkinPreviewView::AssertValid() const\n//{\n//\tCScrollView::AssertValid();\n//}\n\n//#ifndef _WIN32_WCE\n//void CSkinPreviewView::Dump(CDumpContext& dc) const\n//{\n//\tCScrollView::Dump(dc);\n//}\n//#endif\n//#endif //_DEBUG\n\nvoid CSkinPreviewView::InitialUpdate()\n{\n\tOnInitialUpdate();\n}\nvoid CSkinPreviewView::SetSize(int width, int hight)\n{\n\tm_size = CSize(width, hight);\n\tSetScrollSizes(MM_TEXT, m_size);\n}\n\n// CSkinPreviewView 消息处理程序\n"
  },
  {
    "path": "TrafficMonitor/CSkinPreviewView.h",
    "content": "﻿#pragma once\n#include \"DrawCommon.h\"\n#include \"SkinFile.h\"\n\n\n// CSkinPreviewView 视图\n\n\nclass CSkinPreviewView : public CScrollView\n{\n\tDECLARE_DYNCREATE(CSkinPreviewView)\n\nprotected:\n\tCSkinPreviewView();           // 动态创建所使用的受保护的构造函数\n\tvirtual ~CSkinPreviewView();\n\npublic:\n//#ifdef _DEBUG\n//\tvirtual void AssertValid() const;\n//#ifndef _WIN32_WCE\n//\tvirtual void Dump(CDumpContext& dc) const;\n//#endif\n//#endif\n\n//成员函数\npublic:\n\tvoid InitialUpdate();\n\tvoid SetSize(int width, int hight);\n\tvoid SetSkinData(CSkinFile* skin_data) { m_skin_data = skin_data; }\n\n\t//成员变量\nprotected:\n\tCSize m_size;\n\tCPoint m_start_point;\t\t\t//绘图的起始位置\n\n    CSkinFile* m_skin_data;\n\nprotected:\n\tvirtual void OnDraw(CDC* pDC);      // 重写以绘制该视图\n\tvirtual void OnInitialUpdate();     // 构造后的第一次\n\n\tDECLARE_MESSAGE_MAP()\n};\n\n\n"
  },
  {
    "path": "TrafficMonitor/CTabCtrlEx.cpp",
    "content": "﻿// CTabCtrlEx.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"CTabCtrlEx.h\"\n\n\n// CTabCtrlEx\n\nIMPLEMENT_DYNAMIC(CTabCtrlEx, CTabCtrl)\n\nCTabCtrlEx::CTabCtrlEx()\n{\n\n}\n\nCTabCtrlEx::~CTabCtrlEx()\n{\n}\n\nvoid CTabCtrlEx::AddWindow(CWnd* pWnd, LPCTSTR lable_text)\n{\n\tif (pWnd == nullptr || pWnd->GetSafeHwnd() == NULL)\n\t\treturn;\n\n    InsertItem(m_tab_list.size(), lable_text, m_tab_list.size());\n\n\tpWnd->SetParent(this);\n\tpWnd->MoveWindow(m_tab_rect);\n\n\tm_tab_list.push_back(pWnd);\n}\n\nvoid CTabCtrlEx::SetCurTab(int index)\n{\n    if (index < 0 || index >= static_cast<int>(m_tab_list.size()))\n        index = 0;\n\tSetCurSel(index);\n\n\tint tab_size = m_tab_list.size();\n\tfor (int i = 0; i < tab_size; i++)\n\t{\n\t\tif (i == index)\n\t\t{\n\t\t\tm_tab_list[i]->ShowWindow(SW_SHOW);\n\t\t\tm_tab_list[i]->SetFocus();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_tab_list[i]->ShowWindow(SW_HIDE);\n\t\t}\n\t}\n}\n\nCWnd* CTabCtrlEx::GetCurrentTab()\n{\n    int cur_tab_index = GetCurSel();\n    if (cur_tab_index >= 0 && cur_tab_index < m_tab_list.size())\n    {\n        return m_tab_list[cur_tab_index];\n    }\n    return nullptr;\n}\n\nvoid CTabCtrlEx::AdjustTabWindowSize()\n{\n    CalSubWindowSize();\n    for (size_t i{}; i < m_tab_list.size(); i++)\n    {\n        m_tab_list[i]->MoveWindow(m_tab_rect);\n    }\n}\n\nvoid CTabCtrlEx::CalSubWindowSize()\n{\n    GetClientRect(m_tab_rect);\n    CRect rc_temp = m_tab_rect;\n    AdjustRect(FALSE, rc_temp);\n    int margin = rc_temp.left - m_tab_rect.left;\n    CRect rcTabItem;\n    GetItemRect(0, rcTabItem);\n    m_tab_rect.top += rcTabItem.Height() + margin;\n    m_tab_rect.left += margin;\n    m_tab_rect.bottom -= margin;\n    m_tab_rect.right -= margin;\n}\n\n\nBEGIN_MESSAGE_MAP(CTabCtrlEx, CTabCtrl)\n\tON_NOTIFY_REFLECT(TCN_SELCHANGE, &CTabCtrlEx::OnTcnSelchange)\n    ON_WM_SIZE()\nEND_MESSAGE_MAP()\n\n\n\n// CTabCtrlEx 消息处理程序\n\n\n\n\nvoid CTabCtrlEx::OnTcnSelchange(NMHDR *pNMHDR, LRESULT *pResult)\n{\n\t// TODO: 在此添加控件通知处理程序代码\n\tint tab_selected = GetCurSel();\n\tSetCurTab(tab_selected);\n\n\t*pResult = 0;\n}\n\n\nvoid CTabCtrlEx::PreSubclassWindow()\n{\n\t// TODO: 在此添加专用代码和/或调用基类\n\n\t//计算子窗口的位置\n    CalSubWindowSize();\n\n\tCTabCtrl::PreSubclassWindow();\n}\n\n\nvoid CTabCtrlEx::OnSize(UINT nType, int cx, int cy)\n{\n    CTabCtrl::OnSize(nType, cx, cy);\n\n    // TODO: 在此处添加消息处理程序代码\n    AdjustTabWindowSize();\n}\n"
  },
  {
    "path": "TrafficMonitor/CTabCtrlEx.h",
    "content": "#pragma once\n\n\n// CTabCtrlEx\n\nclass CTabCtrlEx : public CTabCtrl\n{\n\tDECLARE_DYNAMIC(CTabCtrlEx)\n\npublic:\n\tCTabCtrlEx();\n\tvirtual ~CTabCtrlEx();\n\n\tvoid AddWindow(CWnd* pWnd, LPCTSTR lable_text);\t\t//ǰtabؼһӴ\n\tvoid SetCurTab(int index);\n    CWnd* GetCurrentTab();\n    void AdjustTabWindowSize();\n\nprotected:\n    void CalSubWindowSize();\n\n\tDECLARE_MESSAGE_MAP()\n\nprotected:\n\tvector<CWnd*> m_tab_list;\t\t//tabؼÿӴڵָ\npublic:\n\tafx_msg void OnTcnSelchange(NMHDR *pNMHDR, LRESULT *pResult);\n\tvirtual void PreSubclassWindow();\n\n\tCRect m_tab_rect;\n    afx_msg void OnSize(UINT nType, int cx, int cy);\n};\n\n\n"
  },
  {
    "path": "TrafficMonitor/CVariant.cpp",
    "content": "#include \"stdafx.h\"\n#include \"CVariant.h\"\n\n\nCVariant::CVariant(int value)\n{\n\tm_value_int = value;\n\tm_type = eType::INT;\n}\n\nCVariant::CVariant(size_t value)\n{\n\tm_value_int = static_cast<int>(value);\n\tm_type = eType::UINT;\n}\n\nCVariant::CVariant(double value)\n{\n\tm_value_double = value;\n\tm_type = eType::DOUBLE;\n}\n\nCVariant::CVariant(LPCTSTR value)\n{\n\tm_value_string = value;\n\tm_type = eType::STRING;\n}\n\nCVariant::CVariant(const CString& value)\n{\n\tm_value_string = value;\n\tm_type = eType::STRING;\n}\n\nCVariant::CVariant(const wstring & value)\n{\n\tm_value_string = value.c_str();\n\tm_type = eType::STRING;\n}\n\nCVariant::~CVariant()\n{\n}\n\nCString CVariant::ToString() const\n{\n\tCString str;\n\tswitch (m_type)\n\t{\n\tcase CVariant::eType::INT:\n\t\tstr.Format(_T(\"%d\"), m_value_int);\n\t\tbreak;\n\tcase eType::UINT:\n\t\tstr.Format(_T(\"%u\"), static_cast<unsigned int>(m_value_int));\n\t\tbreak;\n\tcase CVariant::eType::DOUBLE:\n\t\tstr.Format(_T(\"%g\"), m_value_double);\n\t\tbreak;\n\tcase CVariant::eType::STRING:\n\t\tstr = m_value_string;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn str;\n}\n"
  },
  {
    "path": "TrafficMonitor/CVariant.h",
    "content": "#pragma once\nclass CVariant\n{\npublic:\n\tCVariant(int value);\n\tCVariant(size_t value);\n\tCVariant(double value);\n\tCVariant(LPCTSTR value);\n\tCVariant(const CString& value);\n\tCVariant(const wstring& value);\n\n\t~CVariant();\n\n\tCString ToString() const;\n\nprivate:\n\tenum class eType { INT, UINT, DOUBLE, STRING };\n\n\tint m_value_int;\n\tdouble m_value_double;\n\tCString m_value_string;\n\teType m_type;\n\n};\n\n"
  },
  {
    "path": "TrafficMonitor/CalendarHelper.cpp",
    "content": "#include \"stdafx.h\"\n#include \"CalendarHelper.h\"\n\n\nCCalendarHelper::CCalendarHelper()\n{\n}\n\n\nCCalendarHelper::~CCalendarHelper()\n{\n}\n\nbool CCalendarHelper::IsLeapYear(int year)\n{\n\treturn ((0 == year % 4 && 0 != year % 100) || 0 == year % 400);\n}\n\nint CCalendarHelper::CaculateWeekDay(int y, int m, int d)\n{\n\tif (m <= 2)\n\t{\n\t\tm += 12;\n\t\ty--;\n\t}\n\treturn (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400 + 1) % 7;\n}\n\nint CCalendarHelper::DaysInMonth(int year, int month)\n{\n\tbool leap{ IsLeapYear(year) };\n\tswitch (month)\n\t{\n\tcase 2:\n\t\tif (leap) return 29;\n\t\telse return 28;\n\tcase 4: case 6: case 9: case 11:\n\t\treturn 30;\n\tdefault:\n\t\treturn 31;\n\t}\n}\n\nvoid CCalendarHelper::GetCalendar(int year, int month, DayTraffic calendar[CALENDAR_HEIGHT][CALENDAR_WIDTH], bool sunday_first)\n{\n\tmemset(calendar, 0, sizeof(DayTraffic)*CALENDAR_HEIGHT*CALENDAR_WIDTH);\n\tint days{ DaysInMonth(year, month) };\n\tint first_weak_day{ CaculateWeekDay(year, month, 1) };\n\tif(!sunday_first)\n\t{\n\t\tfirst_weak_day--;\n\t\tif (first_weak_day < 0)\n\t\t\tfirst_weak_day = 6;\n\t}\n\tint i{}, j{};\n\tfor (int n{}; n < 37; n++)\n\t{\n\t\tif (n < first_weak_day)\n\t\t{\n\t\t\tcalendar[i][j].day = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tint day = n - first_weak_day + 1;\n\t\t\tif (day <= days)\n\t\t\t\tcalendar[i][j].day = day;\n\t\t}\n\t\tj++;\n\t\tif (j >= 7)\n\t\t{\n\t\t\tj = 0;\n\t\t\ti++;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "TrafficMonitor/CalendarHelper.h",
    "content": "#pragma once\n#define CALENDAR_WIDTH 7\n#define CALENDAR_HEIGHT 6\n\nstruct DayTraffic\n{\n\tint day;\n\t__int64 up_traffic;\n\t__int64 down_traffic;\n\tbool mixed;\n\tCRect rect;\n\n\t__int64 traffic() const\n\t{\n\t\treturn up_traffic + down_traffic;\n\t}\n};\n\nclass CCalendarHelper\n{\npublic:\n\tCCalendarHelper();\n\t~CCalendarHelper();\n\n\t//ǷΪ\n\tstatic bool IsLeapYear(int year);\n\t//ڼ(0~6~)\n\tstatic int CaculateWeekDay(int y, int m, int d);\n\t//һж\n\tstatic int DaysInMonth(int year, int month);\n\n\t//ȡָ·ݵݣcalendar\n\t//sunday_firstΪtrueΪÿܵĵһ죬򣬽һΪÿܵĵһ\n\tstatic void GetCalendar(int year, int month, DayTraffic calendar[CALENDAR_HEIGHT][CALENDAR_WIDTH], bool sunday_first = true);\n\n};\n\n"
  },
  {
    "path": "TrafficMonitor/ClassicalTaskbarDlg.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"ClassicalTaskbarDlg.h\"\n\nvoid CClassicalTaskbarDlg::AdjustTaskbarWndPos(bool force_adjust)\n{\n    ::GetWindowRect(m_hMin, m_rcMin); //获得最小化窗口的区域\n    ::GetWindowRect(m_hBar, m_rcBar); //获得二级容器的区域\n\n    if (m_taskbar_on_top_or_bottom)     //当任务栏在桌面顶部或底部时\n    {\n        //设置窗口大小\n        m_rect.right = m_rect.left + m_window_width;\n        m_rect.bottom = m_rect.top + m_window_height;\n\n        if (force_adjust || m_rcMin.Width() != m_last_width)   //如果宽度改变了，重新设置任务栏窗口的位置\n        {\n            m_rcMinOri = m_rcMin;\n            m_left_space = m_rcMin.left - m_rcBar.left;\n            //保存上次的宽度\n            m_last_width = m_rcMin.Width() - m_rect.Width();\n            //任务窗口显示在右侧时\n            if (!theApp.m_taskbar_data.tbar_wnd_on_left)\n            {\n                ::MoveWindow(m_hMin, m_left_space, 0, m_rcMin.Width() - m_rect.Width(), m_rcMin.Height(), TRUE);    //设置最小化窗口的位置\n                m_rect.MoveToX(m_left_space + m_rcMin.Width() - m_rect.Width() + 2);\n            }\n            //任务栏窗口显示在左侧时\n            else\n            {\n                ::MoveWindow(m_hMin, m_left_space + m_rect.Width(), 0, m_rcMin.Width() - m_rect.Width(), m_rcMin.Height(), TRUE);\n                m_rect.MoveToX(m_left_space);\n            }\n\n            //设置任务栏窗口的垂直位置\n            m_rect.MoveToY((m_rcBar.Height() - m_rect.Height()) / 2);\n            if (theApp.m_taskbar_data.horizontal_arrange && theApp.m_win_version.IsWindows7())\n                m_rect.MoveToY(m_rect.top + DPI(1));\n            MoveWindow(m_rect);\n        }\n    }\n    else        //当任务栏在屏幕在左侧或右侧时\n    {\n        //设置窗口大小\n        if (force_adjust || m_rcMin.Height() != m_last_height)     //如果高度改变了，重新设置任务栏窗口的位置\n        {\n            m_rcMinOri = m_rcMin;\n            m_top_space = m_rcMin.top - m_rcBar.top;\n            //保存上次的宽度\n            m_last_height = m_rcMin.Height() - m_rect.Height();\n\n            if (!theApp.m_taskbar_data.tbar_wnd_on_left)\n            {\n                ::MoveWindow(m_hMin, 0, m_top_space, m_rcMin.Width(), m_rcMin.Height() - m_rect.Height(), TRUE);    //设置最小化窗口的位置\n                m_rect.MoveToY(m_top_space + m_rcMin.Height() - m_rect.Height() + 2);\n            }\n            else\n            {\n                ::MoveWindow(m_hMin, 0, m_top_space + m_rect.Height(), m_rcMin.Width(), m_rcMin.Height() - m_rect.Height(), TRUE);  //设置最小化窗口的位置\n                m_rect.MoveToY(m_top_space);\n            }\n            m_rect.MoveToX((m_rcMin.Width() - m_window_width) / 2);\n            int left_space = DPI(2);\n            if (m_rect.left < left_space)\n                m_rect.MoveToX(left_space);\n            MoveWindow(m_rect);\n        }\n    }\n}\n\nvoid CClassicalTaskbarDlg::InitTaskbarWnd()\n{\n    m_hBar = ::FindWindowEx(m_hTaskbar, 0, L\"ReBarWindow32\", NULL); //寻找二级容器的句柄\n    if (m_hBar == NULL)\n        m_hBar = ::FindWindowEx(m_hTaskbar, nullptr, L\"WorkerW\", NULL);\n    m_hMin = ::FindWindowEx(m_hBar, 0, L\"MSTaskSwWClass\", NULL);    //寻找最小化窗口的句柄\n    if (m_hMin == NULL)\n        m_hMin = ::FindWindowEx(m_hBar, 0, L\"MSTaskListWClass\", NULL);    //寻找最小化窗口的句柄\n\n    ::GetWindowRect(m_hMin, m_rcMin);   //获得最小化窗口的区域\n    ::GetWindowRect(m_hBar, m_rcBar);   //获得二级容器的区域\n\n    m_left_space = m_rcMin.left - m_rcBar.left;\n    m_top_space = m_rcMin.top - m_rcBar.top;\n}\n\nvoid CClassicalTaskbarDlg::ResetTaskbarPos()\n{\n    //程序关闭的时候，把最小化窗口的width恢复回去\n    if (!m_rcMinOri.IsRectEmpty())\n    {\n        if (m_taskbar_on_top_or_bottom)\n            ::MoveWindow(m_hMin, m_left_space, 0, m_rcMinOri.Width(), m_rcMinOri.Height(), TRUE);\n        else\n\n            ::MoveWindow(m_hMin, 0, m_top_space, m_rcMinOri.Width(), m_rcMinOri.Height(), TRUE);\n    }\n}\n\nHWND CClassicalTaskbarDlg::GetParentHwnd()\n{\n    return m_hBar;\n}\n\nvoid CClassicalTaskbarDlg::CheckTaskbarOnTopOrBottom()\n{\n    CRect rect;\n    CRect rcMin;\n    CRect rcBar;\n    if (m_hTaskbar != 0)\n    {\n        //::GetWindowRect(m_hMin, rcMin); //获得最小化窗口的区域\n        //::GetWindowRect(m_hBar, rcBar); //获得二级容器的区域\n        //if (m_left_space == 0)\n        //    m_left_space = rcMin.left - rcBar.left;\n        //if (m_top_space == 0)\n        //    m_top_space = rcMin.top - rcBar.top;\n\n        ::GetWindowRect(m_hTaskbar, rect);          //获取任务栏的矩形区域\n        m_taskbar_on_top_or_bottom = (rect.Width() >= rect.Height());     //如果任务栏的宽度大于高度，则任务在屏幕的顶部或底部\n    }\n    else\n    {\n        m_taskbar_on_top_or_bottom = true;\n    }\n}\n\n"
  },
  {
    "path": "TrafficMonitor/ClassicalTaskbarDlg.h",
    "content": "﻿#pragma once\n#include \"TaskBarDlg.h\"\nclass CClassicalTaskbarDlg :\n    public CTaskBarDlg\n{\npublic:\n\nprivate:\n    // 通过 CTaskBarDlg 继承\n    virtual void AdjustTaskbarWndPos(bool force_adjust) override;\n    void InitTaskbarWnd() override;\n    void ResetTaskbarPos() override;\n    virtual HWND GetParentHwnd() override;\n\nprivate:\n    CRect m_rcMinOri;   //初始状态时最小化窗口的矩形区域\n    int m_left_space{};\t\t\t//最小化窗口和二级窗口窗口左侧的边距\n    int m_top_space{};\t\t\t//最小化窗口和二级窗口窗口顶部的边距（用于任务栏在屏幕左侧或右侧时）\n    HWND m_hBar;\t\t//任务栏窗口二级容器的句柄\n    HWND m_hMin;\t\t//最小化窗口的句柄\n    CRect m_rcBar;\t\t//初始状态时任务栏窗口的矩形区域\n    CRect m_rcMin;\t\t//最小化窗口的矩形区域\n\n    int m_last_width;\t//用于检测宽度变化的上一次的宽度\n    int m_last_height;\t//用于检测高度变化的上一次的高度（用于任务栏在屏幕左侧或右侧时）\n\n    // 通过 CTaskBarDlg 继承\n    void CheckTaskbarOnTopOrBottom() override;\n};\n\n"
  },
  {
    "path": "TrafficMonitor/ColorSettingListCtrl.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"ColorSettingListCtrl.h\"\n\nIMPLEMENT_DYNAMIC(CColorSettingListCtrl, CListCtrl)\n\nCColorSettingListCtrl::CColorSettingListCtrl()\n{\n}\n\n\nCColorSettingListCtrl::~CColorSettingListCtrl()\n{\n}\n\nvoid CColorSettingListCtrl::SetItemColor(int row, int col, COLORREF color)\n{\n    m_colors[row][col] = color;\n}\n\n\nCOLORREF CColorSettingListCtrl::GetItemColor(int row, int col)\n{\n    return m_colors[row][col];\n}\n\nBEGIN_MESSAGE_MAP(CColorSettingListCtrl, CListCtrl)\n\tON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CColorSettingListCtrl::OnNMCustomdraw)\nEND_MESSAGE_MAP()\n\n\nvoid CColorSettingListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)\n{\n\t*pResult = CDRF_DODEFAULT;\n\tLPNMLVCUSTOMDRAW lplvdr = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);\n\tNMCUSTOMDRAW& nmcd = lplvdr->nmcd;\n\tswitch (lplvdr->nmcd.dwDrawStage)\t//判断状态   \n\t{\n\tcase CDDS_PREPAINT:\n\t\t*pResult = CDRF_NOTIFYITEMDRAW;\n\t\tbreak;\n\tcase CDDS_ITEMPREPAINT:\t\t\t//如果为画ITEM之前就要进行颜色的改变\n\t\tif (nmcd.dwItemSpec >= 0 && nmcd.dwItemSpec < GetItemCount())\n\t\t{\n\t\t\t//double range = m_item_rage_data[nmcd.dwItemSpec].data_value;\n\t\t\t//CDC* pDC = CDC::FromHandle(nmcd.hdc);\t\t//获取绘图DC\n\t\t\t//CRect item_rect, draw_rect;\n\t\t\t//GetSubItemRect(nmcd.dwItemSpec,m_draw_item_range_row, LVIR_BOUNDS, item_rect);\t//获取绘图单元格的矩形区域\n\t\t\t//CDrawCommon::SetDrawRect(pDC, item_rect);\t\t//设置绘图区域为当前列\n\t\t\t//draw_rect = item_rect;\n\t\t\t//if (draw_rect.Height() > 2 * m_margin)\n\t\t\t//{\n\t\t\t//\tdraw_rect.top += m_margin;\n\t\t\t//\tdraw_rect.bottom -= m_margin;\n\t\t\t//}\n\t\t\t//int width;\n\t\t\t//if (m_use_log_scale)\t//使用对数比例（y=ln(x+1)）\n\t\t\t//{\n\t\t\t//\trange = std::log(range + 1);\n\t\t\t//\twidth = static_cast<int>(range*draw_rect.Width() / std::log(1000 + 1));\n\t\t\t//}\n\t\t\t//else\t\t//使用线性比例（y=x）\n\t\t\t//{\n\t\t\t//\twidth = static_cast<int>(range*draw_rect.Width() / 1000);\n\t\t\t//}\n\t\t\t//draw_rect.right = draw_rect.left + width;\n\t\t\t//pDC->FillSolidRect(draw_rect, m_item_rage_data[nmcd.dwItemSpec].color);\n\n\t\t\t////当前列绘制完成后将绘图区域设置为左边的区域，防止当前列的区域被覆盖\n\t\t\t//CRect rect1{ item_rect };\n\t\t\t//rect1.left = 0;\n\t\t\t//rect1.right = item_rect.left;\n\t\t\t//CDrawCommon::SetDrawRect(pDC, rect1);\n\n            CDC* pDC = CDC::FromHandle(nmcd.hdc);\t\t//获取绘图DC\n            CRect item_rect;\n            auto& col_color_map = m_colors[nmcd.dwItemSpec];\n            for (auto iter = col_color_map.begin(); iter != col_color_map.end(); ++iter)\n            {\n                GetSubItemRect(nmcd.dwItemSpec, iter->first, LVIR_BOUNDS, item_rect);\t//获取绘图单元格的矩形区域\n                //设置绘图剪辑区域\n                CDrawCommon::SetDrawRect(pDC, item_rect);\n                //使用双缓冲绘图\n                CDrawDoubleBuffer draw_double_buffer(pDC, item_rect);\n                //填充背景\n                item_rect.MoveToXY(0, 0);\n                draw_double_buffer.GetMemDC()->FillSolidRect(item_rect, GetSysColor(COLOR_WINDOW));\n                //绘制颜色矩形\n                item_rect.DeflateRect(m_margin, m_margin);\n                draw_double_buffer.GetMemDC()->FillSolidRect(item_rect, iter->second);\n                //绘制矩形边框\n                CDrawCommon drawer;\n                drawer.Create(draw_double_buffer.GetMemDC(), this);\n                drawer.DrawRectOutLine(item_rect, RGB(192, 192, 192));\n            }\n            //当前列绘制完成后将绘图区域设置为第一列的区域，防止颜色列的区域被覆盖\n            CRect rect1{};\n            GetSubItemRect(nmcd.dwItemSpec, 1, LVIR_BOUNDS, rect1);\t//获取第1列单元格的矩形区域\n            rect1.right = rect1.left;\n            rect1.left = 0;\n            CDrawCommon::SetDrawRect(pDC, rect1);\n\n\t\t}\n\t\t*pResult = CDRF_DODEFAULT;\n\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "TrafficMonitor/ColorSettingListCtrl.h",
    "content": "#pragma once\n#include \"afxcmn.h\"\n#include \"DrawCommon.h\"\nclass CColorSettingListCtrl :\n\tpublic CListCtrl\n{\nDECLARE_DYNAMIC(CColorSettingListCtrl)\npublic:\n\tCColorSettingListCtrl();\n\t~CColorSettingListCtrl();\n\n    void SetItemColor(int row, int col, COLORREF color);\n    COLORREF GetItemColor(int row, int col);\n\tvoid SetDrawItemRangMargin(int margin) { m_margin = margin; }\t\t\t//ûƻƵľεıԵԪ߿ľΣֵԽƵľԽϸǲܳбоһ\n\nprotected:\n\tint m_margin{};\n\tstd::map<int, std::map<int, COLORREF>> m_colors;\t//ڱÿһÿһеɫ\n\n\tDECLARE_MESSAGE_MAP()\n\tafx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);\n};\n\n"
  },
  {
    "path": "TrafficMonitor/ColorStatic.cpp",
    "content": "﻿// ColorStatic.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"ColorStatic.h\"\n#include \"DrawCommon.h\"\n\n// CColorStatic\n\nIMPLEMENT_DYNAMIC(CColorStatic, CStatic)\n\nCColorStatic::CColorStatic()\n{\n\n}\n\nCColorStatic::~CColorStatic()\n{\n}\n\nvoid CColorStatic::SetFillColor(COLORREF fill_color)\n{\n\tm_colors.resize(1);\n\tm_colors[0] = fill_color;\n\t//m_fill_color = fill_color;\n\tInvalidate();\n}\n\nvoid CColorStatic::SetColorNum(int color_num)\n{\n\tif (color_num <= 0 || color_num > 32)\n\t\tcolor_num = 1;\n\tm_colors.resize(color_num);\n}\n\nvoid CColorStatic::SetFillColor(int index, COLORREF fill_color)\n{\n\tif (index >= 0 && index < static_cast<int>(m_colors.size()))\n\t\tm_colors[index] = fill_color;\n}\n\nvoid CColorStatic::SetLinkCursor(bool link_cursor)\n{\n\tm_link_cursor = link_cursor;\n}\n\nvoid CColorStatic::EnableWindow(bool enable)\n{\n    CStatic::EnableWindow(enable);\n    Invalidate(FALSE);\n}\n\n\nBEGIN_MESSAGE_MAP(CColorStatic, CStatic)\n\tON_WM_PAINT()\n\tON_WM_MOUSEHOVER()\n\tON_WM_MOUSELEAVE()\n\tON_WM_SETCURSOR()\n\tON_WM_MOUSEMOVE()\n\tON_WM_LBUTTONUP()\nEND_MESSAGE_MAP()\n\n\n\n// CColorStatic 消息处理程序\n\n\n\n\nvoid CColorStatic::OnPaint()\n{\n\tCPaintDC dc(this); // device context for painting\n\t\t\t\t\t   // TODO: 在此处添加消息处理程序代码\n\t\t\t\t\t   // 不为绘图消息调用 CStatic::OnPaint()\n\tCRect rect;\n\tGetClientRect(rect);\n\trect.MoveToXY(0, 0);\n\tCRect rc_tmp{ rect };\n\n\tCDrawCommon draw;\n\tdraw.Create(&dc, this);\n\n    int color_num = static_cast<int>(m_colors.size());\n\n\tif (IsWindowEnabled() && color_num > 0)\n\t{\n\t\tif (color_num == 1)\n\t\t{\n\t\t\tdc.FillSolidRect(rect, m_colors[0]);\n\t\t}\n\t\t//颜色数量大于或等于4，并且是4个位数时，上下两行以“Z”字形排列\n\t\telse if (color_num >= 4 && color_num % 4 == 0)\n\t\t{\n\t\t\tdc.FillSolidRect(rect, RGB(255, 255, 255));\n\t\t\tint group_num = color_num / 4;\t\t//颜色组数（4个为一组）\n\t\t\tfor (int i = 0; i < group_num; i++)\n\t\t\t{\n\t\t\t\tint group_left = rect.Width() * i / group_num;\n\t\t\t\tint group_right = rect.Width() * (i + 1) / group_num;\n\t\t\t\tCRect rc_group(group_left, 0, group_right, rect.Height());\t//当前组的矩形区域\n\t\t\t\tCRect rc1(group_left, 0, group_left + rc_group.Width() / 2, rc_group.Height() / 2);\n\t\t\t\tCRect rc2(group_left + rc_group.Width() / 2, 0, rc_group.right, rc_group.Height() / 2);\n\t\t\t\tCRect rc3(group_left, rc_group.Height() / 2, group_left + rc_group.Width() / 2, rc_group.bottom);\n\t\t\t\tCRect rc4(group_left + rc_group.Width() / 2, rc_group.Height() / 2, rc_group.right, rc_group.bottom);\n\t\t\t\tdc.FillSolidRect(rc1, m_colors[static_cast<size_t>(i) * 4]);\n\t\t\t\tdc.FillSolidRect(rc2, m_colors[static_cast<size_t>(i) * 4 + 1]);\n\t\t\t\tdc.FillSolidRect(rc3, m_colors[static_cast<size_t>(i) * 4 + 2]);\n\t\t\t\tdc.FillSolidRect(rc4, m_colors[static_cast<size_t>(i) * 4 + 3]);\n\t\t\t}\n\t\t}\n\t\t//其他情况，一行从左到右排列\n\t\telse\n\t\t{\n\t\t\tdc.FillSolidRect(rect, RGB(255, 255, 255));\n\t\t\tfor (int i = 0; i < color_num; i++)\n\t\t\t{\n\t\t\t\tint left = rect.Width() * i / color_num;\n\t\t\t\tint right = rect.Width() * (i + 1) / color_num;\n\t\t\t\tCRect rc_cell(left, 0, right, rect.Height());\n\t\t\t\tdc.FillSolidRect(rc_cell, m_colors[i]);\n\t\t\t}\n\t\t}\n\n\t\t//画边框\n\t\tdraw.DrawRectOutLine(rect, RGB(160, 160, 160));\n\t}\n\telse\n\t{\n        CBrush brush(HS_BDIAGONAL, RGB(160, 160, 160));\n        dc.FillRect(rect, &brush);\n\t\tdraw.DrawRectOutLine(rect, RGB(192, 192, 192));\n\t}\n}\n\n\nvoid CColorStatic::OnMouseHover(UINT nFlags, CPoint point)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tm_hover = true;\n\n\tCStatic::OnMouseHover(nFlags, point);\n}\n\n\nvoid CColorStatic::OnMouseLeave()\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tm_hover = false;\n\n\tCStatic::OnMouseLeave();\n}\n\n\nBOOL CColorStatic::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tif(m_link_cursor && m_hover)\n\t{\n\t\t::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(32649)));\n\t\treturn TRUE;\n\t}\n\n\treturn CStatic::OnSetCursor(pWnd, nHitTest, message);\n}\n\n\nvoid CColorStatic::PreSubclassWindow()\n{\n\t// TODO: 在此添加专用代码和/或调用基类\n\tDWORD dwStyle = GetStyle();\n\t::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);\n\tModifyStyleEx(WS_EX_STATICEDGE, NULL);\n\n\tCStatic::PreSubclassWindow();\n}\n\n\nvoid CColorStatic::OnMouseMove(UINT nFlags, CPoint point)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tif (m_link_cursor)\n\t{\n\t\tTRACKMOUSEEVENT tme;\n\t\ttme.cbSize = sizeof(tme);\n\t\ttme.hwndTrack = m_hWnd;\n\t\ttme.dwFlags = TME_LEAVE | TME_HOVER;\n\t\ttme.dwHoverTime = 1;\n\t\t_TrackMouseEvent(&tme);\n\t}\n\n\tCStatic::OnMouseMove(nFlags, point);\n}\n\n\nvoid CColorStatic::OnLButtonUp(UINT nFlags, CPoint point)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\t//如果单击了鼠标左键，则向父窗口发送一个WM_STATIC_CLICKED消息\n\tCWnd* pParent{ GetParent() };\n\tif (pParent != nullptr)\n\t\tpParent->SendMessage(WM_STATIC_CLICKED, (WPARAM)this);\n\n\tCStatic::OnLButtonUp(nFlags, point);\n}\n"
  },
  {
    "path": "TrafficMonitor/ColorStatic.h",
    "content": "﻿// CColorStatic\n//派生自CStatic，用于显示颜色的Static控件\n#pragma once\n#define WM_STATIC_CLICKED (WM_USER + 1001)\n\nclass CColorStatic : public CStatic\n{\n\tDECLARE_DYNAMIC(CColorStatic)\n\npublic:\n\tCColorStatic();\n\tvirtual ~CColorStatic();\n\n\tvoid SetFillColor(COLORREF fill_color);\t\t//设置要填充单一的背景色\n\tvoid SetColorNum(int color_num);\t\t\t//设置颜色的数量\n\tvoid SetFillColor(int index, COLORREF fill_color);\n\tvoid SetLinkCursor(bool link_cursor = true);\t\t//设置指向控件时光标变成超链接形状\n    void EnableWindow(bool enable);\n\nprotected:\n\t//COLORREF m_fill_color{ RGB(255, 255,255) };\n\tvector<COLORREF> m_colors;\n\tbool m_hover{ false };\t\t//当鼠标指向控件时为true\n\tbool m_link_cursor{ false };\t//是否启用超链接形状的光标\n\nprotected:\n\tDECLARE_MESSAGE_MAP()\npublic:\n\tafx_msg void OnPaint();\n\tafx_msg void OnMouseHover(UINT nFlags, CPoint point);\n\tafx_msg void OnMouseLeave();\n\tafx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);\n\tvirtual void PreSubclassWindow();\n\tafx_msg void OnMouseMove(UINT nFlags, CPoint point);\n\tafx_msg void OnLButtonUp(UINT nFlags, CPoint point);\n};\n"
  },
  {
    "path": "TrafficMonitor/ComboBox2.cpp",
    "content": "﻿// ComboBox2.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"ComboBox2.h\"\n\n\n// CComboBox2\n\nIMPLEMENT_DYNAMIC(CComboBox2, CComboBox)\n\nCComboBox2::CComboBox2()\n{\n\n}\n\nCComboBox2::~CComboBox2()\n{\n}\n\n\nvoid CComboBox2::SetMouseWheelEnable(bool enable)\n{\n    m_mouse_wheel_enable = enable;\n}\n\nBEGIN_MESSAGE_MAP(CComboBox2, CComboBox)\nEND_MESSAGE_MAP()\n\n\n\n// CComboBox2 消息处理程序\n\n\n\n\nBOOL CComboBox2::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //如果m_mouse_wheel_enable为false，则不响应鼠标滚轮消息\n    if (pMsg->message == WM_MOUSEWHEEL && !m_mouse_wheel_enable)\n    {\n        //将鼠标滚轮消息发送给父窗口\n        CWnd* pParent = GetParent();\n        pParent->SendMessage(WM_MOUSEWHEEL, pMsg->wParam, pMsg->lParam);\n        return true;\n    }\n\n    return CComboBox::PreTranslateMessage(pMsg);\n}\n"
  },
  {
    "path": "TrafficMonitor/ComboBox2.h",
    "content": "﻿#pragma once\n\n\n// CComboBox2\n\nclass CComboBox2 : public CComboBox\n{\n\tDECLARE_DYNAMIC(CComboBox2)\n\npublic:\n\tCComboBox2();\n\tvirtual ~CComboBox2();\n    void SetMouseWheelEnable(bool enable);  //设置是否允许响应鼠标滚轮\n\nprivate:\n    bool m_mouse_wheel_enable{ true };\n\nprotected:\n\tDECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n};\n\n\n"
  },
  {
    "path": "TrafficMonitor/Common.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n\n\nCCommon::CCommon()\n{\n}\n\n\nCCommon::~CCommon()\n{\n}\n\nwstring CCommon::StrToUnicode(const char* str, bool utf8)\n{\n    wstring result;\n    int size;\n    size = MultiByteToWideChar((utf8 ? CP_UTF8 : CP_ACP), 0, str, -1, NULL, 0);\n    if (size <= 0) return wstring();\n    wchar_t* str_unicode = new wchar_t[size + 1];\n    MultiByteToWideChar((utf8 ? CP_UTF8 : CP_ACP), 0, str, -1, str_unicode, size);\n    result.assign(str_unicode);\n    delete[] str_unicode;\n    return result;\n}\n\nstring CCommon::UnicodeToStr(const wchar_t* wstr, bool utf8)\n{\n    string result;\n    int size{ 0 };\n    size = WideCharToMultiByte((utf8 ? CP_UTF8 : CP_ACP), 0, wstr, -1, NULL, 0, NULL, NULL);\n    if (size <= 0) return string();\n    char* str = new char[size + 1];\n    WideCharToMultiByte((utf8 ? CP_UTF8 : CP_ACP), 0, wstr, -1, str, size, NULL, NULL);\n    result.assign(str);\n    delete[] str;\n    return result;\n}\n\nwstring CCommon::AsciiToUnicode(const string& str)\n{\n    std::wstring result;\n    result.resize(str.size());\n    for (size_t i{}; i < str.size(); i++)\n        result[i] = str[i];\n    return result;\n}\n\nstring CCommon::AsciiToStr(const std::wstring& wstr)\n{\n    std::string result;\n    result.resize(wstr.size());\n    for (size_t i{}; i < wstr.size(); i++)\n        result[i] = static_cast<char>(wstr[i]);\n    return result;\n}\n\ntemplate<class T>\nstatic void _StringNormalize(T& str)\n{\n    if (str.empty()) return;\n\n    int size = static_cast<int>(str.size());  //字符串的长度\n    if (size < 0) return;\n    int index1 = 0;     //字符串中第1个不是空格或控制字符的位置\n    int index2 = size - 1;  //字符串中最后一个不是空格或控制字符的位置\n    while (index1 < size && str[index1] >= 0 && str[index1] <= 32)\n        index1++;\n    while (index2 >= 0 && str[index2] >= 0 && str[index2] <= 32)\n        index2--;\n    if (index1 > index2)    //如果index1 > index2，说明字符串全是空格或控制字符\n        str.clear();\n    else if (index1 == 0 && index2 == size - 1) //如果index1和index2的值分别为0和size - 1，说明字符串前后没有空格或控制字符，直接返回\n        return;\n    else\n        str = str.substr(index1, index2 - index1 + 1);\n}\n\nvoid CCommon::StringNormalize(std::string& str)\n{\n    _StringNormalize(str);\n}\n\nvoid CCommon::StringNormalize(std::wstring& str)\n{\n    _StringNormalize(str);\n}\n\ntemplate<class T>\nstatic void _StringSplit(const T& str, wchar_t div_ch, vector<T>& results, bool skip_empty = true, bool trim = true)\n{\n    results.clear();\n    size_t split_index = -1;\n    size_t last_split_index = -1;\n    while (true)\n    {\n        split_index = str.find(div_ch, split_index + 1);\n        T split_str = str.substr(last_split_index + 1, split_index - last_split_index - 1);\n        if (trim)\n            _StringNormalize(split_str);\n        if (!split_str.empty() || !skip_empty)\n            results.push_back(split_str);\n        if (split_index == wstring::npos)\n            break;\n        last_split_index = split_index;\n    }\n}\n\nvoid CCommon::StringSplit(const std::string& str, char div_ch, vector<std::string>& results, bool skip_empty, bool trim)\n{\n    _StringSplit(str, div_ch, results, skip_empty, trim);\n}\n\nvoid CCommon::StringSplit(const std::wstring& str, wchar_t div_ch, vector<std::wstring>& results, bool skip_empty, bool trim)\n{\n    _StringSplit(str, div_ch, results, skip_empty, trim);\n}\n\ntemplate<class T>\nstatic void _StringSplit(const T& str, const T& div_str, vector<T>& results, bool skip_empty = true, bool trim = true)\n{\n    results.clear();\n    size_t split_index = 0 - div_str.size();\n    size_t last_split_index = 0 - div_str.size();\n    while (true)\n    {\n        split_index = str.find(div_str, split_index + div_str.size());\n        T split_str = str.substr(last_split_index + div_str.size(), split_index - last_split_index - div_str.size());\n        if (trim)\n            _StringNormalize(split_str);\n        if (!split_str.empty() || !skip_empty)\n            results.push_back(split_str);\n        if (split_index == wstring::npos)\n            break;\n        last_split_index = split_index;\n    }\n}\n\nvoid CCommon::StringSplit(const std::string& str, const std::string& div_str, vector<std::string>& results, bool skip_empty, bool trim)\n{\n    _StringSplit(str, div_str, results, skip_empty, trim);\n}\n\nvoid CCommon::StringSplit(const std::wstring& str, const std::wstring& div_str, vector<std::wstring>& results, bool skip_empty, bool trim)\n{\n    _StringSplit(str, div_str, results, skip_empty, trim);\n}\n\ntemplate<class T>\nstatic bool _StringTransform(T& str, bool upper)\n{\n    if (str.empty()) return false;\n    if (upper)\n    {\n        for (auto& ch : str)\n        {\n            {\n                if (ch >= 'a' && ch <= 'z')\n                    ch -= 32;\n            }\n        }\n    }\n    else\n    {\n        for (auto& ch : str)\n        {\n            if (ch >= 'A' && ch <= 'Z')\n                ch += 32;\n        }\n    }\n    return true;\n}\n\nbool CCommon::StringTransform(std::string& str, bool upper)\n{\n    return _StringTransform(str, upper);\n}\n\nbool CCommon::StringTransform(std::wstring& str, bool upper)\n{\n    return _StringTransform(str, upper);\n}\n\nbool CCommon::GetFileContent(const wchar_t* file_path, string& contents_buff, bool binary /*= true*/)\n{\n    std::ifstream file{ file_path, (binary ? std::ios::binary : std::ios::in) };\n    if (file.fail())\n        return false;\n    //获取文件长度\n    file.seekg(0, file.end);\n    size_t length = file.tellg();\n    file.seekg(0, file.beg);\n\n    char* buff = new char[length];\n    file.read(buff, length);\n    file.close();\n\n    contents_buff.assign(buff, length);\n    delete[] buff;\n\n    return true;\n}\n\nconst char* CCommon::GetFileContent(const wchar_t* file_path, size_t& length, bool binary /*= true*/)\n{\n    std::ifstream file{ file_path, (binary ? std::ios::binary : std::ios::in) };\n    length = 0;\n    if (file.fail())\n        return nullptr;\n    //获取文件长度\n    file.seekg(0, file.end);\n    length = file.tellg();\n    file.seekg(0, file.beg);\n\n    char* buff = new char[length];\n    file.read(buff, length);\n    file.close();\n\n    return buff;\n}\n\nCString CCommon::DataSizeToString(unsigned long long size, const PublicSettingData& cfg)\n{\n    //CString str;\n    CString value_str, unit_str;\n    if (!cfg.unit_byte)     //如果使用比特(bit)为单位，则数值乘以8\n    {\n        size *= 8;\n    }\n    switch (cfg.speed_unit)\n    {\n    case SpeedUnit::AUTO:\n        if (cfg.speed_short_mode)\n        {\n            if (size < 1024 * 10)                   //10KB以下以KB为单位，保留1位小数\n            {\n                value_str.Format(_T(\"%.1f\"), size / 1024.0f);\n                unit_str = _T(\"K\");\n            }\n            else if (size < 1024 * 1000)            //1000KB以下以KB为单位，保留整数\n            {\n                value_str.Format(_T(\"%.0f\"), size / 1024.0f);\n                unit_str = _T(\"K\");\n            }\n            else if (size < 1024 * 1024 * 1000)     //1000MB以下以MB为单位，保留1位小数\n            {\n                value_str.Format(_T(\"%.1f\"), size / 1024.0f / 1024.0f);\n                unit_str = _T(\"M\");\n            }\n            else\n            {\n                value_str.Format(_T(\"%.2f\"), size / 1024.0f / 1024.0f / 1024.0f);\n                unit_str = _T(\"G\");\n            }\n        }\n        else\n        {\n            if (size < 1024 * 10)                   //10KB以下以KB为单位，保留2位小数\n            {\n                value_str.Format(_T(\"%.2f\"), size / 1024.0f);\n                unit_str = _T(\"KB\");\n            }\n            else if (size < 1024 * 1000)            //1000KB以下以KB为单位，保留1位小数\n            {\n                value_str.Format(_T(\"%.1f\"), size / 1024.0f);\n                unit_str = _T(\"KB\");\n            }\n            else if (size < 1024 * 1024 * 1000)     //1000MB以下以MB为单位，保留2位小数\n            {\n                value_str.Format(_T(\"%.2f\"), size / 1024.0f / 1024.0f);\n                unit_str = _T(\"MB\");\n            }\n            else\n            {\n                value_str.Format(_T(\"%.2f\"), size / 1024.0f / 1024.0f / 1024.0f);\n                unit_str = _T(\"GB\");\n            }\n        }\n        break;\n    case SpeedUnit::KBPS:\n        if (cfg.speed_short_mode)\n        {\n            if (size < 1024 * 10)                   //10KB以下保留1位小数\n                value_str.Format(_T(\"%.1f\"), size / 1024.0f);\n            else                    //10KB以上保留整数\n                value_str.Format(_T(\"%.0f\"), size / 1024.0f);\n            if (!cfg.hide_unit)\n                unit_str = _T(\"K\");\n        }\n        else\n        {\n            if (size < 1024 * 10)                   //10KB以下保留2位小数\n                value_str.Format(_T(\"%.2f\"), size / 1024.0f);\n            else            //10KB以上保留1位小数\n                value_str.Format(_T(\"%.1f\"), size / 1024.0f);\n            if (!cfg.hide_unit)\n                unit_str = _T(\"KB\");\n        }\n        break;\n    case SpeedUnit::MBPS:\n        if (cfg.speed_short_mode)\n        {\n            value_str.Format(_T(\"%.1f\"), size / 1024.0f / 1024.0f);\n            if (!cfg.hide_unit)\n                unit_str = _T(\"M\");\n        }\n        else\n        {\n            value_str.Format(_T(\"%.2f\"), size / 1024.0f / 1024.0f);\n            if (!cfg.hide_unit)\n                unit_str = _T(\"MB\");\n        }\n        break;\n    }\n    CString str;\n    if (cfg.separate_value_unit_with_space && !cfg.hide_unit)\n        str = value_str + _T(' ') + unit_str;\n    else\n        str = value_str + unit_str;\n    if (!cfg.unit_byte)\n    {\n        if (cfg.speed_short_mode && !cfg.hide_unit)\n            str += _T('b');     //如果使用比特(bit)为单位，即使设置了网速简洁模式，也将“b”显示出来\n        else\n            str.Replace(_T('B'), _T('b'));  //如果使用比特(bit)为单位，将B替换成b\n    }\n    return str;\n}\n\nCString CCommon::DataSizeToString(unsigned long long size, bool with_space)\n{\n    CString str;\n    if (size < 1024 * 10)                   //10KB以下以KB为单位，保留2位小数\n        str.Format(_T(\"%.2f KB\"), size / 1024.0);\n    else if (size < 1024 * 1024)            //1MB以下以KB为单位，保留1位小数\n        str.Format(_T(\"%.1f KB\"), size / 1024.0);\n    else if (size < 1024 * 1024 * 1024)     //1GB以下以MB为单位，保留2位小数\n        str.Format(_T(\"%.2f MB\"), size / 1024.0 / 1024.0);\n    else if (size < 1024ll * 1024 * 1024 * 1024)\n        str.Format(_T(\"%.2f GB\"), size / 1024.0 / 1024.0 / 1024.0);\n    else\n        str.Format(_T(\"%.2f TB\"), size / 1024.0 / 1024.0 / 1024.0 / 1024.0);\n    if (!with_space)\n        str.Remove(_T(' '));\n    return str;\n}\n\nCString CCommon::TemperatureToString(float temperature, const PublicSettingData& cfg)\n{\n    CString str_val;\n    if (temperature <= 0)\n        str_val = _T(\"--\");\n    else\n        str_val.Format(_T(\"%d\"), static_cast<int>(temperature));\n    if (cfg.separate_value_unit_with_space)\n        str_val += _T(' ');\n    str_val += _T(\"°C\");\n    return str_val;\n}\n\nCString CCommon::UsageToString(int usage, const PublicSettingData& cfg)\n{\n    CString str_val;\n    if (usage < 0)\n        str_val = _T(\"--\");\n    else\n        str_val.Format(_T(\"%d\"), usage);\n    if (!cfg.hide_percent)\n    {\n        if (cfg.separate_value_unit_with_space)\n            str_val += _T(' ');\n        str_val += _T('%');\n    }\n    return str_val;\n}\n\nCString CCommon::FreqToString(float freq, const PublicSettingData& cfg)\n{\n    CString str_val;\n    if (freq < 0)\n        str_val = _T(\"--\");\n    else\n        str_val.Format(_T(\"%.2f\"), freq);\n    if (cfg.separate_value_unit_with_space)\n        str_val += _T(' ');\n    str_val += _T(\"GHz\");\n    return str_val;\n}\n//CString CCommon::KBytesToString(unsigned int kb_size)\n//{\n//  CString k_bytes_str;\n//  if (kb_size < 1024)\n//      k_bytes_str.Format(_T(\"%d KB\"), kb_size);\n//  else if (kb_size < 1024 * 1024)\n//      k_bytes_str.Format(_T(\"%.2f MB\"), kb_size / 1024.0);\n//  else if (kb_size < 1024 * 1024 * 1024)\n//      k_bytes_str.Format(_T(\"%.2f GB\"), kb_size / 1024.0 / 1024.0);\n//  else\n//      k_bytes_str.Format(_T(\"%.2f TB\"), kb_size / 1024.0 / 1024.0 / 1024.0);\n//  return k_bytes_str;\n//}\n\nCString CCommon::KBytesToString(unsigned __int64 kb_size)\n{\n    CString k_bytes_str;\n    if (kb_size < 1024)\n        k_bytes_str.Format(_T(\"%d KB\"), kb_size);\n    else if (kb_size < 1024 * 1024)\n        k_bytes_str.Format(_T(\"%.2f MB\"), kb_size / 1024.0);\n    else if (kb_size < 1024 * 1024 * 1024)\n        k_bytes_str.Format(_T(\"%.2f GB\"), kb_size / 1024.0 / 1024.0);\n    else\n        k_bytes_str.Format(_T(\"%.2f TB\"), kb_size / 1024.0 / 1024.0 / 1024.0);\n    return k_bytes_str;\n}\n\n__int64 CCommon::CompareFileTime2(FILETIME time1, FILETIME time2)\n{\n    __int64 a = static_cast<__int64>(time1.dwHighDateTime) << 32 | time1.dwLowDateTime;\n    __int64 b = static_cast<__int64>(time2.dwHighDateTime) << 32 | time2.dwLowDateTime;\n    return b - a;\n}\n\nvoid CCommon::WriteLog(const char* str_text, LPCTSTR file_path)\n{\n    SYSTEMTIME cur_time;\n    GetLocalTime(&cur_time);\n    char buff[32];\n    sprintf_s(buff, \"%d/%.2d/%.2d %.2d:%.2d:%.2d.%.3d: \", cur_time.wYear, cur_time.wMonth, cur_time.wDay,\n        cur_time.wHour, cur_time.wMinute, cur_time.wSecond, cur_time.wMilliseconds);\n    ofstream file{ file_path, std::ios::app };  //以追加的方式打开日志文件\n    file << buff;\n    file << str_text << std::endl;\n}\n\nvoid CCommon::WriteLog(const wchar_t* str_text, LPCTSTR file_path)\n{\n    SYSTEMTIME cur_time;\n    GetLocalTime(&cur_time);\n    char buff[32];\n    sprintf_s(buff, \"%d/%.2d/%.2d %.2d:%.2d:%.2d.%.3d: \", cur_time.wYear, cur_time.wMonth, cur_time.wDay,\n        cur_time.wHour, cur_time.wMinute, cur_time.wSecond, cur_time.wMilliseconds);\n    ofstream file{ file_path, std::ios::app };  //以追加的方式打开日志文件\n    file << buff;\n    file << UnicodeToStr(str_text).c_str() << std::endl;\n}\n\nBOOL CCommon::CreateFileShortcut(LPCTSTR lpszLnkFileDir, LPCTSTR lpszFileName, LPCTSTR lpszLnkFileName, LPCTSTR lpszWorkDir, WORD wHotkey, LPCTSTR lpszDescription, int iShowCmd)\n{\n    if (lpszLnkFileDir == NULL)\n        return FALSE;\n\n    HRESULT hr;\n    IShellLink* pLink;  //IShellLink对象指针\n    IPersistFile* ppf; //IPersisFil对象指针\n\n                         //创建IShellLink对象\n    hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pLink);\n    if (FAILED(hr))\n        return FALSE;\n\n    //从IShellLink对象中获取IPersistFile接口\n    hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);\n    if (FAILED(hr))\n    {\n        pLink->Release();\n        return FALSE;\n    }\n\n    TCHAR file_path[MAX_PATH];\n    GetModuleFileName(NULL, file_path, MAX_PATH);\n\n    //目标\n    if (lpszFileName == NULL)\n        pLink->SetPath(file_path);\n    else\n        pLink->SetPath(lpszFileName);\n\n    //工作目录\n    if (lpszWorkDir != NULL)\n    {\n        pLink->SetWorkingDirectory(lpszWorkDir);\n    }\n    else\n    {\n        //设置工作目录为快捷方式目标所在位置\n        TCHAR workDirBuf[MAX_PATH]{};\n        if (lpszFileName == NULL)\n            //wcscpy_s(workDirBuf, file_path);\n            WStringCopy(workDirBuf, 260, file_path, 260);\n        else\n            //wcscpy_s(workDirBuf, lpszFileName);\n            WStringCopy(workDirBuf, 260, lpszFileName);\n        LPTSTR pstr = wcsrchr(workDirBuf, _T('\\\\'));\n        *pstr = _T('\\0');\n        pLink->SetWorkingDirectory(workDirBuf);\n    }\n\n    //快捷键\n    if (wHotkey != 0)\n        pLink->SetHotkey(wHotkey);\n\n    //备注\n    if (lpszDescription != NULL)\n        pLink->SetDescription(lpszDescription);\n\n    //显示方式\n    pLink->SetShowCmd(iShowCmd);\n\n\n    //快捷方式的路径 + 名称\n    wchar_t szBuffer[MAX_PATH];\n    if (lpszLnkFileName != NULL) //指定了快捷方式的名称\n        swprintf_s(szBuffer, L\"%s\\\\%s\", lpszLnkFileDir, lpszLnkFileName);\n    else\n    {\n        //没有指定名称，就从取指定文件的文件名作为快捷方式名称。\n        const wchar_t* pstr;\n        if (lpszFileName != NULL)\n            pstr = wcsrchr(lpszFileName, L'\\\\');\n        else\n            pstr = wcsrchr(file_path, L'\\\\');\n\n        if (pstr == NULL)\n        {\n            ppf->Release();\n            pLink->Release();\n            return FALSE;\n        }\n        //注意后缀名要从.exe改为.lnk\n        swprintf_s(szBuffer, L\"%s\\\\%s\", lpszLnkFileDir, pstr);\n        int nLen = wcslen(szBuffer);\n        szBuffer[nLen - 3] = L'l';\n        szBuffer[nLen - 2] = L'n';\n        szBuffer[nLen - 1] = L'k';\n    }\n    //保存快捷方式到指定目录下\n    //WCHAR  wsz[MAX_PATH];  //定义Unicode字符串\n    //MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, wsz, MAX_PATH);\n\n    hr = ppf->Save(szBuffer, TRUE);\n\n    ppf->Release();\n    pLink->Release();\n    return SUCCEEDED(hr);\n}\n\nwstring CCommon::GetStartUpPath()\n{\n    LPITEMIDLIST ppidl;\n    TCHAR pszStartUpPath[MAX_PATH]{};\n    if (SHGetSpecialFolderLocation(NULL, CSIDL_STARTUP, &ppidl) == S_OK)\n    {\n        SHGetPathFromIDList(ppidl, pszStartUpPath);\n        CoTaskMemFree(ppidl);\n    }\n    return wstring(pszStartUpPath);\n}\n\nvoid CCommon::GetFiles(const wchar_t* path, vector<wstring>& files)\n{\n    //文件句柄\n    intptr_t hFile = 0;\n    //文件信息（用Unicode保存使用_wfinddata_t，多字节字符集使用_finddata_t）\n    _wfinddata_t fileinfo;\n    wstring file_name;\n    if ((hFile = _wfindfirst(path, &fileinfo)) != -1)\n    {\n        do\n        {\n            file_name.assign(fileinfo.name);\n            if (file_name != L\".\" && file_name != L\"..\")\n                //files.push_back(wstring(path) + L\"\\\\\" + file_name);  //将文件名保存(忽略\".\"和\"..\")\n                files.push_back(L\"\\\\\" + file_name);  //将文件名保存(忽略\".\"和\"..\")\n        } while (_wfindnext(hFile, &fileinfo) == 0);\n    }\n    _findclose(hFile);\n}\n\nvoid CCommon::GetFiles(const wchar_t* path, std::function<void(const wstring&)> func)\n{\n    //文件句柄\n    intptr_t hFile = 0;\n    _wfinddata_t fileinfo;\n    wstring file_name;\n    if ((hFile = _wfindfirst(path, &fileinfo)) != -1)\n    {\n        do\n        {\n            file_name.assign(fileinfo.name);\n            if (file_name != L\".\" && file_name != L\"..\")\n                func(file_name);\n        } while (_wfindnext(hFile, &fileinfo) == 0);\n    }\n    _findclose(hFile);\n}\n\nbool CCommon::FileExist(LPCTSTR file_name)\n{\n    return (PathFileExists(file_name) != 0);\n}\n\nbool CCommon::IsFolder(const wstring& path)\n{\n    DWORD dwAttrib = GetFileAttributes(path.c_str());\n    return (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0;\n}\n\nbool CCommon::MoveAFile(LPCTSTR exist_file, LPCTSTR new_file)\n{\n    if (!FileExist(exist_file))\n        return false;\n    //if (FileExist(new_file))      //如果目标文件已经存在，则先删除它\n    //  DeleteFile(new_file);\n    return (MoveFile(exist_file, new_file) != 0);\n}\n\nSYSTEMTIME CCommon::CompareSystemTime(SYSTEMTIME a, SYSTEMTIME b)\n{\n    SYSTEMTIME result{};\n    short hour = a.wHour - b.wHour;\n    short minute = a.wMinute - b.wMinute;\n    short second = a.wSecond - b.wSecond;\n\n    if (second < 0)\n    {\n        second += 60;\n        minute--;\n    }\n\n    if (minute < 0)\n    {\n        minute += 60;\n        hour--;\n    }\n\n    if (hour < 0)\n    {\n        hour += 24;\n    }\n    result.wHour = hour;\n    result.wMinute = minute;\n    result.wSecond = second;\n    return result;\n}\n\nULONGLONG CCommon::GetCurrentTimeSinceEpochMilliseconds()\n{\n    FILETIME fileTime;\n    GetSystemTimeAsFileTime(&fileTime);  // 获取当前系统时间\n\n    // 将FILETIME转换为ULARGE_INTEGER以便计算\n    ULARGE_INTEGER uli;\n    uli.LowPart = fileTime.dwLowDateTime;\n    uli.HighPart = fileTime.dwHighDateTime;\n\n    // 从1601年1月1日到1970年1月1日的100纳秒间隔数\n    const ULONGLONG EPOCH_OFFSET = 116444736000000000ULL;\n\n    // 转换为从1970年1月1日开始的毫秒数\n    ULONGLONG millisecondsSince1970 = (uli.QuadPart - EPOCH_OFFSET) / 10000;\n    return millisecondsSince1970;\n}\n\nwstring CCommon::GetModuleDir()\n{\n    wchar_t path[MAX_PATH];\n    GetModuleFileNameW(NULL, path, MAX_PATH);\n    size_t index;\n    wstring current_path{ path };\n    index = current_path.find_last_of(L'\\\\');\n    current_path = current_path.substr(0, index + 1);\n    return current_path;\n}\n\nwstring CCommon::GetSystemDir()\n{\n    wchar_t buff[MAX_PATH];\n    GetSystemDirectory(buff, MAX_PATH);\n    return wstring(buff);\n}\n\nwstring CCommon::GetTemplateDir()\n{\n    wstring result;\n    wchar_t buff[MAX_PATH];\n    GetTempPath(MAX_PATH, buff);        //获取临时文件夹的路径\n    result = buff;\n    if (result.back() != L'\\\\' && result.back() != L'/')        //确保路径后面有斜杠\n        result.push_back(L'\\\\');\n    return result;\n}\n\nwstring CCommon::GetAppDataConfigDir()\n{\n    LPITEMIDLIST ppidl;\n    TCHAR pszAppDataPath[MAX_PATH];\n    if (SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &ppidl) == S_OK)\n    {\n        SHGetPathFromIDList(ppidl, pszAppDataPath);\n        CoTaskMemFree(ppidl);\n    }\n    wstring app_data_path{ pszAppDataPath };        //获取到C:/User/用户名/AppData/Roaming路径\n    CreateDirectory(app_data_path.c_str(), NULL);       //如果Roaming不存在，则创建它\n    app_data_path += L\"\\\\TrafficMonitor\\\\\";\n    CreateDirectory(app_data_path.c_str(), NULL);       //如果C:/User/用户名/AppData/Roaming/TrafficMonitor不存在，则创建它\n\n    return app_data_path;\n}\n\nvoid CCommon::DrawWindowText(CDC* pDC, CRect rect, LPCTSTR lpszString, COLORREF color, COLORREF back_color)\n{\n    pDC->SetTextColor(color);\n    //m_pDC->SetBkMode(TRANSPARENT);\n    //用背景色填充矩形区域\n    pDC->FillSolidRect(rect, back_color);\n    pDC->DrawText(lpszString, rect, DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);\n\n}\n\n//void CCommon::SetDrawArea(CDC * pDC, CRect rect)\n//{\n//  CRgn rgn;\n//  rgn.CreateRectRgnIndirect(rect);\n//  pDC->SelectClipRgn(&rgn);\n//}\n\n\nbool CCommon::IsForegroundFullscreen(HMONITOR hMonitor)\n{\n    if (hMonitor == NULL)\n        hMonitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY);\n    bool bFullscreen{ false };      //用于指示前台窗口是否是全屏\n    HWND hWnd{};\n    RECT rcApp{};\n\n    // 获取显示器信息\n    MONITORINFOEX monitorInfo{};\n    monitorInfo.cbSize = sizeof(monitorInfo);\n    GetMonitorInfo(hMonitor, &monitorInfo);\n    RECT monitorRect = monitorInfo.rcMonitor;\n\n    hWnd = GetForegroundWindow();   //获取当前正在与用户交互的前台窗口句柄\n    TCHAR buff[256];\n    GetClassName(hWnd, buff, 256);      //获取前台窗口的类名\n    CString class_name{ buff };\n    if (hWnd != GetDesktopWindow() && class_name != _T(\"WorkerW\") && hWnd != GetShellWindow())//如果前台窗口不是桌面窗口，也不是控制台窗口\n    {\n        GetWindowRect(hWnd, &rcApp);    //获取前台窗口的坐标\n        if (rcApp.left <= monitorRect.left && //如果前台窗口的坐标完全覆盖住桌面窗口，就表示前台窗口是全屏的\n            rcApp.top <= monitorRect.top &&\n            rcApp.right >= monitorRect.right &&\n            rcApp.bottom >= monitorRect.bottom)\n        {\n            bFullscreen = true;\n        }\n    }//如果前台窗口是桌面窗口，或者是控制台窗口，就直接返回不是全屏\n    return bFullscreen;\n}\n\nbool CCommon::CopyStringToClipboard(const wstring& str)\n{\n    if (OpenClipboard(NULL))\n    {\n        HGLOBAL clipbuffer;\n        EmptyClipboard();\n        size_t size = (str.size() + 1) * 2;\n        clipbuffer = GlobalAlloc(GMEM_DDESHARE, size);\n        memcpy_s(GlobalLock(clipbuffer), size, str.c_str(), size);\n        GlobalUnlock(clipbuffer);\n        if (SetClipboardData(CF_UNICODETEXT, clipbuffer) == NULL)\n            return false;\n        CloseClipboard();\n        return true;\n    }\n    else return false;\n}\n\n\nwstring CCommon::GetJsonValueSimple(const wstring& json_str, const wstring& name)\n{\n    wstring str_name{ L\"\\\"\" };\n    str_name += name;\n    str_name += L'\\\"';\n    size_t index = json_str.find(str_name);\n    if (index == wstring::npos)\n        return wstring();\n    index = json_str.find(L':', index + 1);\n    if (index == wstring::npos)\n        return wstring();\n    index = json_str.find_first_not_of(L\"\\\" \", index + 1);\n    size_t index_end = json_str.find_first_of(L\"\\\",]}\\r\\n\", index);\n    wstring result = json_str.substr(index, index_end - index);\n    return result;\n}\n\nbool CCommon::GetURL(const wstring& url, std::string& result, const wstring& user_agent)\n{\n    bool succeed{ false };\n    CInternetSession* pSession{};\n    CHttpFile* pfile{};\n    try\n    {\n        pSession = new CInternetSession(user_agent.c_str());\n        pfile = (CHttpFile*)pSession->OpenURL(url.c_str());\n        DWORD dwStatusCode;\n        pfile->QueryInfoStatusCode(dwStatusCode);\n        if (dwStatusCode == HTTP_STATUS_OK)\n        {\n            CString content;\n            CString data;\n            while (pfile->ReadString(data))\n            {\n                content += data;\n            }\n            result = std::string((const char*)content.GetString());\n            succeed = true;\n        }\n        pfile->Close();\n        delete pfile;\n        pSession->Close();\n    }\n    catch (CInternetException* e)\n    {\n        //写入错误日志\n        if (theApp.m_debug_log)\n        {\n            CString info = CCommon::LoadTextFormat(IDS_GET_URL_ERROR_LOG_INFO, { url, static_cast<size_t>(e->m_dwError) });\n            CCommon::WriteLog(info, theApp.m_log_path.c_str());\n        }\n        if (pfile != nullptr)\n        {\n            pfile->Close();\n            delete pfile;\n        }\n        if (pSession != nullptr)\n            pSession->Close();\n        succeed = false;\n        e->Delete();        //没有这句会造成内存泄露\n        SAFE_DELETE(pSession);\n    }\n    SAFE_DELETE(pSession);\n    return succeed;\n}\n\nbool CCommon::GetURL(const wstring& url, wstring& result, bool utf8, const wstring& user_agent)\n{\n    std::string str_result;\n    bool succeed = GetURL(url, str_result, user_agent);\n    if (succeed)\n    {\n        result = CCommon::StrToUnicode(str_result.c_str(), utf8);\n    }\n    return succeed;\n}\n\n\nvoid CCommon::GetInternetIp(wstring& ip_address, wstring& ip_location, bool global)\n{\n    wstring web_page;\n    if (GetURL(L\"https://ip.cn/\", web_page, true))\n    {\n#ifdef _DEBUG\n        ofstream file{ L\".\\\\IP_web_page.log\" };\n        file << UnicodeToStr(web_page.c_str()) << std::endl;\n#endif // _DEBUG\n        size_t index, index1;\n        index = web_page.find(L\"<code>\");\n        index1 = web_page.find(L\"</code>\", index + 6);\n        if (index == wstring::npos || index1 == wstring::npos)\n            ip_address.clear();\n        else\n            ip_address = web_page.substr(index + 6, index1 - index - 6);    //获取IP地址\n        if (ip_address.size() > 15 || ip_address.size() < 7)        //IP地址最长15个字符，最短7个字符\n            ip_address.clear();\n\n        //获取IP地址归属地\n        if (!global)\n        {\n            index = web_page.find(L\"<code>\", index1 + 7);\n            index1 = web_page.find(L\"</code>\", index + 6);\n            if (index == wstring::npos || index1 == wstring::npos)\n                ip_location.clear();\n            else\n                ip_location = web_page.substr(index + 6, index1 - index - 6);\n        }\n        else\n        {\n            index = web_page.find(L\"GeoIP\", index1 + 7);\n            index1 = web_page.find(L\"</p>\", index + 6);\n            if (index == wstring::npos || index1 == wstring::npos)\n                ip_location.clear();\n            else\n                ip_location = web_page.substr(index + 7, index1 - index - 7);\n        }\n    }\n    else\n    {\n        ip_address.clear();\n    }\n}\n\nvoid CCommon::GetInternetIp2(wstring& ip_address, wstring& ip_location, bool ipv6)\n{\n    wstring raw_string;\n    wstring user_agent{ L\"TrafficMonitor/\" };\n    user_agent += VERSION;\n    if (GetURL((ipv6 ? L\"https://v6.yinghualuo.cn/bejson\" : L\"https://v4.yinghualuo.cn/bejson\"), raw_string, true, user_agent))\n    {\n        //解析获取的json字符串\n        ip_address = GetJsonValueSimple(raw_string, L\"ip\");\n        ip_location = GetJsonValueSimple(raw_string, L\"location\");\n\n    }\n    else\n    {\n        ip_address.clear();\n        ip_location.clear();\n    }\n}\n\n\nvoid CCommon::SetRect(CRect& rect, int x, int y, int width, int height)\n{\n    rect.left = x;\n    rect.top = y;\n    rect.right = x + width;\n    rect.bottom = y + height;\n}\n\nCString CCommon::LoadText(const wchar_t* id, LPCTSTR back_str)\n{\n    CString str = theApp.m_str_table.LoadText(id).c_str();\n    if (back_str != nullptr)\n        str += back_str;\n    return str;\n}\n\nCString CCommon::LoadText(LPCTSTR front_str, const wchar_t* id, LPCTSTR back_str)\n{\n    CString str = theApp.m_str_table.LoadText(id).c_str();\n    if (back_str != nullptr)\n        str += back_str;\n    if (front_str != nullptr)\n        str = front_str + str;\n    return str;\n}\n\nCString CCommon::StringFormat(LPCTSTR format_str, const std::initializer_list<CVariant>& paras)\n{\n    CString str_rtn = format_str;\n    int index = 1;\n    for (const auto& para : paras)\n    {\n        CString para_str = para.ToString();\n        CString format_para;\n        format_para.Format(_T(\"<%%%d%%>\"), index);\n        str_rtn.Replace(format_para, para_str);\n\n        index++;\n    }\n    return str_rtn;\n}\n\nCString CCommon::LoadTextFormat(const wchar_t* id, const std::initializer_list<CVariant>& paras)\n{\n    CString str = theApp.m_str_table.LoadText(id).c_str();\n    return StringFormat(str.GetString(), paras);\n}\n\nCString CCommon::IntToString(__int64 n, bool thousand_separation, bool is_unsigned)\n{\n    wstring str = std::to_wstring(is_unsigned ? static_cast<unsigned __int64>(n) : n);\n    int count{};\n    if (thousand_separation)\n    {\n        int length{ static_cast<int>(str.size()) };\n        for (int i{ length - 1 }; i > 0; i--)\n        {\n            count++;\n            if (count % 3 == 0)\n                str.insert(i, L\",\");\n        }\n    }\n    return str.c_str();\n}\n\nvoid CCommon::NormalizeFont(LOGFONT& font)\n{\n    wstring name;\n    wstring style;\n    name = font.lfFaceName;\n    if (name.empty())\n        return;\n    if (name.back() == L' ')\n        name.pop_back();\n    size_t index = name.rfind(L' ');\n    if (index == wstring::npos)\n        return;\n    style = name.substr(index + 1);\n    bool style_acquired = false;\n    if (style == L\"Light\")\n    {\n        font.lfWeight = FW_LIGHT;\n        style_acquired = true;\n    }\n    else if (style == L\"Semilight\")\n    {\n        font.lfWeight = 350;\n        style_acquired = true;\n    }\n    else if (style == L\"Semibold\")\n    {\n        font.lfWeight = FW_SEMIBOLD;\n        style_acquired = true;\n    }\n    else if (style == L\"Bold\")\n    {\n        font.lfWeight = FW_BOLD;\n        style_acquired = true;\n    }\n    else if (style == L\"Black\")\n    {\n        font.lfWeight = FW_BLACK;\n        style_acquired = true;\n    }\n\n    if (style_acquired)\n    {\n        name = name.substr(0, index);\n    }\n    //wcsncpy_s(font.lfFaceName, name.c_str(), 32);\n    WStringCopy(font.lfFaceName, 32, name.c_str(), name.size());\n}\n\nvoid CCommon::WStringCopy(wchar_t* str_dest, int dest_size, const wchar_t* str_source, int source_size)\n{\n    if (dest_size <= 0)\n        return;\n    if (source_size <= 0 || str_source == nullptr)\n    {\n        str_dest[0] = L'\\0';\n        return;\n    }\n    int i;\n    for (i = 0; i < dest_size && i < source_size && str_source[i] != L'\\0'; i++)\n        str_dest[i] = str_source[i];\n    //确保目标字符串末尾有一个\\0\n    int copy_cnt = i;\n    if (copy_cnt < dest_size)\n        str_dest[copy_cnt] = L'\\0';\n    else\n        str_dest[dest_size - 1] = L'\\0';\n}\n\nbool CCommon::StringReplace(wstring& str, const wstring& str_old, const wstring& str_new)\n{\n    if (str.empty())\n        return false;\n    bool replaced{ false };\n    size_t pos = 0;\n    while ((pos = str.find(str_old, pos)) != std::wstring::npos)\n    {\n        str.replace(pos, str_old.length(), str_new);\n        replaced = true;\n        pos += str_new.length();    // 前进到替换后的字符串末尾\n    }\n    return replaced;\n}\n\ntemplate<class T>\nstatic double _StringSimilarDegree_LD(const T& srcString, const T& matchString)\n{\n    int n = static_cast<int>(srcString.size());\n    int m = static_cast<int>(matchString.size());\n    //int[, ] d = new int[n + 1, m + 1]; // matrix\n    vector<vector<int>> d(n + 1, vector<int>(m + 1));\n    int cost; // cost\n    // Step 1（如果其中一个字符串长度为0，则相似度为1）？\n    //if (n == 0) return (double)m / max(srcString.size(), matchString.size());\n    //if (m == 0) return (double)n / max(srcString.size(), matchString.size());\n    if (n == 0 || m == 0) return 0.0;   //如果其中一个字符串长度为0，则相似度为0\n    // Step 2\n    for (int i = 0; i <= n; i++)\n    {\n        d[i][0] = i;\n    }\n    for (int j = 0; j <= m; j++)\n    {\n        d[0][j] = j;\n    }\n    // Step 3\n    for (int i = 1; i <= n; i++)\n    {\n        //Step 4\n        for (int j = 1; j <= m; j++)\n        {\n            // Step 5\n            cost = (matchString.substr(j - 1, 1) == srcString.substr(i - 1, 1) ? 0 : 1);\n            // Step 6\n            d[i][j] = min(min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + cost);\n        }\n    }\n\n    // Step 7\n    double ds = 1 - (double)d[n][m] / max(srcString.size(), matchString.size());\n\n    return ds;\n}\n\n\ndouble CCommon::StringSimilarDegree_LD(const std::string& srcString, const std::string& matchString)\n{\n    return _StringSimilarDegree_LD(srcString, matchString);\n}\n\ndouble CCommon::StringSimilarDegree_LD(const std::wstring& srcString, const std::wstring& matchString)\n{\n    return _StringSimilarDegree_LD(srcString, matchString);\n}\n\nvoid CCommon::SetThreadLanguage(WORD language)\n{\n    if (language != 0)\n        SetThreadUILanguage(language);\n}\n\nvoid CCommon::SetColorMode(ColorMode mode)\n{\n    switch (mode)\n    {\n    case ColorMode::Default:\n        //Win8/8.1下背景色和透明色不使用纯黑色\n        if (theApp.m_win_version.IsWindows8Or8point1())\n        {\n            CTrafficMonitorApp::self->m_taskbar_data.dft_back_color = RGB(0, 0, 1);\n            CTrafficMonitorApp::self->m_taskbar_data.dft_transparent_color = RGB(0, 0, 1);\n        }\n        else\n        {\n            CTrafficMonitorApp::self->m_taskbar_data.dft_back_color = 0;\n            CTrafficMonitorApp::self->m_taskbar_data.dft_transparent_color = 0;\n        }\n        CTrafficMonitorApp::self->m_taskbar_data.dft_status_bar_color = 0x005A5A5A;\n        CTrafficMonitorApp::self->m_taskbar_data.dft_text_colors = 0x00ffffffU;\n        CTrafficMonitorApp::self->m_cfg_data.m_dft_notify_icon = 0;\n        break;\n    case ColorMode::Light:\n        CTrafficMonitorApp::self->m_taskbar_data.dft_back_color = 0x00D3D2D2;\n        CTrafficMonitorApp::self->m_taskbar_data.dft_transparent_color = 0x00D3D2D2;\n        CTrafficMonitorApp::self->m_taskbar_data.dft_status_bar_color = 0x00A5A5A5;\n        CTrafficMonitorApp::self->m_taskbar_data.dft_text_colors = 0x00000000U;\n        CTrafficMonitorApp::self->m_cfg_data.m_dft_notify_icon = 4;\n        break;\n    default:\n        break;\n    }\n}\n\nvoid CCommon::TransparentColorConvert(COLORREF& transparent_color)\n{\n    if (transparent_color == 0)\n        return;\n    BYTE r = GetRValue(transparent_color);\n    BYTE g = GetGValue(transparent_color);\n    BYTE b = GetBValue(transparent_color);\n    if (r == b)\n    {\n        if (b >= 255)\n            b--;\n        else\n            b++;\n        transparent_color = RGB(r, g, b);\n    }\n}\n\nvoid CCommon::SetDialogFont(CWnd* pDlg, CFont* pFont)\n{\n    if (pDlg->GetSafeHwnd() != NULL)\n    {\n        CWnd* pWndChild;\n        pWndChild = pDlg->GetWindow(GW_CHILD);\n        while (pWndChild)\n        {\n            pWndChild->SetFont(pFont);\n            pWndChild = pWndChild->GetWindow(GW_HWNDNEXT);\n        }\n    }\n}\n\nCString CCommon::GetTextResource(UINT id, int code_type)\n{\n    CString res_str;\n    HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(id), _T(\"TEXT\"));\n    if (hRes != NULL)\n    {\n        DWORD resSize = SizeofResource(NULL, hRes);  // 获取资源的大小\n        HGLOBAL hglobal = LoadResource(NULL, hRes);\n        if (hglobal != NULL)\n        {\n            LPVOID pResourceData = LockResource(hglobal);  // 获取资源数据的指针\n            if (code_type == 2)\n            {\n                // 资源是宽字符字符串\n                res_str = CString((const wchar_t*)pResourceData, resSize / sizeof(wchar_t));\n            }\n            else\n            {\n                // 资源是窄字符字符串\n                std::string strData((const char*)pResourceData, resSize);\n                res_str = CCommon::StrToUnicode(strData.c_str(), (code_type != 0)).c_str();\n            }\n        }\n    }\n    return res_str;\n}\n\nCString CCommon::GetLastCompileTime()\n{\n    CString str_compile_time = GetTextResource(IDR_COMPILE_TIME, 0);\n    str_compile_time.Replace(_T(\"\\r\\n\"), _T(\"\"));\n    str_compile_time.Delete(str_compile_time.GetLength() - 1, 1);\n    return str_compile_time;\n}\n\nHICON CCommon::LoadIconResource(UINT id, int size)\n{\n    return (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(id), IMAGE_ICON, size, size, 0);\n}\n\nint CCommon::GetMenuItemPosition(CMenu* pMenu, UINT id)\n{\n    int pos = -1;\n    int item_count = pMenu->GetMenuItemCount();\n    for (int i = 0; i < item_count; i++)\n    {\n        if (pMenu->GetMenuItemID(i) == id)\n        {\n            pos = i;\n            break;\n        }\n    }\n    return pos;\n}\n\n// 递归遍历菜单项并处理多语言翻译\nstatic void TranslateMenuItems(CMenu& menu)\n{\n    // 遍历菜单项\n    for (int i = 0; i < menu.GetMenuItemCount(); ++i)\n    {\n        UINT menuItemID = menu.GetMenuItemID(i);\n        CString menuText;\n        menu.GetMenuString(i, menuText, MF_BYPOSITION);\n\n        // 检查菜单项文本是否以TXT_开头\n        if (menuText.Left(4) == _T(\"TXT_\"))\n        {\n            // 获取翻译后的文本\n            std::wstring key(menuText);\n            const std::wstring& translatedText = theApp.m_str_table.LoadMenuText(key);\n\n            // 更新菜单项文本\n            menu.ModifyMenu(i, MF_BYPOSITION | MF_STRING, menuItemID, translatedText.c_str());\n        }\n\n        if (menuItemID == -1)\n        {\n            // 这是一个弹出菜单（子菜单），递归处理\n            CMenu* pSubMenu = menu.GetSubMenu(i);\n            if (pSubMenu)\n            {\n                TranslateMenuItems(*pSubMenu); // 递归调用\n            }\n        }\n    }\n}\n\nvoid CCommon::LoadMenuResource(CMenu& menu, UINT res_id)\n{\n    // 加载菜单资源\n    menu.LoadMenu(res_id);\n\n    // 处理菜单项翻译\n    TranslateMenuItems(menu);\n}\n\nbool CCommon::IsColorSimilar(COLORREF color1, COLORREF color2)\n{\n    const int DIFF{ 24 };\n    return (std::abs(GetRValue(color1) - GetRValue(color2)) < DIFF\n        && std::abs(GetGValue(color1) - GetGValue(color2)) < DIFF\n        && std::abs(GetBValue(color1) - GetBValue(color2)) < DIFF);\n}\n\nint CCommon::CountOneBits(unsigned int value)\n{\n    int count = 0;\n    while (value != 0)\n    {\n        if (value % 2 == 1)\n        {\n            count++;\n        }\n        value = value >> 1;\n    }\n    return count;\n}\n\nvoid CCommon::SetNumberBit(unsigned int& num, int bit, bool value)\n{\n    if (value)\n    {\n        num |= (1 << bit);\n    }\n    else\n    {\n        num &= ~(1 << bit);\n    }\n}\n\nbool CCommon::GetNumberBit(unsigned int num, int bit)\n{\n    return (num & (1 << bit)) != 0;\n}\n\nCOLORREF CCommon::GetWindowsThemeColor()\n{\n    DWORD crColorization;\n    BOOL fOpaqueBlend;\n    COLORREF theme_color{};\n    HRESULT result = DwmGetColorizationColor(&crColorization, &fOpaqueBlend);\n    if (result == S_OK)\n    {\n        BYTE r, g, b;\n        r = (crColorization >> 16) % 256;\n        g = (crColorization >> 8) % 256;\n        b = crColorization % 256;\n        theme_color = RGB(r, g, b);\n    }\n    return theme_color;\n}\n\nCString CCommon::GetErrorMessage(DWORD error_code)\n{\n    CString error_msg;\n    if (error_code != 0)\n    {\n        LPVOID lpMsgBuf = nullptr;\n        FormatMessage(\n            FORMAT_MESSAGE_ALLOCATE_BUFFER |\n            FORMAT_MESSAGE_FROM_SYSTEM |\n            FORMAT_MESSAGE_IGNORE_INSERTS,\n            NULL,\n            error_code,\n            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n            (LPTSTR)&lpMsgBuf,\n            0,\n            NULL);\n\n        if (lpMsgBuf != nullptr)\n            error_msg = (LPCTSTR)lpMsgBuf;\n\n        LocalFree(lpMsgBuf);\n    }\n    return error_msg;\n}\n"
  },
  {
    "path": "TrafficMonitor/Common.h",
    "content": "﻿#pragma once\n#include \"CommonData.h\"\n#include \"CVariant.h\"\n#include <set>\n#include <functional>\n\nclass CCommon\n{\npublic:\n    CCommon();\n    ~CCommon();\n    //将const char*字符串转换成宽字符字符串\n    static wstring StrToUnicode(const char* str, bool utf8 = false);\n\n    static string UnicodeToStr(const wchar_t* wstr, bool utf8 = false);\n\n    static wstring AsciiToUnicode(const string& str);\n    static string AsciiToStr(const std::wstring& wstr);\n\n    static void StringNormalize(std::string& str);\n    static void StringNormalize(std::wstring& str);\n\n    //将一个字符串分割成若干个字符（模板类型只能为string或wstring）\n    //str: 原始字符串\n    //div_ch: 用于分割的字符\n    //result: 接收分割后的结果\n    static void StringSplit(const std::string& str, char div_ch, vector<std::string>& results, bool skip_empty = true, bool trim = true);\n    static void StringSplit(const std::wstring& str, wchar_t div_ch, vector<std::wstring>& results, bool skip_empty = true, bool trim = true);\n\n    static void StringSplit(const std::string& str, const std::string& div_str, vector<std::string>& results, bool skip_empty = true, bool trim = true);\n    static void StringSplit(const std::wstring& str, const std::wstring& div_str, vector<std::wstring>& results, bool skip_empty = true, bool trim = true);\n\n    static bool StringTransform(std::string& str, bool upper);\n    static bool StringTransform(std::wstring& str, bool upper);\n\n    //读取文件内容\n    static bool GetFileContent(const wchar_t* file_path, string& contents_buff, bool binary = true);\n\n    //读取文件内容\n    //file_path: 文件的路径\n    //length: 文件的长度\n    //binary: 是否以进制方式读取\n    //返回值: 读取成功返回读取到的文件内容的const char类型的指针，在使用完毕后这个指针需要自行使用delete释放。读取失败返回nullptr\n    static const char* GetFileContent(const wchar_t* file_path, size_t& length, bool binary = true);\n\n    /*根据数据的大小转换成以KB、MB、GB为单位的字符串\n    size：数据的字节数\n    返回值：转换后的字符串\n    */\n    static CString DataSizeToString(unsigned long long size, const PublicSettingData& cfg);\n\n    /*根据数据的大小转换成以KB、MB、GB为单位的字符串\n    size：数据的字节数\n    with_space：数值和单位是否使用空格分隔\n    返回值：转换后的字符串\n    */\n    static CString DataSizeToString(unsigned long long size, bool with_space = true);\n\n    //将温度信息转换成字符串\n    static CString TemperatureToString(float temperature, const PublicSettingData& cfg);\n\n    //将使用率转换成字符串\n    static CString UsageToString(int usage, const PublicSettingData& cfg);\n    static CString FreqToString(float usage, const PublicSettingData& cfg);\n    //static CString KBytesToString(unsigned int kb_size);\n    static CString KBytesToString(unsigned __int64 kb_size);\n\n    //返回两个FILETIME结构的时间差\n    static __int64 CompareFileTime2(FILETIME time1, FILETIME time2);\n\n    //将一个日志信息str_text写入到file_path文件中\n    static void WriteLog(const char* str_text, LPCTSTR file_path);\n    static void WriteLog(const wchar_t* str_text, LPCTSTR file_path);\n\n    /*\n    函数功能：对指定文件在指定的目录下创建其快捷方式\n    函数参数：\n    lpszLnkFileDir  指定目录，不能为NULL。\n    lpszFileName    指定文件，为NULL表示当前进程的EXE文件。\n    lpszLnkFileName 快捷方式名称，为NULL表示EXE文件名。\n    wHotkey         为0表示不设置快捷键\n    pszDescription  备注\n    iShowCmd        运行方式，默认为常规窗口\n    */\n    static BOOL CreateFileShortcut(LPCTSTR lpszLnkFileDir, LPCTSTR lpszFileName = NULL, LPCTSTR lpszLnkFileName = NULL, LPCTSTR lpszWorkDir = NULL, WORD wHotkey = 0, LPCTSTR lpszDescription = NULL, int iShowCmd = SW_SHOWNORMAL);\n\n    //获取开始菜单“所有程序”中的“启动”目录的路径\n    static wstring GetStartUpPath();\n\n    //获取path路径下的文件或文件夹，并将文件或文件夹名称保存在files容器中。\n    static void GetFiles(const wchar_t* path, vector<wstring>& files);\n\n    //获取path路径下的文件或文件夹，每次遍历时调用函数对象func\n    //path: 查找的路径\n    //func: 可以是一个函数对象或lambda表达式，参数是遍历到的文件或文件夹名\n    static void GetFiles(const wchar_t* path, std::function<void(const wstring&)> func);\n\n    //判断一个文件是否存在\n    static bool FileExist(LPCTSTR file_name);\n\n    //判断是否是文件夹\n    static bool IsFolder(const wstring& path);\n\n    static bool MoveAFile(LPCTSTR exist_file, LPCTSTR new_file);\n\n    //计算两个SYSTEMTIME结构时间的差（a-b，只保留时、分、秒）\n    static SYSTEMTIME CompareSystemTime(SYSTEMTIME a, SYSTEMTIME b);\n\n    //获取从1970年1月1日到现在的毫秒数\n    static ULONGLONG GetCurrentTimeSinceEpochMilliseconds();\n\n    //获取当前程序的目录\n    static wstring GetModuleDir();\n\n    //获取system32文件夹的路径\n    static wstring GetSystemDir();\n\n    //获取临时文件夹的路径\n    static wstring GetTemplateDir();\n\n    //获取Appdata/Local/TrafficMonitor的目录，如果不存在，则会自动创建\n    static wstring GetAppDataConfigDir();\n\n    //在指定位置绘制文本\n    static void DrawWindowText(CDC* pDC, CRect rect, LPCTSTR lpszString, COLORREF color, COLORREF back_color);\n\n    ////设置绘图的剪辑区域\n    //static void SetDrawArea(CDC* pDC, CRect rect);\n\n    /**\n     * 判断当前正在与用户交互的前台窗口是否是全屏的\n     * @param[in] hMonitor 要判断的显示器（如果为空，则指定为主显示器）\n     * @return \n     */\n    static bool IsForegroundFullscreen(HMONITOR hMonitor = NULL);\n\n    //将一个字符串保存到剪贴板\n    static bool CopyStringToClipboard(const wstring& str);\n\n    static wstring GetJsonValueSimple(const wstring& json_str, const wstring& name);\n\n    //获取URL的内容\n    static bool GetURL(const wstring& url, std::string& result, const wstring& user_agent = wstring());\n    static bool GetURL(const wstring& url, wstring& result, bool utf8 = false, const wstring& user_agent = wstring());\n\n    //获取外网IP地址和IP归属地\n    static void GetInternetIp(wstring& ip_address, wstring& ip_location, bool global);\n\n    static void GetInternetIp2(wstring& ip_address, wstring& ip_location, bool ipv6);\n\n    static void SetRect(CRect& rect, int x, int y, int width, int height);\n\n    //从资源文件载入字符串。其中，front_str、back_str为载入字符串时需要在前面或后面添加的字符串\n    static CString LoadText(const wchar_t* id, LPCTSTR back_str = nullptr);\n    static CString LoadText(LPCTSTR front_str, const wchar_t* id, LPCTSTR back_str);\n\n    //安全的格式化字符串，将format_str中形如<%序号%>的字符串替换成初始化列表paras中的元素，元素支持int/double/LPCTSTR/CString格式，序号从1开始\n    static CString StringFormat(LPCTSTR format_str, const std::initializer_list<CVariant>& paras);\n\n    //从资源文件中载入字符串，并将资源字符串中形如<%序号%>的字符串替换成可变参数列表中的参数\n    static CString LoadTextFormat(const wchar_t* id, const std::initializer_list<CVariant>& paras);\n\n    //将int类型转换成字符串\n    //n：要转换的数值\n    //thousand_separation：是否要每隔3位数使用逗号分隔\n    //is_unsigned：数值是否是无符号的\n    static CString IntToString(__int64 n, bool thousand_separation = false, bool is_unsigned = false);\n\n    //删除字体名称后面的Bold、Light等字符串，并根据这些字符串设置字体粗细\n    static void NormalizeFont(LOGFONT& font);\n\n    //安全的字符串复制函数\n    static void WStringCopy(wchar_t* str_dest, int dest_size, const wchar_t* str_source, int source_size = INT_MAX);\n\n    //字符串替换\n    static bool StringReplace(wstring& str, const wstring& str_old, const wstring& str_new);\n\n    /// <summary>\n    /// 字符串相似度算法-编辑距离法\n    /// </summary>\n    /// <returns>返回的值为0~1，越大相似度越高</returns>\n    static double StringSimilarDegree_LD(const std::string& srcString, const std::string& matchString);\n    static double StringSimilarDegree_LD(const std::wstring& srcString, const std::wstring& matchString);\n    \n    //设置线程语言\n    static void SetThreadLanguage(WORD language);\n\n    //设置颜色模式\n    static void SetColorMode(ColorMode mode);\n\n    //经过测试发现，似乎当透明色的R和B值相等时，会出现右击任务栏窗口时无法弹出右键菜单，而是弹出系统任务栏右键菜单的问题\n    //为了解决这个问题，需要将颜色值进行转换\n    //此函数的作用是判断一个颜色的R和B值是否相等，如果是则将颜色的B值加1（如果B==255，则减1）\n    static void TransparentColorConvert(COLORREF& transparent_color);\n\n    static void SetDialogFont(CWnd* pDlg, CFont* pFont);\n\n    //从资源加载自定义文本资源。id：资源的ID，code_type：文本的编码格式：0:ANSI, 1:UTF8, 2:UTF16\n    static CString GetTextResource(UINT id, int code_type);\n\n    //从资源文件读取上次编译时间\n    static CString GetLastCompileTime();\n\n    //从资源加载一个图标\n    static HICON LoadIconResource(UINT id, int size);\n\n    //获取一个菜单项的序号\n    static int GetMenuItemPosition(CMenu* pMenu, UINT id);\n\n    //从资源文件加载一个菜单，并处理文本翻译\n    static void LoadMenuResource(CMenu& menu, UINT res_id);\n\n    static bool IsColorSimilar(COLORREF color1, COLORREF color2);\n\n    //计算二进制中1的个数\n    static int CountOneBits(unsigned int value);\n\n    //设置一个数字的某个bit位\n    static void SetNumberBit(unsigned int& num, int bit, bool value);\n\n    //获取一个数字的某个bit位\n    static bool GetNumberBit(unsigned int num, int bit);\n\n    //在不排序的情况下删除vector中的重复元素\n    template<class T>\n    static void RemoveVectorDuplicateItem(vector<T>& vec)\n    {\n        std::set<T> si;\n        for (auto it = vec.begin(); it != vec.end();)\n        {\n            if (si.count(*it) == 0)//这里判断当前元素是否已经出现过，若没有出现过则将该元素保留，并做标记\n            {\n                si.insert(*it);\n                ++it;\n            }\n            else//如果前面已经出现过，则删除当前元素\n            {\n                it = vec.erase(it);//这里删除it指向的元素\n            }\n        }\n    }\n\n    /**\n     * @brief   限制一个数的范围\n     * @param   value 要限制范围的值\n     * @param   min_value 最小值\n     * @param   max_value 最大值\n     */\n    template<class T>\n    static void ValidatValue(T& value, const T& min_value, const T& max_value)\n    {\n        if (value < min_value)\n            value = min_value;\n        if (value > max_value)\n            value = max_value;\n    }\n\n    //获取Windows主题颜色\n    static COLORREF GetWindowsThemeColor();\n\n    static CString GetErrorMessage(DWORD error_code);\n};\n\n/**\n * @brief 编译期获取数组长度\n *\n * @tparam T 数组元素类型\n * @tparam N 编译期推断的数组长度\n * @return constexpr std::size_t 编译期推断的数组长度\n */\ntemplate <typename T, std::size_t N>\nconstexpr std::size_t GetArrayLength(const T (&)[N]) noexcept\n{\n    return N;\n}\n\n/**\n * @brief 析构StaticVariableWrapper包装对象前默认执行的函数，实际上无操作\n *\n * @tparam T\n */\ntemplate <class T>\nclass CDefaultStaticVariableWrapperDtor\n{\npublic:\n    void operator()(T*){};\n};\n/**\n * @brief 设计上用于静态变量包装类，用于自定义变量默认初始化后行为和析构前行为\n *\n * @tparam T 要被包装的类型\n * @tparam DTOR 自定义执行析构函数前的行为\n */\ntemplate <class T, class DTOR = CDefaultStaticVariableWrapperDtor<T>>\nclass CStaticVariableWrapper : private DTOR\n{\nprivate:\n    T m_content;\n\npublic:\n    /**\n     * @brief 构造一个StaticVariableWrapper\n     *\n     * @tparam CTOR 自定义变量默认初始化后的函数类型\n     * @param ctor 自定义变量默认初始化后的行为，传入变量的指针作为参数\n     * @param dtor 自定义变量执行析构函数前的行为，传入变量的指针作为参数\n     */\n    template <class CTOR>\n    CStaticVariableWrapper(CTOR ctor, DTOR dtor = {})\n        : DTOR{dtor}\n    {\n        ctor(std::addressof(m_content));\n    }\n    ~CStaticVariableWrapper()\n    {\n        (*static_cast<DTOR*>(this))(std::addressof(m_content));\n    }\n    T& Get() noexcept\n    {\n        return m_content;\n    }\n    const T& Get() const noexcept\n    {\n        return m_content;\n    }\n};\n/**\n * @brief 生成静态变量包装类的函数\n *\n * @tparam T 要被包装的类型\n * @tparam CTOR 自定义变量默认初始化后的函数类型\n * @tparam DTOR 自定义变量执行析构函数前的函数类型\n * @param ctor 自定义变量默认初始化后的行为，传入变量的指针作为参数\n * @param dtor 自定义变量执行析构函数前的行为，传入变量的指针作为参数\n * @return CStaticVariableWrapper<T, DTOR> 包装后的变量，已经初始化\n */\ntemplate <class T, class CTOR, class DTOR = CDefaultStaticVariableWrapperDtor<T>>\nauto MakeStaticVariableWrapper(CTOR ctor, DTOR dtor = {})\n    -> CStaticVariableWrapper<T, DTOR>\n{\n    return {ctor, dtor};\n}\n\n/**\n * @brief 调用指针指向的对象的对应类型的析构函数\n *\n * @tparam T 传入的移除了指针后的类型\n * @param p_memory 指向要执行析构函数的对象的指针\n */\ntemplate <class T>\nvoid Destroy(T* p_memory)\n{\n    p_memory->~T();\n}\n\ntemplate <class T, class... Args>\nvoid EmplaceAt(T* p_memory, Args&&... args)\n{\n    ::new (p_memory) T(std::forward<Args>(args)...);\n}\n"
  },
  {
    "path": "TrafficMonitor/CommonData.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"CommonData.h\"\n#include \"Common.h\"\n#include \"CalendarHelper.h\"\n#include \"TrafficMonitor.h\"\n#include \"WindowsSettingHelper.h\"\n\n///////////////////////////////////////////////////////////////////////////////////\nint Date::week() const\n{\n    //计算当前是一年的第几天\n    int days{};\n    for (int i{ 1 }; i < month; i++)\n    {\n        days += CCalendarHelper::DaysInMonth(year, i);\n    }\n    days += day;\n    //计算这一年的1月1日是星期几\n    int week_day = CCalendarHelper::CaculateWeekDay(year, 1, 1);\n    if (theApp.m_cfg_data.m_sunday_first)\n    {\n        days += (week_day - 1);\n    }\n    else\n    {\n        days += (week_day - 2);\n    }\n    return days / 7 + 1;\n}\n\nbool Date::DateGreater(const Date& a, const Date& b)\n{\n    if (a.year != b.year)\n        return a.year > b.year;\n    else if (a.month != b.month)\n        return a.month > b.month;\n    else if (a.day != b.day)\n        return a.day > b.day;\n    else\n        return false;\n}\n\nbool Date::DateEqual(const Date& a, const Date& b)\n{\n    return a.year == b.year && a.month == b.month && a.day == b.day;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////////\n//HistoryTraffic\nunsigned __int64 HistoryTraffic::kBytes() const\n{\n    return up_kBytes + down_kBytes;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////////\nwstring& DispStrings::Get(CommonDisplayItem item)\n{\n    return map_str[item];\n}\n\nconst wstring& DispStrings::GetConst(CommonDisplayItem item) const\n{\n    auto iter = map_str.find(item);\n    if (iter != map_str.end())\n        return iter->second;\n    static wstring empty_str;\n    return empty_str;\n}\n\nconst std::map<CommonDisplayItem, wstring>& DispStrings::GetAllItems() const\n{\n    return map_str;\n}\n\nbool DispStrings::operator==(const DispStrings& disp_str) const\n{\n    return map_str == disp_str.map_str;\n}\n\nbool DispStrings::IsInvalid() const\n{\n    return map_str.empty();\n}\n\nvoid DispStrings::Load(const std::wstring& plugin_id, const std::wstring& disp_str)\n{\n    auto plugin = theApp.m_plugins.GetItemById(plugin_id);\n    if (plugin != nullptr)\n    {\n        map_str[plugin] = disp_str;\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////////\nbool FontInfo::operator==(const FontInfo& a) const\n{\n    return name == a.name && size == a.size && bold == a.bold && italic == a.italic\n        && underline == a.underline && strike_out == a.strike_out;\n}\n\n///////////////////////////////////////////////////////////////////////////////////\nbool StringSet::Contains(const std::wstring& str) const\n{\n    return string_set.count(str) != 0;\n}\n\nvoid StringSet::SetStrContained(const std::wstring& str, bool contained)\n{\n    if (contained)\n        string_set.insert(str);\n    else\n        string_set.erase(str);\n}\n\nvoid StringSet::FromString(const std::wstring& str)\n{\n    std::vector<std::wstring> item_vect;\n    CCommon::StringSplit(str, L',', item_vect);\n    string_set.clear();\n    for (const auto& i : item_vect)\n        string_set.insert(i);\n}\n\nstd::wstring StringSet::ToString() const\n{\n    std::vector<std::wstring> item_vect;\n    for (const auto& i : string_set)\n        item_vect.push_back(i);\n    std::wstring item_str;\n    for (const auto& i : item_vect)\n    {\n        item_str += i;\n        item_str += L',';\n    }\n    if (!item_str.empty())\n        item_str.pop_back();\n    return item_str;\n}\n\nvoid StringSet::FromVector(const std::vector<std::wstring>& vec)\n{\n    string_set.clear();\n    for (const auto& str : vec)\n        string_set.insert(str);\n}\n\nstd::vector<std::wstring> StringSet::ToVector() const\n{\n    std::vector<std::wstring> vec;\n    for (const auto& str : string_set)\n        vec.push_back(str);\n    return vec;\n}\n\nstd::set<std::wstring>& StringSet::data()\n{\n    return string_set;\n}\n\n///////////////////////////////////////////////////////////////////////////////////\nbool SkinSettingData::IsEmpty() const\n{\n    return font.name.IsEmpty() && disp_str.GetAllItems().empty() && text_colors.empty();\n}\n\nbool SkinSettingData::operator==(const SkinSettingData& a) const\n{\n    return font == a.font && disp_str == a.disp_str && text_colors == a.text_colors && specify_each_item_color == a.specify_each_item_color;\n}\n\n///////////////////////////////////////////////////////////////////////////////////\nvoid MainWndSettingData::FormSkinSettingData(const SkinSettingData& sking_setting_data)\n{\n    font = sking_setting_data.font;\n    disp_str = sking_setting_data.disp_str;\n    text_colors = sking_setting_data.text_colors;\n    specify_each_item_color = sking_setting_data.specify_each_item_color;\n}\n\nSkinSettingData MainWndSettingData::ToSkinSettingData() const\n{\n    SkinSettingData sking_setting_data;\n    sking_setting_data.font = font;\n    sking_setting_data.disp_str = disp_str;\n    sking_setting_data.text_colors = text_colors;\n    sking_setting_data.specify_each_item_color = specify_each_item_color;\n    return sking_setting_data;\n}\n\n///////////////////////////////////////////////////////////////////////////////////\nbool TaskBarSettingData::IsTaskbarTransparent() const\n{\n    if (CWindowsSettingHelper::IsWindows10LightTheme() || theApp.m_win_version.IsWindows8Or8point1() || theApp.IsWindows11Taskbar())\n        return (transparent_color == back_color);\n    else\n        return transparent_color == 0;\n}\n\nvoid TaskBarSettingData::SetTaskabrTransparent(bool transparent)\n{\n    if (transparent)\n    {\n        if (CWindowsSettingHelper::IsWindows10LightTheme() || theApp.m_win_version.IsWindows8Or8point1() || theApp.IsWindows11Taskbar())\n        {\n            //浅色模式下要设置任务栏窗口透明，只需将透明色设置成和背景色一样即可\n            CCommon::TransparentColorConvert(back_color);\n            transparent_color = back_color;\n        }\n        else\n        {\n            //深色模式下，背景色透明将透明色设置成黑色\n            transparent_color = 0;\n        }\n    }\n    else\n    {\n        //要设置任务栏窗口不透明，只需将透明色设置成和背景色不一样即可\n        if (back_color != TASKBAR_TRANSPARENT_COLOR1)\n            transparent_color = TASKBAR_TRANSPARENT_COLOR1;\n        else\n            transparent_color = TASKBAR_TRANSPARENT_COLOR2;\n    }\n}\n\nvoid TaskBarSettingData::ValidItemSpace()\n{\n    if (item_space < 0)\n        item_space = 0;\n    if (item_space > 32)\n        item_space = 32;\n}\n\nvoid TaskBarSettingData::ValidVerticalMargin()\n{\n    if (vertical_margin < -10)\n        vertical_margin = -10;\n    if (vertical_margin > 10)\n        vertical_margin = 10;\n}\n\nvoid TaskBarSettingData::ValidWindowOffsetTop()\n{\n    if (window_offset_top < -20)\n        window_offset_top = -20;\n    if (window_offset_top > 20)\n        window_offset_top = 20;\n}\n\nvoid TaskBarSettingData::ValidWindowOffsetLeft()\n{\n    if (window_offset_left < -800)\n        window_offset_top = -800;\n    if (window_offset_top > 800)\n        window_offset_top = 800;\n}\n\nunsigned __int64 TaskBarSettingData::GetNetspeedFigureMaxValueInBytes() const\n{\n    if (netspeed_figure_max_value_unit == 0)        //单位为KB\n        return static_cast<unsigned __int64>(netspeed_figure_max_value) * 1024;\n    else\n        return static_cast<unsigned __int64>(netspeed_figure_max_value) * 1024 * 1024;\n}\n\nCOLORREF TaskBarSettingData::GetUsageGraphColor() const\n{\n    if (graph_color_following_system)\n    {\n        COLORREF theme_color = theApp.GetThemeColor();\n        //转换为HLS\n        double h, l, s;\n        CDrawingManager::RGBtoHSL(theme_color, &h, &s, &l);\n        //根据当前系统深浅色模式指定亮度\n        if (theApp.m_last_light_mode)\n        {\n            //浅色任务栏，将亮度设为0.7\n            l = 0.7;\n        }\n        else\n        {\n            //深色任务栏，将亮度设为0.4\n            l = 0.4;\n        }\n        //转换回RGB\n        COLORREF graph_color = CDrawingManager::HLStoRGB_ONE(h, l, s);\n        return graph_color;\n    }\n    else\n    {\n        return status_bar_color;\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/CommonData.h",
    "content": "﻿//此文件包含全局结构体、枚举类型的定义\n#pragma once\n#include \"stdafx.h\"\n#include \"TaskbarItemOrderHelper.h\"\n\nstruct Date\n{\n    int year{};\n    int month{};\n    int day{};\n\n    int week() const;       //该日期是一年的第几周\n\n    //比较两个HistoryTraffic对象的日期，如果a的时间大于b，则返回true\n    static bool DateGreater(const Date& a, const Date& b);\n\n    //判断两个HistoryTraffic对象的日期是否相等\n    static bool DateEqual(const Date& a, const Date& b);\n\n};\n\n//储存某一天的历史流量\nstruct HistoryTraffic : public Date\n{\n    //当天使用的流量（以KB为单位）\n    unsigned __int64 up_kBytes{};\n    unsigned __int64 down_kBytes{};\n    bool mixed{ true };     //如果不区分上传和下载流量，则为true\n\n    unsigned __int64 kBytes() const;\n\n};\n\n//历史流量统计中用于指示不同范围内的流量的颜色\n#define TRAFFIC_COLOR_BLUE RGB(0, 183, 238)\n#define TRAFFIC_COLOR_GREEN RGB(128, 194, 105)\n#define TRAFFIC_COLOR_YELLOE RGB(255, 216, 58)\n#define TRAFFIC_COLOR_RED RGB(255, 95, 74)\n#define TRAFFIC_COLOR_DARK_RED RGB(166, 19, 0)\n\n//网速单位\nenum class SpeedUnit\n{\n    AUTO,       //自动\n    KBPS,       //KB/s\n    MBPS        //MB/s\n};\n\n\n//硬件监控的项目\nenum HardwareItem\n{\n    HI_CPU = 1 << 0,        //CPU\n    HI_GPU = 1 << 1,        //显卡\n    HI_HDD = 1 << 2,        //硬盘\n    HI_MBD = 1 << 3         //主板\n};\n\n#define DEF_CH L'\\\"'        //写入和读取ini文件字符串时，在字符串前后添加的字符\nstruct DispStrings      //显示的文本\n{\nprivate:\n    std::map<CommonDisplayItem, wstring> map_str;\n\npublic:\n    //获取一个显示的文本\n    wstring& Get(CommonDisplayItem item);\n    const wstring& GetConst(CommonDisplayItem item) const;\n\n    const std::map<CommonDisplayItem, wstring>& GetAllItems() const;\n\n    bool operator==(const DispStrings& disp_str) const;\n\n    //载入一个插件项目的显示文本\n    void Load(const std::wstring& plugin_id, const std::wstring& disp_str);\n\n    //是否无效\n    bool IsInvalid() const;\n};\n\n//鼠标双击窗口的动作\nenum class DoubleClickAction\n{\n    CONNECTION_INFO,    //连接详情\n    HISTORY_TRAFFIC,    //历史流量统计\n    SHOW_MORE_INFO,     //显示更多信息\n    OPTIONS,            //选项设置\n    TASK_MANAGER,       //任务管理器\n    SEPCIFIC_APP,       //指定应用程序\n    CHANGE_SKIN,        //更换皮肤\n    NONE                //不执行任何动作\n};\n\n//颜色模式\nenum class ColorMode\n{\n    Default, //默认颜色\n    Light   //浅色\n};\n\n//将字号转成LOGFONT结构中的lfHeight\ninline int FontSizeToLfHeight(int font_size, int dpi = 0)\n{\n    if (dpi == 0)\n    {\n        HDC hDC = ::GetDC(HWND_DESKTOP);\n        dpi = GetDeviceCaps(hDC, LOGPIXELSY);\n        ::ReleaseDC(HWND_DESKTOP, hDC);\n    }\n    int lfHeight = -MulDiv(font_size, dpi, 72);\n    return lfHeight;\n}\n\n//字体\nstruct FontInfo\n{\n    CString name;       //字体名称\n    int size{ 9 };      //字体大小\n    bool bold{};        //粗体\n    bool italic{};      //斜体\n    bool underline{};   //下划线\n    bool strike_out{};  //删除线\n\n    bool operator==(const FontInfo& a) const;\n\n    //创建一个CFont对象\n    void Create(CFont& font, int dpi = 0) const\n    {\n        font.CreateFont(\n            FontSizeToLfHeight(size, dpi), // nHeight\n            0, // nWidth\n            0, // nEscapement\n            0, // nOrientation\n            (bold ? FW_BOLD : FW_NORMAL), // nWeight\n            italic, // bItalic\n            underline, // bUnderline\n            strike_out, // cStrikeOut\n            DEFAULT_CHARSET, // nCharSet\n            OUT_DEFAULT_PRECIS, // nOutPrecision\n            CLIP_DEFAULT_PRECIS, // nClipPrecision\n            DEFAULT_QUALITY, // nQuality\n            DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily\n            name);\n    }\n};\n\n//历史流量统计列表视图中显示模式\nenum class HistoryTrafficViewType\n{\n    HV_DAY,         //日视图\n    HV_WEEK,        //周视图\n    HV_MONTH,          //月视图\n    HV_QUARTER,     //季视图\n    HV_YEAR            //年视图\n};\n\nstruct StringSet\n{\npublic:\n    bool Contains(const std::wstring& str) const;\n    void SetStrContained(const std::wstring& str, bool contained);\n    void FromString(const std::wstring& str);\n    std::wstring ToString() const;\n    void FromVector(const std::vector<std::wstring>& vec);\n    std::vector<std::wstring> ToVector() const;\n    std::set<std::wstring>& data();\nprivate:\n    std::set<std::wstring> string_set;\n};\n\n//选项设置数据\nstruct MainConfigData\n{\n    int m_transparency{ 100 };          //窗口透明度\n    bool m_show_more_info{ false };     //显示更多信息\n    bool m_show_task_bar_wnd{ false };  //显示任务栏窗口\n    bool m_hide_main_window;            //隐藏主窗口\n    //bool m_tbar_show_cpu_memory;      //任务栏窗口显示CPU和内存利用率\n\n    int m_position_x;   //窗口位置的x坐标\n    int m_position_y;   //窗口位置的y坐标\n\n    bool m_auto_select{ false };    //自动选择连接\n    bool m_select_all{ false };     //统计所有连接的网速\n    string m_connection_name;      //当前选择网络的名称\n\n    wstring m_skin_name;            //选择的皮肤的名称\n\n    bool skin_auto_adapt{ false };  //根据深色/浅色模式自动切换皮肤\n    wstring skin_name_light_mode;   //浅色模式下的皮肤名称\n    wstring skin_name_dark_mode;    //深色模式下的皮肤名称\n\n    int m_dft_notify_icon = 0;      //默认的通知图标(用于区分win10的深色和浅色模式)\n    int m_notify_icon_selected{};   //要显示的通知区图标\n    bool m_notify_icon_auto_adapt{ false }; //通知区图标是否自动适应Win10深浅色模式\n\n    //bool m_show_internet_ip{ false };     //是否在“连接详情”对话框中显示外网IP地址\n    bool m_use_log_scale{ false };          //“历史流量统计”对话框中绘制表示历史流量数值的矩形时是否使用对数比例\n    HistoryTrafficViewType m_view_type{};\n    bool m_sunday_first{ true };            //是否将周日作为一周的第一天\n    StringSet plugin_disabled;      //已禁用的插件\n\n};\n\n//内存显示方式\nenum class MemoryDisplay\n{\n    USAGE_PERCENTAGE,       //已使用百分比\n    MEMORY_USED,            //内存已使用\n    MEMORY_AVAILABLE        //内存可用\n};\n\n//为每个皮肤单独保存的数据\nstruct SkinSettingData\n{\n    FontInfo font;          //字体\n    DispStrings disp_str;   //显示的文本\n    std::map<CommonDisplayItem, COLORREF> text_colors{};    //文字的颜色\n    bool specify_each_item_color{};\n\n    bool IsEmpty() const;\n    bool operator==(const SkinSettingData& a) const;\n};\n\n//选项设置中“主窗口设置”和“任务栏窗口设置”中公共的数据（不使用此结构体创建对象）\nstruct PublicSettingData\n{\n    bool specify_each_item_color{ false };      //是否指定每个项目的颜色\n    FontInfo font;          //字体\n    DispStrings disp_str;   //显示的文本\n    bool speed_short_mode{ false };     //网速显示简洁模式（减少小数点的位数，单位不显示“B”）\n    bool separate_value_unit_with_space{ true };    //网速数值和单位用空格分隔\n    bool show_tool_tip{ true };         //显示鼠标提示\n    MemoryDisplay memory_display{ MemoryDisplay::USAGE_PERCENTAGE };    //内存显示方式\n\n    bool unit_byte{ true };             //使用字节(B)而不是比特(b)为单位\n    SpeedUnit speed_unit;       //网速的单位\n    bool hide_unit;         //隐藏单位\n    bool hide_percent;      //隐藏百分号\n    DoubleClickAction double_click_action;      //鼠标双击动作\n    wstring double_click_exe;   //鼠标双击动作为打开指定应用程序时，打开的程序路径\n};\n\n//#define MAIN_WND_COLOR_NUM 9      //主窗口颜色数量\n//选项设置中“主窗口设置”的数据\nstruct MainWndSettingData : public PublicSettingData\n{\n    std::map<CommonDisplayItem, COLORREF> text_colors{};    //文字的颜色\n    bool swap_up_down{ false };     //交换上传和下载显示的位置\n    bool hide_main_wnd_when_fullscreen;     //有程序全屏运行时隐藏悬浮窗\n    bool m_always_on_top{ false };      //窗口置顶\n    bool m_lock_window_pos{ false };    //锁定窗口位置\n    bool m_mouse_penetrate{ false };    //鼠标穿透\n    bool m_alow_out_of_border{ false };     //是否允许悬浮窗超出屏幕边界\n\n    void FormSkinSettingData(const SkinSettingData& sking_setting_data);\n    SkinSettingData ToSkinSettingData() const;\n};\n\n//#define TASKBAR_COLOR_NUM 18      //任务栏窗口颜色数量\n\nstruct TaskbarItemColor //任务栏窗口每一项的颜色\n{\n    COLORREF label{};   //标签颜色\n    COLORREF value{};   //数值颜色\n\n    bool operator==(const TaskbarItemColor& item) const\n    {\n        return label == item.label && value == item.value;\n    }\n};\n\n//选项设置中“任务栏窗口设置”的数据\nstruct TaskBarSettingData : public PublicSettingData\n{\n    COLORREF  back_color{ RGB(0, 0, 0) };   //背景颜色\n    COLORREF transparent_color{ RGB(0, 0, 0) };     //透明色\n    COLORREF status_bar_color{ RGB(0, 0, 0) };      // CPU/内存 状态条颜色\n    std::map<CommonDisplayItem, TaskbarItemColor> text_colors{};    //文字的颜色\n    int dft_back_color = 0;                         //默认背景颜色\n    int dft_transparent_color = 0;                  //默认透明色\n    int dft_status_bar_color = 0x005A5A5A;          //默认CPU/内存 状态条颜色\n    int dft_text_colors = 0x00ffffffU;              //默认文字颜色\n\n    bool auto_adapt_light_theme{ true };            //是否自动适应浅色主题\n    int dark_default_style{ 0 };                    //深色主题时使用的预设方案\n    int light_default_style{ -1 };                  //浅色主题时使用的预设方案\n    bool auto_set_background_color{ false };        //根据任务栏颜色自动设置背景色\n    bool auto_save_taskbar_color_settings_to_preset{};    //当启用“自动适应Windows10深色/浅色主题”时，是否在颜色设置有更改时自动将当前颜色设置保存到对应的预设\n    bool IsTaskbarTransparent() const;\n    void SetTaskabrTransparent(bool transparent);\n\n    CTaskbarItemOrderHelper item_order;\n    DisplayItemSet display_item{ TDI_UP, TDI_DOWN };      //任务栏窗口显示的项目\n    StringSet plugin_display_item;                  //任务窗口显示的插件项目\n\n    bool show_taskbar_wnd_in_secondary_display{ false };    //是否在副显示器上显示任务栏窗口\n    int secondary_display_index{};      //在第几个副显示器上显示任务栏窗口\n    bool value_right_align{ false };    //数值是否右对齐\n    int digits_number{ 4 };             //数据位数\n    bool horizontal_arrange{ true };    //水平排列\n    bool show_status_bar{ true };       //显示 CPU/内存的状态条\n    bool tbar_wnd_on_left{ false };     //如果为true，则任务栏窗口显示在任务栏的左侧（或上方）\n    bool tbar_wnd_snap{ false };     \t//如果为true，则在Win11中任务栏窗口贴靠中间任务栏，否则靠近边缘\n    bool cm_graph_type{ false };        //如果为false，默认原样式，柱状图显示占用率，如为true，滚动显示占用率\n    bool show_graph_dashed_box{ true }; //显示占用图虚线框\n\n    int item_space{};                   //项目间距\n    int vertical_margin{};              //项目垂直间距\n    int window_offset_top{};            //任务栏窗口顶部边距\n    int window_offset_left{};           //任务栏窗口左侧边距\n    void ValidItemSpace();\n    void ValidVerticalMargin();\n    void ValidWindowOffsetTop();\n    void ValidWindowOffsetLeft();\n    bool avoid_overlap_with_widgets{ false };   //避免与右侧小组件重叠\n    int taskbar_left_space_win11{};         //Windows11下，任务栏小工具的宽度\n    int taskbar_right_space_win11{};        //Windows11下，任务栏窗口距离任务栏右侧的宽度（仅当无法获取到任务栏TrayNotifyWnd窗口的位置时有效）\n\n    bool show_netspeed_figure{ false };     //是否显示网速占用图\n    int netspeed_figure_max_value;          //网速占用图的最大值\n    int netspeed_figure_max_value_unit{};   //网速占用图最大值的单位（0: KB, 1: MB）\n    unsigned __int64 GetNetspeedFigureMaxValueInBytes() const;  //获取网速占用图的最大值（以字节为单位）\n    bool graph_color_following_system{ false }; //占用图颜色跟随系统主题色\n    COLORREF GetUsageGraphColor() const;    //获取占用图的颜色\n\n    bool disable_d2d{ false };//是否禁用d2d绘图\n    DWORD update_layered_window_error_code{0}; // 使用D2D1渲染时，UpdateLayeredWindowIndirect失败的错误代码，会在关闭任务栏窗口时被重置为0\n    bool enable_colorful_emoji{ true };       //是否显示彩色emoji\n\n    bool is_windows_web_experience_detected{ false }; //是否检测到Windows Web Experience小组件安装信息\n};\n\n//选项设置中“常规设置”的数据\nstruct GeneralSettingData\n{\n    bool check_update_when_start{ true };\n    int update_source{};                    //更新源。0: GitHub; 1: Gitee\n    bool auto_run{ false };\n    bool show_notify_icon{ true };    //显示通知区域图标\n//通知消息\n    bool traffic_tip_enable{ false };       //是否启用流量超出时提示\n    int traffic_tip_value;                  //要提示的流量临界值\n    int traffic_tip_unit{};                 //要提示的流量值的单位（0: MB, 1: GB）\n\n    struct NotifyTipSettings        //超过某个值时弹出提示的设置\n    {\n        bool enable;                //是否启用提示\n        int tip_value;              //要弹出提示的临界值\n    };\n    NotifyTipSettings memory_usage_tip;     //用内存使用率超出提示\n    NotifyTipSettings cpu_temp_tip;         //CPU温度超出提示\n    NotifyTipSettings gpu_temp_tip;         //显卡温度超出提示\n    NotifyTipSettings hdd_temp_tip;         //硬盘温度超出提示\n    NotifyTipSettings mainboard_temp_tip;   //主板温度超出提示\n\n\n    //语言id\n    WORD language;\n\n    bool show_all_interface{ true };\n\n    //CPU利用率获取方式\n    enum CpuUsageAcquireMethod\n    {\n        CA_CPU_TIME,    //使用时间\n        CA_PDH,         //性能计数器\n        CA_HARDWARE_MONITOR     //来自硬件监控\n    };\n    CpuUsageAcquireMethod cpu_usage_acquire_method{};  //获取CPU利用率的方式\n\n    bool portable_mode{ false };        //便携模式，如果为true，则程序所有数据都保存到exe所在目录下，否则保存到Appdata\\Romaing目录下\n    int monitor_time_span{ 1000 };    //监控的时间间隔\n\n    std::wstring hard_disk_name;        //要监控的硬盘名称\n    std::wstring cpu_core_name;         //要监控的CPU核心的名称\n\n    unsigned int hardware_monitor_item{};   //要监控哪些硬件\n    bool IsHardwareEnable(HardwareItem item_type) const\n    {\n        return hardware_monitor_item & item_type;\n    }\n    void SetHardwareEnable(HardwareItem item_type, bool enable)\n    {\n        if (enable)\n            hardware_monitor_item |= item_type;\n        else\n            hardware_monitor_item &= ~item_type;\n    }\n\n    StringSet connections_hide;     //用于保存哪些网络要从“选择网络连接”子菜单项中隐藏\n};\n\n//定义监控时间间隔有效的最大值和最小值\n#define MONITOR_TIME_SPAN_MIN 200\n#define MONITOR_TIME_SPAN_MAX 30000\n\n//通过构造函数传递一个bool变量的引用，在构造时将其置为true，析构时置为false\nclass CFlagLocker\n{\npublic:\n    CFlagLocker(bool& flag)\n        : m_flag(flag)\n    {\n        m_flag = true;\n    }\n\n    ~CFlagLocker()\n    {\n        m_flag = false;\n    }\n\nprivate:\n    bool& m_flag;\n};\n"
  },
  {
    "path": "TrafficMonitor/D2D1Support.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"D2D1Support.h\"\n#include \"Common.h\"\n\n#pragma comment(lib, \"D2d1.lib\")\n#pragma comment(lib, \"Dwrite.lib\")\n\nbool CD2D1Support::CheckSupport()\n{\n    static bool result = FunctionChecker::CheckFunctionExist(_T(\"D2d1.dll\"), \"D2D1CreateFactory\");\n    return result;\n}\n\nID2D1Factory* CD2D1Support::GetFactory()\n{\n    static auto result = MakeStaticVariableWrapper<ID2D1Factory*>(\n        [](ID2D1Factory** pp_factory)\n        {\n            *pp_factory = nullptr;\n\n            ThrowIfFailed(::D2D1CreateFactory(\n                              D2D1_FACTORY_TYPE_SINGLE_THREADED,\n                              CD2D1Support::CREATION_OPTIONS,\n                              pp_factory),\n                          TRAFFICMONITOR_ERROR_STR(\"Create D2D1 factory failed.\"));\n        },\n        [](ID2D1Factory** pp_factory)\n        {\n            auto* p_factory = *pp_factory;\n            RELEASE_COM(p_factory);\n        });\n    return result.Get();\n}\n\nbool CD2D1Support1::CheckSupport()\n{\n    static bool result = FunctionChecker::CheckFunctionExist(_T(\"D2D1.dll\"), \"D2D1CreateDevice\");\n    return result;\n}\n\nID2D1Factory1* CD2D1Support1::GetFactory()\n{\n    static auto result = MakeStaticVariableWrapper<ID2D1Factory1*>(\n        [](auto pp_factory)\n        {\n            *pp_factory = nullptr;\n\n            ThrowIfFailed(::D2D1CreateFactory(\n                              D2D1_FACTORY_TYPE_SINGLE_THREADED,\n                              CD2D1Support::CREATION_OPTIONS,\n                              pp_factory),\n                          TRAFFICMONITOR_ERROR_STR(\"Create D2D1 factory failed.\"));\n        },\n        [](auto pp_factory)\n        {\n            auto* p_factory = *pp_factory;\n            RELEASE_COM(p_factory);\n        });\n    return result.Get();\n}\n\nvoid CD2D1Device::Recreate(Microsoft::WRL::ComPtr<IDXGIDevice> p_dxgi_device)\n{\n    ThrowIfFailed<CD2D1Exception>(\n        CD2D1Support1::GetFactory()->CreateDevice(\n            p_dxgi_device.Get(),\n            &m_p_device),\n        TRAFFICMONITOR_ERROR_STR(\"Create ID2D1Device failed.\"));\n\n    NotifyAllResourceWhenDeviceRecreate(\n        m_resource_tracker,\n        m_p_device);\n}\n\nauto CD2D1Device::GetStorage()\n    -> std::shared_ptr<Storage>\n{\n    return m_resource_tracker.GetSharedResourceTrackerStorage();\n}\n\nauto CD2D1Device::Get()\n    -> Type\n{\n    return m_p_device;\n}\n\nbool CDWriteSupport::CheckSupport()\n{\n    static bool result = FunctionChecker::CheckFunctionExist(_T(\"Dwrite.dll\"), \"DWriteCreateFactory\");\n    return result;\n}\n\nIDWriteFactory* CDWriteSupport::GetFactory()\n{\n    static auto result = MakeStaticVariableWrapper<IDWriteFactory*>(\n        [](IDWriteFactory** pp_factory)\n        {\n            *pp_factory = nullptr;\n            ThrowIfFailed(::DWriteCreateFactory(\n                              DWRITE_FACTORY_TYPE_SHARED,\n                              __uuidof(IDWriteFactory),\n                              reinterpret_cast<IUnknown**>(pp_factory)),\n                          TRAFFICMONITOR_ERROR_STR(\"Create DWrite factory failed.\"));\n        },\n        [](IDWriteFactory** pp_factory)\n        {\n            auto* p_factory = *pp_factory;\n            RELEASE_COM(p_factory);\n        });\n    return result.Get();\n}\n"
  },
  {
    "path": "TrafficMonitor/D2D1Support.h",
    "content": "﻿#pragma once\n#include <d2d1_1.h>\n#include <dwrite.h>\n#include \"HResultException.h\"\n#include \"RenderAPISupport.h\"\n\nclass CD2D1Exception final : public CHResultException\n{\n    using CHResultException::CHResultException;\n};\n\nclass CDWriteException final : public CHResultException\n{\n    using CHResultException::CHResultException;\n};\n\nclass CD2D1Support\n{\npublic:\n#ifdef DEBUG\n    constexpr static D2D1_FACTORY_OPTIONS CREATION_OPTIONS{D2D1_DEBUG_LEVEL_INFORMATION};\n#else\n    constexpr static D2D1_FACTORY_OPTIONS CREATION_OPTIONS{D2D1_DEBUG_LEVEL_NONE};\n#endif\n\n    static bool CheckSupport();\n    static ID2D1Factory* GetFactory();\n};\n\nclass CD2D1Device\n{\npublic:\n    using Type = Microsoft::WRL::ComPtr<ID2D1Device>;\n    using Resource = CDeviceResource<CD2D1Device>;\n    using Storage = storage_t<CResourceTracker<Resource>>;\n\nprivate:\n    Type m_p_device{};\n    CResourceTracker<Resource> m_resource_tracker{std::make_shared<Storage>()};\n\npublic:\n    void Recreate(Microsoft::WRL::ComPtr<IDXGIDevice> p_dxgi_device);\n    auto GetStorage()\n        -> std::shared_ptr<Storage>;\n    Type Get();\n};\n\nclass CD2D1Support1\n{\npublic:\n    static bool CheckSupport();\n    static ID2D1Factory1* GetFactory();\n};\n\nclass CDWriteSupport\n{\npublic:\n    static bool CheckSupport();\n    static IDWriteFactory* GetFactory();\n};\n"
  },
  {
    "path": "TrafficMonitor/D3D10Support1.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include <algorithm>\n#include <memory>\n#include <tuple>\n#include <chrono>\n#include \"D3D10Support1.h\"\n#include \"Common.h\"\n#include \"Nullable.hpp\"\n#include \"DllFunctions.h\"\n\n#pragma comment(lib, \"DXGI.lib\")\n#pragma comment(lib, \"D3D10_1.lib\")\n\nusing Microsoft::WRL::ComPtr;\n\nvoid CD3D10Device1::Recreate(Microsoft::WRL::ComPtr<IDXGIAdapter1> p_adapter1)\n{\n    m_sp_storage->m_p_adapter1 = p_adapter1;\n    ThrowIfFailed(\n        D3D10CreateDevice1(\n            m_sp_storage->m_p_adapter1.Get(),\n            m_sp_storage->m_driver_type,\n            m_sp_storage->m_h_software,\n            m_sp_storage->m_flags,\n            m_sp_storage->m_feature_level,\n            m_sp_storage->m_sdk_version,\n            &m_sp_storage->m_p_device1),\n        TRAFFICMONITOR_ERROR_STR(\"Create D3D10Device1 failed.\"));\n\n    NotifyAllResourceWhenDeviceRecreate(\n        m_resource_tracker,\n        m_sp_storage->m_p_device1);\n}\n\nauto CD3D10Device1::Get() noexcept\n    -> Microsoft::WRL::ComPtr<ID3D10Device1>\n{\n    return m_sp_storage->m_p_device1;\n}\n\nauto CD3D10Device1::GetAdapter() noexcept\n    -> Microsoft::WRL::ComPtr<IDXGIAdapter1>\n{\n    return m_sp_storage->m_p_adapter1;\n}\n\nauto CD3D10Device1::GetDriverType() const noexcept\n    -> D3D10_DRIVER_TYPE\n{\n    return m_sp_storage->m_driver_type;\n}\n\nauto CD3D10Device1::SetDriverType(D3D10_DRIVER_TYPE driver_type) noexcept\n    -> CD3D10Device1&\n{\n    m_sp_storage->m_driver_type = driver_type;\n    return *this;\n}\n\nauto CD3D10Device1::GetSoftwareHandle() const noexcept\n    -> HMODULE\n{\n    return m_sp_storage->m_h_software;\n}\n\nauto CD3D10Device1::SetSoftwareHandle(HMODULE h_software) noexcept\n    -> CD3D10Device1&\n{\n    m_sp_storage->m_h_software = h_software;\n    return *this;\n}\n\nauto CD3D10Device1::GetFlags() const noexcept\n    -> UINT\n{\n    return m_sp_storage->m_flags;\n}\n\nauto CD3D10Device1::SetFlags(UINT flags) noexcept\n    -> CD3D10Device1&\n{\n    m_sp_storage->m_flags = flags;\n    return *this;\n}\n\nauto CD3D10Device1::GetFeaturelLevel() const noexcept\n    -> D3D10_FEATURE_LEVEL1\n{\n    return m_sp_storage->m_feature_level;\n}\n\nauto CD3D10Device1::SetFeaturelLevel(D3D10_FEATURE_LEVEL1 featurel_level) noexcept\n    -> CD3D10Device1&\n{\n    m_sp_storage->m_feature_level = featurel_level;\n    return *this;\n}\n\nauto CD3D10Device1::GetSdkVersion() const noexcept\n    -> UINT\n{\n    return m_sp_storage->m_sdk_version;\n}\n\nauto CD3D10Device1::SetSdkVersion(UINT sdk_version) noexcept\n    -> CD3D10Device1&\n{\n    m_sp_storage->m_sdk_version = sdk_version;\n    return *this;\n}\n\nauto CD3D10Device1::GetStorage() noexcept\n    -> std::shared_ptr<Storage>\n{\n    return m_sp_storage;\n}\n\nbool CD3D10Support1::CheckSupport()\n{\n    static bool result = FunctionChecker::CheckFunctionExist(_T(\"D3D10_1.dll\"), \"D3D10CreateDevice1\");\n    return result;\n}\n\nauto CD3D10Support1::GetDeviceList(bool force_refresh)\n    -> const std::vector<Microsoft::WRL::ComPtr<IDXGIAdapter1>>&\n{\n    static CNullable<CStaticVariableWrapper<ComPtr<IDXGIFactory1>>> p_dxgi_factory1_wrapper{};\n    if (!p_dxgi_factory1_wrapper || force_refresh)\n    {\n        Destroy(&p_dxgi_factory1_wrapper);\n        EmplaceAt(&p_dxgi_factory1_wrapper);\n        p_dxgi_factory1_wrapper.Construct([](ComPtr<IDXGIFactory1>* p_content)\n                                          { CreateDXGIFactory1(IID_PPV_ARGS(&*p_content)); });\n    }\n\n    using DeviceVector = std::vector<ComPtr<IDXGIAdapter1>>;\n    static CNullable<CStaticVariableWrapper<DeviceVector>> result{};\n    if (!result || force_refresh)\n    {\n        Destroy(&result);\n        EmplaceAt(&result);\n        result.Construct([](DeviceVector* p_content)\n                         {\n            auto p_dxgi_factory1 = p_dxgi_factory1_wrapper.GetUnsafe().Get();\n            UINT i = 0;\n            do\n            {\n                ComPtr<IDXGIAdapter1> p_current_adapter1{};\n                auto hr = p_dxgi_factory1->EnumAdapters1(i, &p_current_adapter1);\n                if (hr == S_OK)\n                {\n                    ++i;\n                    p_content->emplace_back(std::move(p_current_adapter1));\n                    continue;\n                }\n                else if (hr == DXGI_ERROR_NOT_FOUND)\n                {\n                    break;\n                }\n                else if (FAILED(hr))\n                {\n                    ThrowIfFailed(\n                        hr,\n                    TRAFFICMONITOR_ERROR_STR(\"EnumAdapters1 failed. Maybe ppAdapter parameter is NULL.\"));\n                }\n            } while (true); });\n    }\n\n    return result.GetUnsafe().Get();\n}\n\nCDXShaderException::CDXShaderException(HRESULT hr, const char* p_error, Microsoft::WRL::ComPtr<ID3DBlob> p_shader_error)\n    : CHResultException{hr, p_error}, m_error{p_error}\n{\n    if (p_shader_error != nullptr)\n    {\n        m_error += static_cast<char*>(p_shader_error->GetBufferPointer());\n    }\n}\n\nconst char* CDXShaderException::what() const noexcept\n{\n    return m_error.c_str();\n}\n\nauto CShader::Compile() const\n    -> Microsoft::WRL::ComPtr<ID3DBlob>\n{\n    if (m_is_macro_changed && !m_macros.empty())\n    {\n        m_shader_macros.resize(m_macros.size() + 1);\n        std::transform(m_macros.begin(), m_macros.end(), m_shader_macros.begin(),\n                       [](const ShaderMacro& current) -> D3D_SHADER_MACRO\n                       {\n                           return {current.m_name.c_str(), current.m_definition.c_str()};\n                       });\n        m_shader_macros.back() = {NULL, NULL};\n    }\n    m_is_macro_changed = false;\n\n    if (m_is_config_changed)\n    {\n        if (!CDllFunctions::D3DCompile.HasValue())\n        {\n            throw std::runtime_error{\n                TRAFFICMONITOR_ERROR_STR(\"Can not find function D3DCompile in d3dcompiler_47.dll or d3dcompiler_47.dll is not exist.\")};\n        }\n        ComPtr<ID3DBlob> p_error_message{};\n        ThrowIfFailed<CDXShaderException>(\n            CDllFunctions::D3DCompile(\n                m_code.c_str(),\n                m_code.size(),\n                m_name.c_str(),\n                m_macros.empty() ? NULL : m_shader_macros.data(),\n                m_p_include == nullptr ? D3D_COMPILE_STANDARD_FILE_INCLUDE : m_p_include,\n                m_entry_point.c_str(),\n                m_target.c_str(),\n                m_flags1,\n                m_flags2,\n                &m_p_cached_byte_code,\n                &p_error_message),\n            TRAFFICMONITOR_ERROR_STR(\"Compile DX shader failed.\"),\n            p_error_message);\n        m_is_config_changed = false;\n    }\n\n    return m_p_cached_byte_code;\n}\n\nauto CShader::GetCode() const noexcept\n    -> const std::string&\n{\n    return m_code;\n}\n\nauto CShader::SetCode(const std::string& code)\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_code = code;\n    return *this;\n}\n\nauto CShader::GetEntryPoint() const noexcept\n    -> const std::string&\n{\n    return m_entry_point;\n}\n\nauto CShader::SetEntryPoint(const std::string& entry_point)\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_entry_point = entry_point;\n    return *this;\n}\n\nauto CShader::GetName() const noexcept\n    -> const std::string&\n{\n    return m_name;\n}\n\nauto CShader::SetName(const std::string& name)\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_name = name;\n    return *this;\n}\n\nauto CShader::GetTarget() const noexcept\n    -> const std::string&\n{\n    return m_target;\n}\n\nauto CShader::SetTarget(const std::string& target)\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_target = target;\n    return *this;\n}\n\nauto CShader::AddMacro(const ShaderMacro& macro)\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_macros.push_back(macro);\n    return *this;\n}\n\nauto CShader::DeleteMacro(const std::string& name)\n    -> CShader&\n{\n    m_is_config_changed = true;\n    std::ignore = std::remove_if(m_macros.begin(), m_macros.end(), [&name](const ShaderMacro& x)\n                                 { return x.m_name == name; });\n    return *this;\n}\n\nauto CShader::GetMacros() const noexcept\n    -> const std::vector<ShaderMacro>&\n{\n    return m_macros;\n}\n\nUINT CShader::GetFlags1() const noexcept\n{\n    return m_flags1;\n}\n\nauto CShader::SetFlags1(UINT flags1) noexcept\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_flags1 = flags1;\n    return *this;\n}\n\nUINT CShader::GetFlags2() const noexcept\n{\n    return m_flags2;\n}\n\nauto CShader::SetFlags2(UINT flags2) noexcept\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_flags2 = flags2;\n    return *this;\n}\n\nauto CShader::GetInclude() noexcept\n    -> ID3DInclude*\n{\n    m_is_config_changed = true;\n    return m_p_include;\n}\n\nauto CShader::SetInclude(ID3DInclude* p_indclude) noexcept\n    -> CShader&\n{\n    m_is_config_changed = true;\n    m_p_include = p_indclude;\n    return *this;\n}\n\nCD3D10DrawCallWaiter::CD3D10DrawCallWaiter(Microsoft::WRL::ComPtr<ID3D10Device1> p_device)\n{\n    D3D10_QUERY_DESC query_desc{};\n    query_desc.Query = D3D10_QUERY_EVENT;\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device->CreateQuery(&query_desc, &m_p_query),\n        TRAFFICMONITOR_ERROR_STR(\"Create ID3D10Query failed.\"));\n    m_p_query->End();\n}\n\nHRESULT CD3D10DrawCallWaiter::Wait() const noexcept\n{\n    HRESULT result{S_FALSE};\n    constexpr std::uint32_t MAX_QUERY_TIME = 20;\n    for (std::uint32_t i = 0; i < MAX_QUERY_TIME; ++i)\n    {\n        result = m_p_query->GetData(NULL, 0, 0);\n        if (result != S_FALSE)\n        {\n            return result;\n        }\n    }\n    const auto start_time = std::chrono::system_clock::now();\n    using namespace std::chrono_literals;\n    do\n    {\n        result = m_p_query->GetData(NULL, 0, 0);\n    } while (result != S_FALSE && std::chrono::system_clock::now() - start_time < 1500ms);\n    return result;\n}\n"
  },
  {
    "path": "TrafficMonitor/D3D10Support1.h",
    "content": "﻿#pragma once\n#include <cstdint>\n#include <functional>\n#include <vector>\n#include <memory>\n#include <mutex>\n#include <d3d10_1.h>\n#include <dxgi.h>\n#include <d3dcompiler.h>\n#include \"HResultException.h\"\n#include \"RenderAPISupport.h\"\n\nclass CD3D10Exception1 final : public CHResultException\n{\n    using CHResultException::CHResultException;\n};\n\nclass CD3D10Device1\n{\npublic:\n    using Type = Microsoft::WRL::ComPtr<ID3D10Device1>;\n    struct Data\n    {\n        Microsoft::WRL::ComPtr<ID3D10Device1> m_p_device1{};\n\n        Microsoft::WRL::ComPtr<IDXGIAdapter1> m_p_adapter1{};\n        D3D10_DRIVER_TYPE m_driver_type{D3D10_DRIVER_TYPE_HARDWARE};\n        HMODULE m_h_software{NULL};\n        UINT m_flags{0};\n        D3D10_FEATURE_LEVEL1 m_feature_level{D3D10_FEATURE_LEVEL_10_1};\n        UINT m_sdk_version{D3D10_1_SDK_VERSION};\n    };\n    using Resource = CDeviceResource<CD3D10Device1>;\n    using Storage = MutipleStorage<Data,\n                                   storage_t<CResourceTracker<Resource>>>;\n\nprivate:\n    std::shared_ptr<Storage> m_sp_storage{std::make_shared<Storage>()};\n    CResourceTracker<Resource> m_resource_tracker{m_sp_storage};\n\npublic:\n    void Recreate(Microsoft::WRL::ComPtr<IDXGIAdapter1> p_adapter1);\n    auto Get() noexcept\n        -> Microsoft::WRL::ComPtr<ID3D10Device1>;\n\n    auto GetAdapter() noexcept\n        -> Microsoft::WRL::ComPtr<IDXGIAdapter1>;\n\n    auto GetDriverType() const noexcept\n        -> D3D10_DRIVER_TYPE;\n    auto SetDriverType(D3D10_DRIVER_TYPE driver_type) noexcept\n        -> CD3D10Device1&;\n\n    auto GetSoftwareHandle() const noexcept\n        -> HMODULE;\n    auto SetSoftwareHandle(HMODULE h_software) noexcept\n        -> CD3D10Device1&;\n\n    auto GetFlags() const noexcept\n        -> UINT;\n    auto SetFlags(UINT flags) noexcept\n        -> CD3D10Device1&;\n\n    auto GetFeaturelLevel() const noexcept\n        -> D3D10_FEATURE_LEVEL1;\n    auto SetFeaturelLevel(D3D10_FEATURE_LEVEL1 featurel_level) noexcept\n        -> CD3D10Device1&;\n\n    auto GetSdkVersion() const noexcept\n        -> UINT;\n    auto SetSdkVersion(UINT sdk_version) noexcept\n        -> CD3D10Device1&;\n\n    auto GetStorage() noexcept\n        -> std::shared_ptr<Storage>;\n};\n\nclass CD3D10Support1\n{\npublic:\n    static bool CheckSupport();\n    static auto GetDeviceList(bool force_refresh = false)\n        -> const std::vector<Microsoft::WRL::ComPtr<IDXGIAdapter1>>&;\n};\n\nclass CDXShaderException final : public CHResultException\n{\nprivate:\n    std::string m_error;\n\npublic:\n    CDXShaderException(HRESULT hr, const char* p_error, Microsoft::WRL::ComPtr<ID3DBlob> p_shader_error);\n    ~CDXShaderException() override = default;\n\n    const char* what() const noexcept override;\n};\n\nstruct ShaderMacro\n{\n    std::string m_name{};\n    std::string m_definition{};\n};\n\nclass CShader\n{\nprivate:\n    std::string m_code{};\n    std::string m_entry_point{};\n    std::string m_name{};\n    std::string m_target{};\n    std::vector<ShaderMacro> m_macros{};\n    mutable std::vector<D3D_SHADER_MACRO> m_shader_macros{0};\n    ID3DInclude* m_p_include{};\n    UINT m_flags1{};\n    UINT m_flags2{};\n    mutable bool m_is_macro_changed{true};\n    mutable bool m_is_config_changed{true};\n    mutable Microsoft::WRL::ComPtr<ID3DBlob> m_p_cached_byte_code{};\n\npublic:\n    CShader() = default;\n    ~CShader() = default;\n\n    auto GetCode() const noexcept\n        -> const std::string&;\n    auto SetCode(const std::string& code)\n        -> CShader&;\n\n    auto GetEntryPoint() const noexcept\n        -> const std::string&;\n    auto SetEntryPoint(const std::string& entry_point)\n        -> CShader&;\n\n    auto GetName() const noexcept\n        -> const std::string&;\n    auto SetName(const std::string& name)\n        -> CShader&;\n\n    auto GetTarget() const noexcept\n        -> const std::string&;\n    auto SetTarget(const std::string& target)\n        -> CShader&;\n\n    auto AddMacro(const ShaderMacro& macro)\n        -> CShader&;\n    auto DeleteMacro(const std::string& name)\n        -> CShader&;\n    auto GetMacros() const noexcept\n        -> const std::vector<ShaderMacro>&;\n\n    UINT GetFlags1() const noexcept;\n    auto SetFlags1(UINT flags1) noexcept\n        -> CShader&;\n\n    UINT GetFlags2() const noexcept;\n    auto SetFlags2(UINT flags2) noexcept\n        -> CShader&;\n\n    auto GetInclude() noexcept\n        -> ID3DInclude*;\n    auto SetInclude(ID3DInclude* p_indclude) noexcept\n        -> CShader&;\n\n    auto Compile() const\n        -> Microsoft::WRL::ComPtr<ID3DBlob>;\n};\n\nclass CD3D10DrawCallWaiter\n{\nprivate:\n    Microsoft::WRL::ComPtr<ID3D10Query> m_p_query{};\n\npublic:\n    explicit CD3D10DrawCallWaiter(Microsoft::WRL::ComPtr<ID3D10Device1> p_device);\n    ~CD3D10DrawCallWaiter() = default;\n    /**\n     * @brief\n     *\n     * @return HRESULT 若成功，返回S_OK，否则可能为DXGI_ERROR_DEVICE_REMOVED或DXGI_ERROR_INVALID_CALL\n     * 若返回S_FALSE，此为函数本身的返回值，不能参考MS的文档，这代表等待超时（超过1.5s的等待时间）\n     */\n    HRESULT Wait() const noexcept;\n};\n"
  },
  {
    "path": "TrafficMonitor/DCompositionSupport.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"DCompositionSupport.h\"\n#include \"Common.h\"\n#include \"DllFunctions.h\"\n\nvoid CDCompositionDevice::Recreate(Microsoft::WRL::ComPtr<IDXGIDevice> p_dxgi_device)\n{\n    ThrowIfFailed<CDCompositionException>(\n        CDllFunctions::DCompositionCreateDevice(\n            p_dxgi_device.Get(),\n            IID_PPV_ARGS(&m_p_device)),\n        TRAFFICMONITOR_ERROR_STR(\"Recreate DComposition device failed.\"));\n\n    NotifyAllResourceWhenDeviceRecreate(m_resource_tracker, m_p_device);\n}\n\nauto CDCompositionDevice::GetStorage()\n    -> std::shared_ptr<Storage>\n{\n    return m_resource_tracker.GetSharedResourceTrackerStorage();\n}\n\nbool CDCompositionSupport::CheckSupport()\n{\n    static auto result =\n        FunctionChecker::CheckFunctionExist(_T(\"dcomp.dll\"), \"DCompositionCreateDevice\");\n    return result;\n}\n\nauto CDCompositionDevice::Get()\n    -> Microsoft::WRL::ComPtr<IDCompositionDevice>\n{\n    return m_p_device;\n}\n"
  },
  {
    "path": "TrafficMonitor/DCompositionSupport.h",
    "content": "﻿#pragma once\n#include <wrl/client.h>\n#include <dcomp.h>\n#include \"HResultException.h\"\n#include \"RenderAPISupport.h\"\n\nclass CDCompositionException final : public CHResultException\n{\n    using CHResultException::CHResultException;\n};\n\nclass CDCompositionDevice\n{\npublic:\n    using Resource = CDeviceResource<CDCompositionDevice>;\n    using Type = Microsoft::WRL::ComPtr<IDCompositionDevice>;\n    using Storage = storage_t<CResourceTracker<Resource>>;\n\nprivate:\n    Type m_p_device{};\n    CResourceTracker<Resource> m_resource_tracker{std::make_shared<Storage>()};\n\npublic:\n    void Recreate(Microsoft::WRL::ComPtr<IDXGIDevice> p_dxgi_device);\n    auto GetStorage()\n        -> std::shared_ptr<Storage>;\n    auto Get()\n        -> Microsoft::WRL::ComPtr<IDCompositionDevice>;\n};\n\nclass CDCompositionSupport\n{\npublic:\n    static bool CheckSupport();\n};\n"
  },
  {
    "path": "TrafficMonitor/DisplayItem.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"DisplayItem.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n\nCommonDisplayItem::CommonDisplayItem(DisplayItem item)\n{\n    is_plugin = false;\n    item_type = item;\n    plugin_item = nullptr;\n}\n\nCommonDisplayItem::CommonDisplayItem(IPluginItem* item)\n{\n    is_plugin = true;\n    plugin_item = item;\n}\n\nbool CommonDisplayItem::operator<(const CommonDisplayItem& item) const\n{\n    if (is_plugin && !item.is_plugin)\n        return false;\n    else if (!is_plugin && item.is_plugin)\n        return true;\n    else if (!is_plugin)\n        return item_type < item.item_type;\n    else\n        return theApp.m_plugins.GetItemIndex(plugin_item) < theApp.m_plugins.GetItemIndex(item.plugin_item);\n}\n\nbool CommonDisplayItem::operator==(const CommonDisplayItem& item) const\n{\n    if (is_plugin != item.is_plugin)\n        return false;\n    else if (!is_plugin)\n        return item_type == item.item_type;\n    else\n        return plugin_item == item.plugin_item;\n}\n\nbool CommonDisplayItem::IsPlugin() const\n{\n    return is_plugin;\n}\n\nDisplayItem CommonDisplayItem::ItemType() const\n{\n    return item_type;\n}\n\nIPluginItem* CommonDisplayItem::PluginItem() const\n{\n    return plugin_item;\n}\n\nCString CommonDisplayItem::GetItemName() const\n{\n    if (is_plugin)\n    {\n        if (plugin_item != nullptr)\n            return plugin_item->GetItemName();\n        else\n            return CString();\n    }\n    else\n    {\n        switch (item_type)\n        {\n        case TDI_UP: return CCommon::LoadText(IDS_UPLOAD);\n        case TDI_DOWN: return CCommon::LoadText(IDS_DOWNLOAD);\n        case TDI_TOTAL_SPEED: return CCommon::LoadText(IDS_TOTAL_NET_SPEED);\n        case TDI_CPU: return CCommon::LoadText(IDS_CPU_USAGE);\n        case TDI_MEMORY: return CCommon::LoadText(IDS_MEMORY_USAGE);\n        case TDI_GPU_USAGE: return CCommon::LoadText(IDS_GPU_USAGE);\n        case TDI_CPU_TEMP: return CCommon::LoadText(IDS_CPU_TEMPERATURE);\n        case TDI_GPU_TEMP: return CCommon::LoadText(IDS_GPU_TEMPERATURE);\n        case TDI_HDD_TEMP: return CCommon::LoadText(IDS_HDD_TEMPERATURE);\n        case TDI_MAIN_BOARD_TEMP: return CCommon::LoadText(IDS_MAINBOARD_TEMPERATURE);\n        case TDI_HDD_USAGE: return CCommon::LoadText(IDS_HDD_USAGE);\n        case TDI_CPU_FREQ: return CCommon::LoadText(IDS_CPU_FREQ);\n        case TDI_TODAY_TRAFFIC: return CCommon::LoadText(IDS_TRAFFIC_USED);\n        default:\n            ASSERT(false);\n            break;\n        }\n    }\n    return CString();\n}\n\nstd::wstring CommonDisplayItem::DefaultString(bool is_main_window) const\n{\n    std::wstring default_text;\n    if (is_plugin)\n    {\n        default_text = plugin_item->GetItemLableText();\n        default_text += L' ';\n    }\n    else\n    {\n        switch (item_type)\n        {\n        case TDI_UP:\n            if (is_main_window)\n                default_text = CCommon::LoadText(IDS_UPLOAD_DISP, _T(\": \"));\n            else\n                default_text = _T(\"↑: \");\n            break;\n        case TDI_DOWN:\n            if (is_main_window)\n                default_text = CCommon::LoadText(IDS_DOWNLOAD_DISP, _T(\": \"));\n            else\n                default_text = _T(\"↓: \");\n            break;\n        case TDI_TOTAL_SPEED:\n            default_text = _T(\"↑↓: \");\n            break;\n        case TDI_TODAY_TRAFFIC:\n            default_text = CCommon::LoadText(IDS_TRAFFIC_USED, _T(\": \"));\n            break;\n        case TDI_CPU:\n            default_text = _T(\"CPU: \");\n            break;\n        case TDI_CPU_TEMP:\n            default_text = _T(\"CPU: \");\n            break;\n        case TDI_CPU_FREQ:\n            default_text = CCommon::LoadText(IDS_CPU_FREQ, _T(\": \"));\n            break;\n        case TDI_MEMORY:\n            default_text = CCommon::LoadText(IDS_MEMORY_DISP, _T(\": \"));\n            break;\n        case TDI_GPU_USAGE:\n            default_text = CCommon::LoadText(IDS_GPU_DISP, _T(\": \"));\n            break;\n        case TDI_GPU_TEMP:\n            default_text = CCommon::LoadText(IDS_GPU_DISP, _T(\": \"));\n            break;\n        case TDI_HDD_TEMP:\n            default_text = CCommon::LoadText(IDS_HDD_DISP, _T(\": \"));\n            break;\n        case TDI_MAIN_BOARD_TEMP:\n            default_text = CCommon::LoadText(IDS_MAINBOARD_DISP, _T(\": \"));\n            break;\n        case TDI_HDD_USAGE:\n            default_text = CCommon::LoadText(IDS_HDD_DISP, _T(\": \"));\n            break;\n        default:\n            ASSERT(false);\n            break;\n        }\n    }\n\n    return default_text;\n}\n\nconst wchar_t* CommonDisplayItem::GetItemIniKeyName() const\n{\n    if (is_plugin)\n    {\n        return plugin_item->GetItemId();\n    }\n    else\n    {\n        switch (item_type)\n        {\n        case TDI_UP: return L\"up_string\";\n        case TDI_DOWN: return L\"down_string\";\n        case TDI_CPU: return L\"cpu_string\";\n        case TDI_MEMORY: return L\"memory_string\";\n        case TDI_GPU_USAGE: return L\"gpu_string\";\n        case TDI_CPU_TEMP: return L\"cpu_temp_string\";\n        case TDI_GPU_TEMP: return L\"gpu_temp_string\";\n        case TDI_HDD_TEMP: return L\"hdd_temp_string\";\n        case TDI_MAIN_BOARD_TEMP: return L\"main_board_temp_string\";\n        case TDI_HDD_USAGE: return L\"hdd_string\";\n        case TDI_TOTAL_SPEED: return L\"total_speed_string\";\n        case TDI_CPU_FREQ: return L\"cpu_freq_string\";\n        case TDI_TODAY_TRAFFIC: return L\"today_traffic_string\";\n        }\n        ASSERT(FALSE);\n        return L\"\";\n    }\n}\n\nCString CommonDisplayItem::GetItemValueText(bool is_main_window) const\n{\n    if (is_plugin)\n    {\n        return plugin_item->GetItemValueText();\n    }\n    else\n    {\n        const PublicSettingData* cfg_data{};\n        if (is_main_window)\n            cfg_data = &theApp.m_main_wnd_data;\n        else\n            cfg_data = &theApp.m_taskbar_data;\n        CString str_value;\n        switch (item_type)\n        {\n        //上传、下载、总网速\n        case TDI_UP:\n        case TDI_DOWN:\n        case TDI_TOTAL_SPEED:\n        {\n            CString str_in_speed = CCommon::DataSizeToString(theApp.m_in_speed, *cfg_data);\n            CString str_out_speed = CCommon::DataSizeToString(theApp.m_out_speed, *cfg_data);\n            CString str_total_speed = CCommon::DataSizeToString(theApp.m_in_speed + theApp.m_out_speed, *cfg_data);\n            if (!cfg_data->hide_unit || cfg_data->speed_unit == SpeedUnit::AUTO)\n            {\n                str_in_speed += _T(\"/s\");\n                str_out_speed += _T(\"/s\");\n                str_total_speed += _T(\"/s\");\n            }\n            //交换上传和下载位置\n            if (is_main_window && theApp.m_main_wnd_data.swap_up_down)\n                std::swap(str_in_speed, str_out_speed);\n            if (item_type == TDI_UP)\n                str_value = str_out_speed;\n            else if (item_type == TDI_DOWN)\n                str_value = str_in_speed;\n            else\n                str_value = str_total_speed;\n        }\n            break;\n        //CPU利用率\n        case TDI_CPU:\n            str_value = CCommon::UsageToString(theApp.m_cpu_usage, *cfg_data);\n            break;\n        //内存利用率\n        case TDI_MEMORY:\n            if (cfg_data->memory_display == MemoryDisplay::MEMORY_USED)\n                str_value = CCommon::DataSizeToString(static_cast<unsigned long long>(theApp.m_used_memory) * 1024, cfg_data->separate_value_unit_with_space);\n            else if (cfg_data->memory_display == MemoryDisplay::MEMORY_AVAILABLE)\n                str_value = CCommon::DataSizeToString((static_cast<unsigned long long>(theApp.m_total_memory) - static_cast<unsigned long long>(theApp.m_used_memory)) * 1024, cfg_data->separate_value_unit_with_space);\n            else\n                str_value = CCommon::UsageToString(theApp.m_memory_usage, *cfg_data);\n            break;\n        //显卡利用率\n        case TDI_GPU_USAGE:\n            str_value = CCommon::UsageToString(theApp.m_gpu_usage, *cfg_data);\n            break;\n        //硬盘利用率\n        case TDI_HDD_USAGE:\n            str_value = CCommon::UsageToString(theApp.m_hdd_usage, *cfg_data);\n            break;\n        //CPU温度\n        case TDI_CPU_TEMP:\n            str_value = CCommon::TemperatureToString(theApp.m_cpu_temperature, *cfg_data);\n            break;\n        //显卡温度\n        case TDI_GPU_TEMP:\n            str_value = CCommon::TemperatureToString(theApp.m_gpu_temperature, *cfg_data);\n            break;\n        //硬盘温度\n        case TDI_HDD_TEMP:\n            str_value = CCommon::TemperatureToString(theApp.m_hdd_temperature, *cfg_data);\n            break;\n        //主板温度\n        case TDI_MAIN_BOARD_TEMP:\n            str_value = CCommon::TemperatureToString(theApp.m_main_board_temperature, *cfg_data);\n            break;\n        //CPU频率\n        case TDI_CPU_FREQ:\n            str_value = CCommon::FreqToString(theApp.m_cpu_freq, *cfg_data);\n            break;\n        //总流量\n        case TDI_TODAY_TRAFFIC:\n            str_value = CCommon::KBytesToString((theApp.m_today_up_traffic + theApp.m_today_down_traffic) / 1024u);\n            break;\n        default:\n            break;\n        }\n        return str_value;\n    }\n}\n\nCString CommonDisplayItem::GetItemValueSampleText(bool is_main_window) const\n{\n    if (is_plugin)\n    {\n        return plugin_item->GetItemValueSampleText();\n    }\n    //主窗口（用于绘制预览图）\n    else if (is_main_window)\n    {\n        CString sample_str;\n        switch (item_type)\n        {\n        case TDI_UP:\n            sample_str = _T(\"88.8 KB/s\");\n            break;\n        case TDI_DOWN:\n            sample_str = _T(\"88.9 KB/s\");\n            break;\n        case TDI_TOTAL_SPEED:\n            sample_str = _T(\"90 KB/s\");\n            break;\n        case TDI_TODAY_TRAFFIC:\n            sample_str = _T(\"100 MB\");\n            break;\n        case TDI_CPU:\n            sample_str = _T(\"50 %\");\n            break;\n        case TDI_MEMORY:\n            sample_str = _T(\"51 %\");\n            break;\n        case TDI_CPU_TEMP: case TDI_GPU_TEMP: case TDI_HDD_TEMP: case TDI_MAIN_BOARD_TEMP:\n            sample_str = _T(\"40 °C\");\n            break;\n        case TDI_CPU_FREQ:\n            sample_str = _T(\"1.0 GHz\");\n            break;\n        default:\n            sample_str = _T(\"99\");\n            break;\n        }\n        return sample_str;\n    }\n    //任务栏窗口（用于计算任务栏窗口宽度）\n    else\n    {\n        CString sample_str;\n        switch (item_type)\n        {\n        //网速\n        case TDI_UP:\n        case TDI_DOWN:\n        case TDI_TOTAL_SPEED:\n        {\n            wstring digits(theApp.m_taskbar_data.digits_number, L'8');      //根据数据位数生成指定个数的“8”\n            bool hide_unit{ theApp.m_taskbar_data.hide_unit && theApp.m_taskbar_data.speed_unit != SpeedUnit::AUTO };\n            if (theApp.m_taskbar_data.speed_short_mode)\n            {\n                if (hide_unit)\n                    sample_str.Format(_T(\"%s.\"), digits.c_str());\n                else\n                    sample_str.Format(_T(\"%s.M/s\"), digits.c_str());\n            }\n            else\n            {\n                if (hide_unit)\n                    sample_str.Format(_T(\"%s.8\"), digits.c_str());\n                else\n                    sample_str.Format(_T(\"%s.8MB/s\"), digits.c_str());\n            }\n            if (!hide_unit && theApp.m_taskbar_data.separate_value_unit_with_space)\n                sample_str += _T(' ');\n            if (theApp.m_taskbar_data.speed_short_mode && !theApp.m_taskbar_data.unit_byte && !theApp.m_taskbar_data.hide_unit)\n                sample_str += _T('b');\n        }\n            break;\n        //占用率百分比\n        case TDI_CPU:\n        case TDI_MEMORY:\n        case TDI_GPU_USAGE:\n        case TDI_HDD_USAGE:\n        {\n            sample_str = _T(\"100\");\n            if (!theApp.m_taskbar_data.hide_percent)\n            {\n                if (theApp.m_taskbar_data.separate_value_unit_with_space)\n                    sample_str += _T(\" %\");\n                else\n                    sample_str += _T(\"%\");\n            }\n            //内存显示不为已使用百分比时\n            if (item_type == TDI_MEMORY)\n            {\n                if (theApp.m_taskbar_data.memory_display == MemoryDisplay::MEMORY_USED || theApp.m_taskbar_data.memory_display == MemoryDisplay::MEMORY_AVAILABLE)\n                {\n                    //宽度为总内存的宽度\n                    sample_str = CCommon::DataSizeToString(static_cast<unsigned long long>(theApp.m_total_memory) * 1024, theApp.m_taskbar_data.separate_value_unit_with_space);\n                }\n            }\n        }\n            break;\n        //温度\n        case TDI_CPU_TEMP:\n        case TDI_GPU_TEMP:\n        case TDI_HDD_TEMP:\n        case TDI_MAIN_BOARD_TEMP:\n        {\n            if (theApp.m_taskbar_data.separate_value_unit_with_space)\n                sample_str = _T(\"99 °C\");\n            else\n                sample_str = _T(\"99°C\");\n        }\n            break;\n        //CPU频率\n        case TDI_CPU_FREQ:\n        {\n            if (theApp.m_taskbar_data.separate_value_unit_with_space)\n                sample_str = _T(\"1.00 GHz\");\n            else\n                sample_str = _T(\"1.00GHz\");\n        }\n            break;\n        //流量\n        case TDI_TODAY_TRAFFIC:\n        {\n            if (theApp.m_taskbar_data.separate_value_unit_with_space)\n                sample_str = _T(\"999.99 MB\");\n            else\n                sample_str = _T(\"999.99MB\");\n        }\n            break;\n        }\n        return sample_str;\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////\nDisplayItemSet::DisplayItemSet(std::initializer_list<DisplayItem> items)\n    : data(items)\n{\n}\n\nvoid DisplayItemSet::Add(DisplayItem item)\n{\n    data.insert(item);\n}\n\nvoid DisplayItemSet::Remove(DisplayItem item)\n{\n    data.erase(item);\n}\n\nbool DisplayItemSet::Contains(DisplayItem item) const\n{\n    auto iter = data.find(item);\n    return iter != data.end();\n}\n\nint DisplayItemSet::ToInt() const\n{\n    int value = 0;\n    //将set中的枚举值转换成int的每个bit位\n    for (const auto& item : data)\n    {\n        if (item <= 31)     //int左移不超过31位\n            value |= (1 << item);\n    }\n    return value;\n}\n\nvoid DisplayItemSet::FromInt(int value)\n{\n    data.clear();\n    //将int的每个bit位转换成set中的枚举值\n    for (const auto& item : AllDisplayItems)\n    {\n        if (item <= 31 && (value & (1 << item)))\n            data.insert(item);\n    }\n}\n\nbool DisplayItemSet::IsEmpty() const\n{\n    return data.empty();\n}\n"
  },
  {
    "path": "TrafficMonitor/DisplayItem.h",
    "content": "﻿#pragma once\n#include \"PluginInterface.h\"\n\n//内置的显示的项目\nenum DisplayItem\n{\n    TDI_UP,\n    TDI_DOWN,\n    TDI_CPU,\n    TDI_MEMORY,\n    TDI_GPU_USAGE,\n    TDI_CPU_TEMP,\n    TDI_GPU_TEMP,\n    TDI_HDD_TEMP,\n    TDI_MAIN_BOARD_TEMP,\n    TDI_HDD_USAGE,\n    TDI_TOTAL_SPEED,\n    TDI_CPU_FREQ,\n    TDI_TODAY_TRAFFIC\n};\n\n//所有内置显示项目的集合\nconst std::set<DisplayItem> AllDisplayItems\n{\n    TDI_UP, TDI_DOWN, TDI_CPU, TDI_MEMORY, TDI_GPU_USAGE\n#ifndef WITHOUT_TEMPERATURE\n    , TDI_CPU_TEMP, TDI_GPU_TEMP, TDI_HDD_TEMP, TDI_MAIN_BOARD_TEMP\n#endif\n    , TDI_HDD_USAGE, TDI_CPU_FREQ, TDI_TOTAL_SPEED, TDI_TODAY_TRAFFIC\n};\n\n//显示的项目\nclass CommonDisplayItem\n{\npublic:\n    CommonDisplayItem() {}\n    CommonDisplayItem(DisplayItem item);\n    CommonDisplayItem(IPluginItem* item);\n\n    bool operator<(const CommonDisplayItem&) const;\n    bool operator==(const CommonDisplayItem&) const;\n\n    //是否为插件项目\n    bool IsPlugin() const;\n\n    //获取内置的显示项目\n    DisplayItem ItemType() const;\n\n    //获取插件显示项目\n    IPluginItem* PluginItem() const;\n\n    //获取显示项目的名称\n    CString GetItemName() const;\n\n    //获取一个显示项目的默认显示文本\n    std::wstring DefaultString(bool is_main_window) const;\n\n    //获取一个显示项目的显示文本保存在ini文件中的key的名称\n    const wchar_t* GetItemIniKeyName() const;\n\n    /**\n     * @brief   获取一个显示项目的数值文本\n     * @param   is_main_window 如果为true则为主窗口，否则为任务栏窗口\n     * @return  显示的文本\n     */\n    CString GetItemValueText(bool is_main_window) const;\n\n    /**\n     * @brief   获取一个显示项目的数值示例文本\n     * @param   is_main_window 如果为true则为主窗口，否则为任务栏窗口\n     * @return  示例文本\n     */\n    CString GetItemValueSampleText(bool is_main_window) const;\n\nprivate:\n    bool is_plugin{};           //是否为插件项目\n    DisplayItem item_type{};    //内置的显示项目\n    IPluginItem* plugin_item{}; //插件显示项目\n};\n\n\nclass DisplayItemSet\n{\npublic:\n    DisplayItemSet(){}\n    DisplayItemSet(std::initializer_list<DisplayItem> items);\n\n    void Add(DisplayItem item);\n    void Remove(DisplayItem item);\n    bool Contains(DisplayItem item) const;\n\n    int ToInt() const;\n    void FromInt(int value);\n    bool IsEmpty() const;\n\nprivate:\n    std::set<DisplayItem> data;\n};\n"
  },
  {
    "path": "TrafficMonitor/DisplayTextSettingDlg.cpp",
    "content": "﻿// DisplayTextSettingDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"DisplayTextSettingDlg.h\"\n#include \"TrafficMonitorDlg.h\"\n#include \"SkinManager.h\"\n\n\n// CDisplayTextSettingDlg 对话框\n\nIMPLEMENT_DYNAMIC(CDisplayTextSettingDlg, CBaseDialog)\n\nCDisplayTextSettingDlg::CDisplayTextSettingDlg(DispStrings& display_texts, bool main_window_text, CWnd* pParent /*=nullptr*/)\n\t: CBaseDialog(IDD_DISPLAY_TEXT_SETTINGS_DIALOG, pParent), m_display_texts(display_texts), m_main_window_text(main_window_text)\n{\n\n}\n\nCDisplayTextSettingDlg::~CDisplayTextSettingDlg()\n{\n}\n\nvoid CDisplayTextSettingDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_LIST1, m_list_ctrl);\n}\n\n\nCString CDisplayTextSettingDlg::GetDialogName() const\n{\n    return _T(\"DisplayTextSettingDlg\");\n}\n\nBEGIN_MESSAGE_MAP(CDisplayTextSettingDlg, CBaseDialog)\n    ON_BN_CLICKED(IDC_RESTORE_DEFAULT_BUTTON, &CDisplayTextSettingDlg::OnBnClickedRestoreDefaultButton)\n    ON_COMMAND(ID_RESTORE_DEFAULT, &CDisplayTextSettingDlg::OnRestoreDefault)\n    ON_NOTIFY(NM_RCLICK, IDC_LIST1, &CDisplayTextSettingDlg::OnNMRClickList1)\n    ON_WM_INITMENU()\n    ON_NOTIFY(NM_CLICK, IDC_LIST1, &CDisplayTextSettingDlg::OnNMClickList1)\nEND_MESSAGE_MAP()\n\n\n// CDisplayTextSettingDlg 消息处理程序\n\n\nBOOL CDisplayTextSettingDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n\n    SetIcon(theApp.GetMenuIcon(IDI_ITEM), FALSE);\t\t// 设置小图标\n\n    //初始化列表控件\n    CRect rect;\n    m_list_ctrl.GetClientRect(rect);\n    m_list_ctrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);\n    int width0, width1;\n    width0 = rect.Width() / 2;\n    width1 = rect.Width() - width0 - theApp.DPI(20) - 1;\n    m_list_ctrl.InsertColumn(0, CCommon::LoadText(IDS_ITEM), LVCFMT_LEFT, width0);\t\t//插入第0列\n    m_list_ctrl.InsertColumn(1, CCommon::LoadText(IDS_VALUE), LVCFMT_LEFT, width1);\t\t//插入第1列\n\n    //如果是主窗口，清除当前皮肤中没有的行\n    if (m_main_window_text)\n    {\n        std::set<CommonDisplayItem> all_skin_items;\n        CTrafficMonitorDlg::Instance()->GetCurSkin().GetSkinDisplayItems(all_skin_items);\n\n        DispStrings temp = m_display_texts;\n        m_display_texts = DispStrings();\n        for (const auto& display_item : all_skin_items)\n        {\n            m_display_texts.Get(display_item) = temp.GetConst(display_item);\n        }\n    }\n\n    //向列表中插入行\n    for (auto iter = m_display_texts.GetAllItems().begin(); iter != m_display_texts.GetAllItems().end(); ++iter)\n    {\n        CString item_name = iter->first.GetItemName();\n        if (!item_name.IsEmpty())\n        {\n            int index = m_list_ctrl.GetItemCount();\n            m_list_ctrl.InsertItem(index, item_name);\n            m_list_ctrl.SetItemText(index, 1, iter->second.c_str());\n            m_list_ctrl.SetItemData(index, (DWORD_PTR)&(iter->first));\n        }\n    }\n\n    m_list_ctrl.SetEditColMethod(CListCtrlEx::EC_SPECIFIED);        //设置列表可编辑\n    m_list_ctrl.SetEditableCol({ 1 });                              //设置可编辑的列\n\n    CCommon::LoadMenuResource(m_menu, IDR_DISPLAY_ITEM_CONTEXT_MENU); //装载右键菜单\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\nCommonDisplayItem CDisplayTextSettingDlg::GetDisplayItem(int row)\n{\n    CommonDisplayItem* item = (CommonDisplayItem*)m_list_ctrl.GetItemData(row);\n    return *item;\n}\n\nvoid CDisplayTextSettingDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n\n    int item_count = m_list_ctrl.GetItemCount();\n    for (int i{}; i < item_count; i++)\n    {\n        CommonDisplayItem display_item = GetDisplayItem(i);\n        m_display_texts.Get(display_item) = m_list_ctrl.GetItemText(i, 1).GetString();\n    }\n\n    CBaseDialog::OnOK();\n}\n\n\n\nvoid CDisplayTextSettingDlg::OnBnClickedRestoreDefaultButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    int item_count = m_list_ctrl.GetItemCount();\n    CTrafficMonitorDlg* pMainWnd = CTrafficMonitorDlg::Instance();\n    if (m_main_window_text && pMainWnd != nullptr)\n    {\n        //主窗口恢复默认显示文本时，从皮肤获取\n        SkinSettingData skin_setting_data;\n        CSkinManager::SkinSettingDataFronSkin(skin_setting_data, pMainWnd->GetCurSkin());\n        for (int i{}; i < item_count; i++)\n        {\n            CommonDisplayItem display_item = GetDisplayItem(i);\n            std::wstring default_text = skin_setting_data.disp_str.GetConst(display_item);\n            m_list_ctrl.SetItemText(i, 1, default_text.c_str());\n        }\n    }\n    else\n    {\n        for (int i{}; i < item_count; i++)\n        {\n            CommonDisplayItem display_item = GetDisplayItem(i);\n            std::wstring default_text = display_item.DefaultString(m_main_window_text);\n            m_list_ctrl.SetItemText(i, 1, default_text.c_str());\n        }\n    }\n}\n\nvoid CDisplayTextSettingDlg::OnRestoreDefault()\n{\n    if (m_item_selected >= 0)\n    {\n        CTrafficMonitorDlg* pMainWnd = CTrafficMonitorDlg::Instance();\n        if (m_main_window_text && pMainWnd != nullptr)\n        {\n            //主窗口恢复默认显示文本时，从皮肤获取\n            SkinSettingData skin_setting_data;\n            CSkinManager::SkinSettingDataFronSkin(skin_setting_data, pMainWnd->GetCurSkin());\n            CommonDisplayItem display_item = GetDisplayItem(m_item_selected);\n            std::wstring default_text = skin_setting_data.disp_str.GetConst(display_item);\n            m_list_ctrl.SetItemText(m_item_selected, 1, default_text.c_str());\n        }\n        else\n        {\n            CommonDisplayItem display_item = GetDisplayItem(m_item_selected);\n            std::wstring default_text = display_item.DefaultString(m_main_window_text);\n            m_list_ctrl.SetItemText(m_item_selected, 1, default_text.c_str());\n        }\n    }\n}\n\nvoid CDisplayTextSettingDlg::OnNMRClickList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    m_item_selected = pNMItemActivate->iItem;\n    //弹出右键菜单\n    CMenu* pContextMenu = m_menu.GetSubMenu(0);\t//获取第一个弹出菜单\n    CPoint point1;\t//定义一个用于确定光标位置的位置\n    GetCursorPos(&point1);\t//获取当前光标的位置，以便使得菜单可以跟随光标\n    pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this); //在指定位置显示弹出菜单\n\n    *pResult = 0;\n}\n\nvoid CDisplayTextSettingDlg::OnInitMenu(CMenu* pMenu)\n{\n    CBaseDialog::OnInitMenu(pMenu);\n\n    bool selected_enable{ m_item_selected >= 0 };\n    pMenu->EnableMenuItem(ID_RESTORE_DEFAULT, MF_BYCOMMAND | (selected_enable ? MF_ENABLED : MF_GRAYED));\n}\n\nvoid CDisplayTextSettingDlg::OnNMClickList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    m_item_selected = pNMItemActivate->iItem;\n    *pResult = 0;\n}\n"
  },
  {
    "path": "TrafficMonitor/DisplayTextSettingDlg.h",
    "content": "﻿#pragma once\n#include \"BaseDialog.h\"\n#include \"CommonData.h\"\n#include \"ListCtrlEx.h\"\n\n// CDisplayTextSettingDlg 对话框\n\nclass CDisplayTextSettingDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CDisplayTextSettingDlg)\n\npublic:\n\tCDisplayTextSettingDlg(DispStrings& display_texts, bool main_window_text = false, CWnd* pParent = nullptr);   // 标准构造函数\n\tvirtual ~CDisplayTextSettingDlg();\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_DISPLAY_TEXT_SETTINGS_DIALOG };\n#endif\n\nprivate:\n    DispStrings& m_display_texts;\n\n    CListCtrlEx m_list_ctrl;\n    bool m_main_window_text{ false };       //如果为true，则为主窗口文本设置，否则为任务栏窗口设置\n    CMenu m_menu;\n    int m_item_selected{ -1 };\n\nprotected:\n    virtual CString GetDialogName() const override;\n    CommonDisplayItem GetDisplayItem(int row);\n\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n\tDECLARE_MESSAGE_MAP()\n\npublic:\n    virtual BOOL OnInitDialog();\n    virtual void OnOK();\n    afx_msg void OnBnClickedRestoreDefaultButton();\n    afx_msg void OnRestoreDefault();\n    afx_msg void OnNMRClickList1(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnInitMenu(CMenu* pMenu);\n    afx_msg void OnNMClickList1(NMHDR* pNMHDR, LRESULT* pResult);\n};\n"
  },
  {
    "path": "TrafficMonitor/DllFunctions.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"DllFunctions.h\"\n\nCDllFunctions::CDllFunctions()\n{\n    // shellscalingapi\n    m_shcore_module = ::LoadLibrary(_T(\"Shcore.dll\"));\n    if (m_shcore_module != NULL)\n    {\n        m_getDpiForMonitor = (_GetDpiForMonitor)::GetProcAddress(m_shcore_module, \"GetDpiForMonitor\");\n    }\n}\n\nCDllFunctions::~CDllFunctions()\n{\n    if (m_shcore_module != NULL)\n    {\n        FreeLibrary(m_shcore_module);\n        m_shcore_module = NULL;\n    }\n}\n\nHRESULT CDllFunctions::GetDpiForMonitor(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY)\n{\n    if (m_getDpiForMonitor != nullptr)\n        return m_getDpiForMonitor(hmonitor, dpiType, dpiX, dpiY);\n    return E_NOINTERFACE;\n}\n\n#define TRAFFICMONITOR_DEFINE_STATIC_MEMBER_IN_DLL_FUNCTIONS(member_name, ...) \\\n    decltype(CDllFunctions::member_name) CDllFunctions::member_name(__VA_ARGS__)\n\nTRAFFICMONITOR_DEFINE_STATIC_MEMBER_IN_DLL_FUNCTIONS(\n    D3DCompile,\n    _T(\"d3dcompiler_47.dll\"), \"D3DCompile\");\n\nTRAFFICMONITOR_DEFINE_STATIC_MEMBER_IN_DLL_FUNCTIONS(\n    DCompositionCreateDevice,\n    _T(\"dcomp.dll\"), \"DCompositionCreateDevice\");\n\nTRAFFICMONITOR_DEFINE_STATIC_MEMBER_IN_DLL_FUNCTIONS(\n    CreateDXGIFactory2,\n    _T(\"dxgi.dll\"), \"CreateDXGIFactory2\");"
  },
  {
    "path": "TrafficMonitor/DllFunctions.h",
    "content": "﻿#pragma once\n#include <shellscalingapi.h> // 包含::GetDpiForMonitor\n#include <d3dcompiler.h> // 包含D3DCompile\n#include <dcomp.h> // 包含DCompositionCreateDevice\n#include <dxgi1_3.h> // 包含CreateDXGIFactory2\n#include <tchar.h>\n#include <utility>\n\ntemplate <class FunctionPointer>\nclass CDllFunction\n#ifdef WIN32\n{\n    // workaround for MSVC 19.34.31933 target x86\n\nprivate:\n    FunctionPointer m_p_function{nullptr};\n    HMODULE m_h_dll;\n\npublic:\n    CDllFunction(LPCTSTR dll_name, LPCSTR function_name) noexcept\n    {\n        m_h_dll = ::LoadLibrary(dll_name);\n        if (m_h_dll != NULL)\n        {\n            m_p_function = (FunctionPointer)::GetProcAddress(m_h_dll, function_name);\n            if (m_p_function == nullptr)\n            {\n                ::FreeLibrary(m_h_dll);\n                m_h_dll = NULL;\n            }\n        }\n    }\n    ~CDllFunction() noexcept\n    {\n        if (m_h_dll != NULL)\n        {\n            ::FreeLibrary(m_h_dll);\n            m_h_dll = NULL;\n        }\n    }\n    template <class... Args>\n    auto operator()(Args&&... args) const\n    {\n        return m_p_function(std::forward<Args>(args)...);\n    }\n    bool HasValue() const noexcept\n    {\n        return m_p_function != nullptr;\n    }\n}\n#endif\n;\n/**\n * @brief 可以自动管理HMODULE生命周期，并自动尝试加载指定函数的类\n 使用示例：\n    定义：CDllFunction<decltype(&::GetDpiForMonitor)> GetDpiForMonitor{_T(\"Shcore.dll\"), \"GetDpiForMonitor\"};\n    使用：(某个类或者命名空间)::GetDpiForMonitor(所需的参数);\n    当然，变量GetDpiForMonitor不能暴露在全局命名空间内。\n *\n * @tparam R 函数返回值\n * @tparam Args 函数参数\n */\ntemplate <class R, class... Args>\nclass CDllFunction<R (*)(Args...)>\n{\n    using FunctionPointer = R (*)(Args...);\n\nprivate:\n    FunctionPointer m_p_function{nullptr};\n    HMODULE m_h_dll;\n\npublic:\n    CDllFunction(LPCTSTR dll_name, LPCSTR function_name) noexcept\n    {\n        m_h_dll = ::LoadLibrary(dll_name);\n        if (m_h_dll != NULL)\n        {\n            m_p_function = (FunctionPointer)::GetProcAddress(m_h_dll, function_name);\n            if (m_p_function == nullptr)\n            {\n                ::FreeLibrary(m_h_dll);\n                m_h_dll = NULL;\n            }\n        }\n    }\n    ~CDllFunction() noexcept\n    {\n        if (m_h_dll != NULL)\n        {\n            ::FreeLibrary(m_h_dll);\n            m_h_dll = NULL;\n        }\n    }\n    R operator()(Args... args) const\n    {\n        return m_p_function(args...);\n    }\n    bool HasValue() const noexcept\n    {\n        return m_p_function != nullptr;\n    }\n};\n\ntypedef HRESULT(WINAPI* _GetDpiForMonitor)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);\n\nclass CDllFunctions\n{\npublic:\n    CDllFunctions();\n    ~CDllFunctions();\n\npublic:\n    HRESULT GetDpiForMonitor(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);\n    static const CDllFunction<decltype(&::D3DCompile)> D3DCompile;\n    static const CDllFunction<decltype(&::DCompositionCreateDevice)> DCompositionCreateDevice;\n    static const CDllFunction<decltype(&::CreateDXGIFactory2)> CreateDXGIFactory2;\n\nprivate:\n    _GetDpiForMonitor m_getDpiForMonitor{};\n\nprivate:\n    HMODULE m_shcore_module{};\n};\n"
  },
  {
    "path": "TrafficMonitor/DrawCommon.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"DrawCommon.h\"\n#include \"TrafficMonitor.h\"\n\nCDrawCommon::CDrawCommon()\n{\n}\n\nCDrawCommon::~CDrawCommon()\n{\n}\n\nvoid CDrawCommon::Create(CDC* pDC, CWnd* pMainWnd)\n{\n    m_pDC = pDC;\n    m_pMainWnd = pMainWnd;\n    if (pMainWnd != nullptr)\n        m_pfont = m_pMainWnd->GetFont();\n}\n\nvoid CDrawCommon::SetFont(CFont* pfont)\n{\n    m_pfont = pfont;\n    m_pDC->SelectObject(m_pfont);\n}\n\nvoid CDrawCommon::SetDC(CDC* pDC)\n{\n    m_pDC = pDC;\n}\n\nvoid CDrawCommon::DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align, bool draw_back_ground, bool multi_line, BYTE alpha)\n{\n    m_pDC->SetTextColor(color);\n    if (!draw_back_ground)\n        m_pDC->SetBkMode(TRANSPARENT);\n    m_pDC->SelectObject(m_pfont);\n    CSize text_size = m_pDC->GetTextExtent(lpszString);\n\n    auto format = DrawCommonHelper::ProccessTextFormat(rect, text_size, align, multi_line);\n\n    if (draw_back_ground)\n        m_pDC->FillSolidRect(rect, m_back_color);\n    m_pDC->DrawText(lpszString, rect, format);\n}\n\nvoid CDrawCommon::SetDrawRect(CRect rect)\n{\n    CRgn rgn;\n    rgn.CreateRectRgnIndirect(rect);\n    m_pDC->SelectClipRgn(&rgn);\n}\n\nvoid CDrawCommon::SetDrawRect(CDC* pDC, CRect rect)\n{\n    CRgn rgn;\n    rgn.CreateRectRgnIndirect(rect);\n    pDC->SelectClipRgn(&rgn);\n}\n\nvoid CDrawCommon::DrawBitmap(CBitmap& bitmap, CPoint start_point, CSize size, StretchMode stretch_mode)\n{\n    CDC memDC;\n\n    //获取图像实际大小\n    BITMAP bm;\n    GetObject(bitmap, sizeof(BITMAP), &bm);\n\n    memDC.CreateCompatibleDC(m_pDC);\n    memDC.SelectObject(&bitmap);\n    // 以下两行避免图片失真\n    m_pDC->SetStretchBltMode(HALFTONE);\n    m_pDC->SetBrushOrg(0, 0);\n\n    DrawCommonHelper::ImageDrawAreaConvert(CSize(bm.bmWidth, bm.bmHeight), start_point, size, stretch_mode);\n\n    m_pDC->StretchBlt(start_point.x, start_point.y, size.cx, size.cy, &memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);\n    memDC.DeleteDC();\n}\n\nvoid CDrawCommon::DrawBitmap(UINT bitmap_id, CPoint start_point, CSize size, StretchMode stretch_mode)\n{\n    CBitmap bitmap;\n    bitmap.LoadBitmap(bitmap_id);\n    DrawBitmap(bitmap, start_point, size, stretch_mode);\n}\n\nvoid CDrawCommon::DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode, BYTE)\n{\n    CBitmap bitmap;\n    if (!bitmap.Attach(hbitmap))\n        return;\n    DrawBitmap(bitmap, start_point, size, stretch_mode);\n    bitmap.Detach();\n}\n\nvoid CDrawCommon::DrawIcon(HICON hIcon, CPoint start_point, CSize size)\n{\n    if (m_pDC->GetSafeHdc() == NULL)\n        return;\n    if (size.cx == 0 || size.cy == 0)\n        ::DrawIconEx(m_pDC->GetSafeHdc(), start_point.x, start_point.y, hIcon, 0, 0, 0, NULL, DI_NORMAL | DI_DEFAULTSIZE);\n    else\n        ::DrawIconEx(m_pDC->GetSafeHdc(), start_point.x, start_point.y, hIcon, size.cx, size.cy, 0, NULL, DI_NORMAL);\n}\n\nvoid CDrawCommon::BitmapStretch(CImage* pImage, CImage* ResultImage, CSize size)\n{\n    if (pImage->IsDIBSection())\n    {\n        // 取得 pImage 的 DC\n        CDC* pImageDC1 = CDC::FromHandle(pImage->GetDC()); // Image 因為有自己的 DC, 所以必須使用 FromHandle 取得對應的 DC\n\n        CBitmap* bitmap1 = pImageDC1->GetCurrentBitmap();\n        BITMAP bmpInfo;\n        bitmap1->GetBitmap(&bmpInfo);\n\n        // 建立新的 CImage\n        ResultImage->Create(size.cx, size.cy, bmpInfo.bmBitsPixel);\n        CDC* ResultImageDC = CDC::FromHandle(ResultImage->GetDC());\n\n        // 當 Destination 比較小的時候, 會根據 Destination DC 上的 Stretch Blt mode 決定是否要保留被刪除點的資訊\n        ResultImageDC->SetStretchBltMode(HALFTONE);        // 使用最高品質的方式\n        ::SetBrushOrgEx(ResultImageDC->m_hDC, 0, 0, NULL); // 調整 Brush 的起點\n\n        // 把 pImage 畫到 ResultImage 上面\n        StretchBlt(*ResultImageDC, 0, 0, size.cx, size.cy, *pImageDC1, 0, 0, pImage->GetWidth(), pImage->GetHeight(), SRCCOPY);\n        // pImage->Draw(*ResultImageDC,0,0,StretchWidth,StretchHeight,0,0,pImage->GetWidth(),pImage->GetHeight());\n\n        pImage->ReleaseDC();\n        ResultImage->ReleaseDC();\n    }\n}\n\nvoid CDrawCommon::FillRect(CRect rect, COLORREF color, BYTE alpha)\n{\n    m_pDC->FillSolidRect(rect, color);\n}\n\nvoid CDrawCommon::FillRectWithBackColor(CRect rect)\n{\n    m_pDC->FillSolidRect(rect, m_back_color);\n}\n\nvoid CDrawCommon::DrawRectOutLine(CRect rect, COLORREF color, int width, bool dot_line, BYTE alpha)\n{\n    CPen aPen, *pOldPen;\n    aPen.CreatePen((dot_line ? PS_DOT : PS_SOLID), width, color);\n    pOldPen = m_pDC->SelectObject(&aPen);\n    CBrush* pOldBrush{dynamic_cast<CBrush*>(m_pDC->SelectStockObject(NULL_BRUSH))};\n\n    rect.DeflateRect(width / 2, width / 2);\n    m_pDC->Rectangle(rect);\n    m_pDC->SelectObject(pOldPen);\n    m_pDC->SelectObject(pOldBrush); // Restore the old brush\n    aPen.DeleteObject();\n}\n\nvoid CDrawCommon::GetRegionFromImage(CRgn& rgn, CBitmap& cBitmap, int threshold)\n{\n    CDC memDC;\n\n    memDC.CreateCompatibleDC(NULL);\n    CBitmap* pOldMemBmp = NULL;\n    pOldMemBmp = memDC.SelectObject(&cBitmap);\n\n    //创建总的窗体区域，初始region为0\n    rgn.CreateRectRgn(0, 0, 0, 0);\n\n    BITMAP bit;\n    cBitmap.GetBitmap(&bit); //取得位图参数，这里要用到位图的长和宽\n    int y;\n    for (y = 0; y < bit.bmHeight; y++)\n    {\n        CRgn rgnTemp; //保存临时region\n        int iX = 0;\n        do\n        {\n            //跳过透明色找到下一个非透明色的点.\n            while (iX < bit.bmWidth && GetColorBritness(memDC.GetPixel(iX, y)) <= threshold)\n                iX++;\n            int iLeftX = iX; //记住这个起始点\n\n            //寻找下个透明色的点\n            while (iX < bit.bmWidth && GetColorBritness(memDC.GetPixel(iX, y)) > threshold)\n                ++iX;\n\n            //创建一个包含起点与重点间高为1像素的临时“region”\n            rgnTemp.CreateRectRgn(iLeftX, y, iX, y + 1);\n            rgn.CombineRgn(&rgn, &rgnTemp, RGN_OR);\n\n            //删除临时\"region\",否则下次创建时和出错\n            rgnTemp.DeleteObject();\n        } while (iX < bit.bmWidth);\n    }\n    memDC.DeleteDC();\n}\n\nint CDrawCommon::GetColorBritness(COLORREF color)\n{\n    return (GetRValue(color) + GetGValue(color) + GetBValue(color)) / 3;\n}\n\nvoid CDrawCommon::DrawLine(CPoint start_point, int height, COLORREF color, BYTE alpha)\n{\n    CPen aPen, *pOldPen;\n    aPen.CreatePen(PS_SOLID, 1, color);\n    pOldPen = m_pDC->SelectObject(&aPen);\n    CBrush* pOldBrush{dynamic_cast<CBrush*>(m_pDC->SelectStockObject(NULL_BRUSH))};\n\n    m_pDC->MoveTo(start_point); //移动到起始点，默认是从下向上画\n    m_pDC->LineTo(CPoint(start_point.x, start_point.y - height));\n    m_pDC->SelectObject(pOldPen);\n    m_pDC->SelectObject(pOldBrush); // Restore the old brush\n    aPen.DeleteObject();\n}\n\nint CDrawCommon::GetTextWidth(LPCTSTR lpszString)\n{\n    return m_pDC->GetTextExtent(lpszString).cx;\n}\n\nUINT DrawCommonHelper::ProccessTextFormat(CRect rect, CSize text_length, IDrawCommon::Alignment align, bool multi_line) noexcept\n{\n    UINT result; // CDC::DrawText()函数的文本格式\n    if (multi_line)\n        result = DT_EDITCONTROL | DT_WORDBREAK | DT_NOPREFIX;\n    else\n        result = DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX;\n\n    if (text_length.cx > rect.Width()) //如果文本宽度超过了矩形区域的宽度，设置了居中时左对齐\n    {\n        if (align == IDrawCommon::Alignment::RIGHT)\n            result |= DT_RIGHT;\n    }\n    else\n    {\n        switch (align)\n        {\n        case IDrawCommon::Alignment::RIGHT:\n            result |= DT_RIGHT;\n            break;\n        case IDrawCommon::Alignment::CENTER:\n            result |= DT_CENTER;\n            break;\n        }\n    }\n    return result;\n}\n\nvoid DrawCommonHelper::ImageDrawAreaConvert(CSize image_size, CPoint& start_point, CSize& size, IDrawCommon::StretchMode stretch_mode)\n{\n    if (size.cx == 0 || size.cy == 0)       //如果指定的size为0，则使用位图的实际大小绘制\n    {\n        size = CSize(image_size.cx, image_size.cy);\n    }\n    else\n    {\n        if (stretch_mode == IDrawCommon::StretchMode::FILL)\n        {\n            float w_h_ratio, w_h_ratio_draw;        //图像的宽高比、绘制大小的宽高比\n            w_h_ratio = static_cast<float>(image_size.cx) / image_size.cy;\n            w_h_ratio_draw = static_cast<float>(size.cx) / size.cy;\n            if (w_h_ratio > w_h_ratio_draw)     //如果图像的宽高比大于绘制区域的宽高比，则需要裁剪两边的图像\n            {\n                int image_width;        //按比例缩放后的宽度\n                image_width = image_size.cx * size.cy / image_size.cy;\n                start_point.x -= ((image_width - size.cx) / 2);\n                size.cx = image_width;\n            }\n            else\n            {\n                int image_height;       //按比例缩放后的高度\n                image_height = image_size.cy * size.cx / image_size.cx;\n                start_point.y -= ((image_height - size.cy) / 2);\n                size.cy = image_height;\n            }\n        }\n        else if (stretch_mode == IDrawCommon::StretchMode::FIT)\n        {\n            CSize draw_size = image_size;\n            float w_h_ratio, w_h_ratio_draw;        //图像的宽高比、绘制大小的宽高比\n            w_h_ratio = static_cast<float>(image_size.cx) / image_size.cy;\n            w_h_ratio_draw = static_cast<float>(size.cx) / size.cy;\n            if (w_h_ratio > w_h_ratio_draw)     //如果图像的宽高比大于绘制区域的宽高比\n            {\n                draw_size.cy = draw_size.cy * size.cx / draw_size.cx;\n                draw_size.cx = size.cx;\n                start_point.y += ((size.cy - draw_size.cy) / 2);\n            }\n            else\n            {\n                draw_size.cx = draw_size.cx * size.cy / draw_size.cy;\n                draw_size.cy = size.cy;\n                start_point.x += ((size.cx - draw_size.cx) / 2);\n            }\n            size = draw_size;\n        }\n    }\n}\n\nvoid DrawCommonHelper::GetBitmapAlphaPixel(HBITMAP hBitmap, std::set<Point>& points)\n{\n    points.clear();\n    BITMAP bm;\n    GetObject(hBitmap, sizeof(BITMAP), &bm);\n\n    int width = bm.bmWidth;\n    int height = bm.bmHeight;\n\n    // 获取位图的像素数据\n    BITMAPINFO bmpInfo = { 0 };\n    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n    bmpInfo.bmiHeader.biWidth = width;\n    bmpInfo.bmiHeader.biHeight = -height; // top-down DIB\n    bmpInfo.bmiHeader.biPlanes = 1;\n    bmpInfo.bmiHeader.biBitCount = 32;\n    bmpInfo.bmiHeader.biCompression = BI_RGB;\n\n    HDC hdc = CreateCompatibleDC(NULL);\n    SelectObject(hdc, hBitmap);\n\n    // 分配内存存储位图像素\n    RGBQUAD* pPixels = new RGBQUAD[width * height];\n    GetDIBits(hdc, hBitmap, 0, height, pPixels, &bmpInfo, DIB_RGB_COLORS);\n\n    // 遍历所有像素点\n    for (int y = 0; y < height; ++y)\n    {\n        for (int x = 0; x < width; ++x)\n        {\n            int index = y * width + x;\n            //添加alpha值为0的像素点\n            if (pPixels[index].rgbReserved == 0)\n                points.insert(Point(x, y));\n        }\n    }\n\n    delete[] pPixels;\n    DeleteDC(hdc);\n\n}\n\nvoid DrawCommonHelper::FixBitmapTextAlpha(HBITMAP hBitmap, BYTE alpha, std::set<Point> alpha_points)\n{\n    BITMAP bm;\n    GetObject(hBitmap, sizeof(BITMAP), &bm);\n\n    int width = bm.bmWidth;\n    int height = bm.bmHeight;\n\n    // 获取位图的像素数据\n    BITMAPINFO bmpInfo = { 0 };\n    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n    bmpInfo.bmiHeader.biWidth = width;\n    bmpInfo.bmiHeader.biHeight = -height; // top-down DIB\n    bmpInfo.bmiHeader.biPlanes = 1;\n    bmpInfo.bmiHeader.biBitCount = 32;\n    bmpInfo.bmiHeader.biCompression = BI_RGB;\n\n    HDC hdc = CreateCompatibleDC(NULL);\n    SelectObject(hdc, hBitmap);\n\n    // 分配内存存储位图像素\n    RGBQUAD* pPixels = new RGBQUAD[width * height];\n    GetDIBits(hdc, hBitmap, 0, height, pPixels, &bmpInfo, DIB_RGB_COLORS);\n\n    // 遍历所有像素\n    for (int y = 0; y < height; ++y)\n    {\n        for (int x = 0; x < width; ++x)\n        {\n            int index = y * width + x;\n            //如果检测到alpha值为0，但是却不在alpha_points里，将其修正为正确的alpha值\n            if (pPixels[index].rgbReserved == 0 && !alpha_points.contains(Point(x, y)))\n                pPixels[index].rgbReserved = alpha; // 设置Alpha通道\n        }\n    }\n\n    // 将修改后的像素数据写回位图\n    SetDIBits(hdc, hBitmap, 0, height, pPixels, &bmpInfo, DIB_RGB_COLORS);\n\n    delete[] pPixels;\n    DeleteDC(hdc);\n}\n"
  },
  {
    "path": "TrafficMonitor/DrawCommon.h",
    "content": "﻿//封装的绘图类\n#pragma once\n#include \"IDrawCommon.h\"\n#include \"D2D1Support.h\"\n#include \"CommonData.h\"\n#include \"Nullable.hpp\"\n\nclass CDrawCommon final : public IDrawCommon\n{\npublic:\n\n    CDrawCommon();\n    ~CDrawCommon();\n\n    void Create(CDC* pDC, CWnd* pMainWnd);\n    void SetFont(CFont* pfont) override;\t\t//设置绘制文本的字体\n    void SetDC(CDC* pDC);\t\t//设置绘图的DC\n    virtual CDC* GetDC() override { return m_pDC; }\n    void SetBackColor(COLORREF back_color, BYTE alpha = 255) override { m_back_color = back_color; }\n    void SetTextColor(const COLORREF text_color, BYTE alpha = 255) override\n    {\n        m_pDC->SetTextColor(text_color);\n    }\n\n    void DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align = Alignment::LEFT, bool draw_back_ground = false, bool multi_line = false, BYTE alpha = 255) override; //在指定的矩形区域内绘制文本\n\n    void SetDrawRect(CRect rect) override;\t\t//设置绘图剪辑区域\n    static void SetDrawRect(CDC* pDC, CRect rect);\n\n    //绘制一个位图\n    //（注意：当stretch_mode设置为StretchMode::FILL（填充）时，会设置绘图剪辑区域，如果之后需要绘制其他图形，\n    //需要重新设置绘图剪辑区域，否则图片外的区域会无法绘制）\n    void DrawBitmap(CBitmap& bitmap, CPoint start_point, CSize size, StretchMode stretch_mode = StretchMode::STRETCH);\n    void DrawBitmap(UINT bitmap_id, CPoint start_point, CSize size, StretchMode stretch_mode = StretchMode::STRETCH);\n    void DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode = StretchMode::STRETCH, BYTE alpha = 255) override;\n\n    void DrawIcon(HICON hIcon, CPoint start_point, CSize size);\n\n    //将图片拉伸到指定尺寸(https://blog.csdn.net/sichuanpb/article/details/22986877)\n    static void BitmapStretch(CImage* pImage, CImage* ResultImage, CSize size);\n\n    void FillRect(CRect rect, COLORREF color, BYTE alpha = 255) override; //用纯色填充矩形\n    void FillRectWithBackColor(CRect rect);\t\t\t//使用背景色填充矩形\n    void DrawRectOutLine(CRect rect, COLORREF color, int width = 1, bool dot_line = false, BYTE alpha = 255) override; //绘制矩形边框。如果dot_line为true，则为虚线\n\n    //从图像创建区域，如果像素点的亮度小于threshold（取值为0~255，0为黑色，255为白色），则该像素点在区域外\n    //https://blog.csdn.net/tajon1226/article/details/6589180\n    static void GetRegionFromImage(CRgn& rgn, CBitmap& cBitmap, int threshold);\n\n    void DrawLine(CPoint start_point, int height, COLORREF color, BYTE alpha = 255) override; //使用当前画笔画线\n\n    virtual int GetTextWidth(LPCTSTR lpszString) override;\n\nprivate:\n    CDC* m_pDC{};\t\t//用于绘图的CDC类的指针\n    CWnd* m_pMainWnd{};\t//绘图窗口的句柄\n    CFont* m_pfont{};\n    COLORREF m_back_color{};\n\n    static int GetColorBritness(COLORREF color);\n};\n\n\n//用于双缓冲绘图的类\nclass CDrawDoubleBuffer final : public IDrawBuffer\n{\npublic:\n    CDrawDoubleBuffer(CDC* pDC, CRect rect)\n        : m_pDC(pDC), m_rect(rect)\n    {\n        if (m_pDC != nullptr)\n        {\n            m_memDC.CreateCompatibleDC(NULL);\n            m_memBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());\n            m_pOldBit = m_memDC.SelectObject(&m_memBitmap);\n        }\n    }\n\n    ~CDrawDoubleBuffer()\n    {\n        if (m_pDC != nullptr)\n        {\n            m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), &m_memDC, 0, 0, SRCCOPY);\n            m_memDC.SelectObject(m_pOldBit);\n            m_memBitmap.DeleteObject();\n            m_memDC.DeleteDC();\n        }\n    }\n\n    CDC* GetMemDC()\n    {\n        return &m_memDC;\n    }\n\nprivate:\n    CDC* m_pDC;\n    CDC m_memDC;\n    CBitmap m_memBitmap;\n    CBitmap* m_pOldBit;\n    CRect m_rect;\n};\n\nnamespace DrawCommonHelper\n{\n    UINT ProccessTextFormat(CRect rect, CSize text_length, IDrawCommon::Alignment align, bool multi_line) noexcept;\n\n    //根据图片拉伸模式，计算绘制图片的实际位置\n    //image_size[int]：图片的原始大小\n    //start_point[int][out]：绘制区域的起始位置\n    //size[int][out]：绘制区域的大小\n    //stretch_mode[int]：拉伸模式\n    void ImageDrawAreaConvert(CSize image_size, CPoint& start_point, CSize& size, IDrawCommon::StretchMode stretch_mode);\n\n    struct Point\n    {\n    public:\n        Point() {}\n        Point(int x, int y)\n            : m_x(x), m_y(y)\n        {}\n        bool operator==(const Point& a) const\n        {\n            return m_x == a.m_x && m_y == a.m_y;\n        }\n        bool operator<(const Point& a) const\n        {\n            if (m_x == a.m_x)\n                return m_y < a.m_y;\n            else\n                return m_x < a.m_x;\n        }\n\n    private:\n        int m_x{};\n        int m_y{};\n    };\n\n    //获取一个位置中完全透明的点，并保存到points中\n    void GetBitmapAlphaPixel(HBITMAP hBitmap, std::set<Point>& points);\n\n    //修正位图中文本部分的Alpha通道\n    //使用了UpdateLayeredWindow后，使用GDI绘制的文本也会变得透明，此函数会遍历bitmap中alpha值为0，但是不在alpha_points中的像素，将其修正为正确的alpha值\n    void FixBitmapTextAlpha(HBITMAP hBitmap, BYTE alpha, std::set<Point> alpha_points);\n};\n"
  },
  {
    "path": "TrafficMonitor/DrawCommonEx.cpp",
    "content": "#include \"stdafx.h\"\n#include \"DrawCommonEx.h\"\n#include \"DrawCommon.h\"\n\nCDrawCommonEx::CDrawCommonEx(CDC* pDC)\n{\n    Create(pDC);\n}\n\nCDrawCommonEx::CDrawCommonEx()\n{\n}\n\n\nCDrawCommonEx::~CDrawCommonEx()\n{\n    SAFE_DELETE(m_pGraphics);\n}\n\nvoid CDrawCommonEx::Create(CDC* pDC)\n{\n    ASSERT(pDC != nullptr);\n    m_pDC = pDC;\n    SAFE_DELETE(m_pGraphics);\n    m_pGraphics = new Gdiplus::Graphics(pDC->GetSafeHdc());\n}\n\nvoid CDrawCommonEx::SetFont(CFont * pFont)\n{\n    //õCDCͼʱCDCGDI+\n    m_pDC->SelectObject(pFont);\n}\n\nvoid CDrawCommonEx::DrawImage(Gdiplus::Image* pImage, CPoint start_point, CSize size, StretchMode stretch_mode)\n{\n    m_pGraphics->SetInterpolationMode(Gdiplus::InterpolationMode::InterpolationModeHighQuality);\n    DrawCommonHelper::ImageDrawAreaConvert(CSize(pImage->GetWidth(), pImage->GetHeight()), start_point, size, stretch_mode);\n    m_pGraphics->DrawImage(pImage, INT(start_point.x), INT(start_point.y), INT(size.cx), INT(size.cy));\n}\n\nvoid CDrawCommonEx::SetBackColor(COLORREF back_color, BYTE alpha)\n{\n    m_back_color = CGdiPlusHelper::COLORREFToGdiplusColor(back_color, alpha);\n}\n\nvoid CDrawCommonEx::DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align, bool draw_back_ground, bool multi_line, BYTE alpha)\n{\n    //\n    Gdiplus::RectF rect_gdiplus = CGdiPlusHelper::CRectToGdiplusRect(rect);\n\n    //Ʊ\n    if (draw_back_ground)\n    {\n        Gdiplus::SolidBrush brush(m_back_color);\n        m_pGraphics->FillRectangle(&brush, rect_gdiplus);\n    }\n    //\n    Gdiplus::Font font(m_pDC->GetSafeHdc());\n    //ıɫ\n    Gdiplus::SolidBrush brush(CGdiPlusHelper::COLORREFToGdiplusColor(color, alpha));\n    //ö뷽ʽ\n    Gdiplus::StringFormat format;\n    Gdiplus::StringAlignment alignment = Gdiplus::StringAlignmentNear;\n    if (align == Alignment::CENTER)\n        alignment = Gdiplus::StringAlignmentCenter;\n    else if (align == Alignment::RIGHT)\n        alignment = Gdiplus::StringAlignmentFar;\n    format.SetAlignment(alignment);    //ˮƽ뷽ʽ\n    format.SetLineAlignment(Gdiplus::StringAlignmentCenter);    //ֱ뷽ʽ\n    UINT flags = Gdiplus::StringFormatFlagsNoFitBlackBox;\n    if (!multi_line)\n        flags |= Gdiplus::StringFormatFlagsNoWrap;      //Զ\n    format.SetTrimming(Gdiplus::StringTrimmingNone);    //ֹıض\n    format.SetFormatFlags(flags);\n\n    //ı\n    m_pGraphics->DrawString(lpszString, -1, &font, rect_gdiplus, &format, &brush);\n}\n\nvoid CDrawCommonEx::SetDrawRect(CRect rect)\n{\n    m_pGraphics->SetClip(CGdiPlusHelper::CRectToGdiplusRect(rect));\n}\n\nvoid CDrawCommonEx::FillRect(CRect rect, COLORREF color, BYTE alpha)\n{\n    Gdiplus::RectF rect_gdiplus = CGdiPlusHelper::CRectToGdiplusRect(rect);\n    Gdiplus::SolidBrush brush(CGdiPlusHelper::COLORREFToGdiplusColor(color, alpha));\n    m_pGraphics->FillRectangle(&brush, rect_gdiplus);\n}\n\nvoid CDrawCommonEx::DrawRectOutLine(CRect rect, COLORREF color, int width, bool dot_line, BYTE alpha)\n{\n}\n\nvoid CDrawCommonEx::DrawLine(CPoint start_point, int height, COLORREF color, BYTE alpha)\n{\n}\n\nvoid CDrawCommonEx::SetTextColor(const COLORREF color, BYTE alpha)\n{\n    m_text_color = CGdiPlusHelper::COLORREFToGdiplusColor(color, alpha);\n}\n\nCDC* CDrawCommonEx::GetDC()\n{\n    return m_pDC;\n}\n\nint CDrawCommonEx::GetTextWidth(LPCTSTR lpszString)\n{\n    Gdiplus::Font font(m_pDC->GetSafeHdc());\n    Gdiplus::RectF textSize;\n    m_pGraphics->MeasureString(lpszString, -1, &font, Gdiplus::PointF(0, 0), &textSize);\n    return textSize.Width;\n}\n\nvoid CDrawCommonEx::DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode, BYTE alpha)\n{\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////////////////\n/////////////////////////////////////////////////////////////////////////////////////////////\nGdiplus::Color CGdiPlusHelper::COLORREFToGdiplusColor(COLORREF color, BYTE alpha /*= 255*/)\n{\n    return Gdiplus::Color(alpha, GetRValue(color), GetGValue(color), GetBValue(color));\n}\n\nCOLORREF CGdiPlusHelper::GdiplusColorToCOLORREF(Gdiplus::Color color)\n{\n    return RGB(color.GetR(), color.GetG(), color.GetB());\n}\n\nCRect CGdiPlusHelper::GdiplusRectToCRect(Gdiplus::RectF rect)\n{\n    return CRect(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());\n}\n\nGdiplus::RectF CGdiPlusHelper::CRectToGdiplusRect(CRect rect)\n{\n    return Gdiplus::RectF(rect.left, rect.top, rect.Width(), rect.Height());\n}\n"
  },
  {
    "path": "TrafficMonitor/DrawCommonEx.h",
    "content": "#pragma once\n#include \"IDrawCommon.h\"\n#include <gdiplus.h>\n\n//ʹGDI+Ļͼ\nclass CDrawCommonEx : public IDrawCommon\n{\npublic:\n    CDrawCommonEx(CDC* pDC);\n    CDrawCommonEx();\n    ~CDrawCommonEx();\n\n    void Create(CDC* pDC);\n    void SetFont(CFont* pFont);\n    Gdiplus::Graphics* GetGraphics() { return m_pGraphics; }\n\n    //һGDI+ͼ\n    void DrawImage(Gdiplus::Image* pImage, CPoint start_point, CSize size, StretchMode stretch_mode);\n\n    // ͨ IDrawCommon ̳\n    void SetBackColor(COLORREF back_color, BYTE alpha) override;\n    void DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align, bool draw_back_ground, bool multi_line, BYTE alpha) override;\n    void SetDrawRect(CRect rect) override;\n    void FillRect(CRect rect, COLORREF color, BYTE alpha) override;\n    void DrawRectOutLine(CRect rect, COLORREF color, int width, bool dot_line, BYTE alpha) override;\n    void DrawLine(CPoint start_point, int height, COLORREF color, BYTE alpha) override;\n    void SetTextColor(const COLORREF color, BYTE alpha) override;\n    void DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode, BYTE alpha) override;\n    virtual CDC* GetDC() override;\n    virtual int GetTextWidth(LPCTSTR lpszString) override;\n\nprivate:\n    CDC* m_pDC{};\n    Gdiplus::Graphics* m_pGraphics{};\n    Gdiplus::Color m_text_color{};\n    Gdiplus::Color m_back_color{};\n};\n\nclass CGdiPlusHelper\n{\npublic:\n    static Gdiplus::Color COLORREFToGdiplusColor(COLORREF color, BYTE alpha = 255);\n    static COLORREF GdiplusColorToCOLORREF(Gdiplus::Color color);\n    static CRect GdiplusRectToCRect(Gdiplus::RectF rect);\n    static Gdiplus::RectF CRectToGdiplusRect(CRect rect);\n};\n"
  },
  {
    "path": "TrafficMonitor/DrawCommonFactory.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"DrawCommonFactory.h\"\n\nauto GetInterfaceFromAllInvolvedDrawCommonObjects(\n    AllInvolvedDrawCommonObjectsStorage& ref_object_storage,\n    DrawCommonHelper::RenderType render_type,\n    std::initializer_list<TaggedAllInvolvedDrawCommonObjectsInitializer> initializer_list)\n    -> std::tuple<IDrawBuffer*, IDrawCommon*>\n{\n    auto& ref_draw_buffer_and_draw_common_objects = *static_cast<InvolvedDrawCommonStorages*>(\n        static_cast<void*>(std::addressof(ref_object_storage)));\n    auto p_draw_buffer = static_cast<IDrawBuffer*>(\n        static_cast<void*>(\n            std::addressof(ref_draw_buffer_and_draw_common_objects.m_draw_buffer_union_storage)));\n    auto p_draw_common = static_cast<IDrawCommon*>(\n        static_cast<void*>(\n            std::addressof(ref_draw_buffer_and_draw_common_objects.m_draw_common_union_storage)));\n\n    for (auto& initializer : initializer_list)\n    {\n        if (initializer.first == render_type)\n        {\n            initializer.second(p_draw_buffer, p_draw_common);\n\n            UniqueIDrawBuffer up_draw_buffer{p_draw_buffer};\n            ref_object_storage.m_unique_draw_buffer.swap(up_draw_buffer);\n            UniqueIDrawCommon up_draw_common{p_draw_common};\n            ref_object_storage.m_unique_draw_common.swap(up_draw_common);\n            return {p_draw_buffer, p_draw_common};\n        }\n    }\n    throw std::runtime_error{TRAFFICMONITOR_ERROR_STR(\"No matching render type for initializer\")};\n}"
  },
  {
    "path": "TrafficMonitor/DrawCommonFactory.h",
    "content": "﻿#pragma once\n#include \"stdafx.h\"\n#include <memory>\n#include \"IDrawCommon.h\"\n#include \"DrawCommon.h\"\n#include \"TaskBarDlgDrawCommon.h\"\n\ntemplate <class T>\nstruct StackObjectDeleter\n{\n    using pointer = std::add_pointer_t<T>;\n    void operator()(pointer p_stack_object) const noexcept\n    {\n        if (p_stack_object)\n        {\n            Destroy(p_stack_object);\n        }\n    }\n};\nusing UniqueIDrawCommon = std::unique_ptr<void, StackObjectDeleter<IDrawCommon>>;\nusing UniqueIDrawBuffer = std::unique_ptr<void, StackObjectDeleter<IDrawBuffer>>;\n\n/**\n * @brief 新增渲染器类型后，将新类型写到下面类型的模板参数中\n *\n */\nusing DrawCommonUnionStorage = AlignedUnionStorage<CDrawCommon, CTaskBarDlgDrawCommon>;\n/**\n * @brief 新增缓冲器（即析构时提交窗口绘制内容到系统的对象）类型后，将新类型写入到下面类型的模板参数中\n *\n */\nusing DrawBufferUnionStorage = AlignedUnionStorage<CDrawDoubleBuffer, CTaskBarDlgDrawBuffer, CTaskBarDlgDrawBufferUseDComposition>;\nstruct InvolvedDrawCommonStorages\n{\n    DrawBufferUnionStorage m_draw_buffer_union_storage{};\n    DrawCommonUnionStorage m_draw_common_union_storage{};\n};\n/**\n * @brief 具有DrawCommon和DrawBuffer栈内存以及它们对应独占指针的栈内存块，\n 注意：它会先析构DrawCommon再析构DrawBuffer\n *\n */\nstruct AllInvolvedDrawCommonObjectsStorage\n{\n    InvolvedDrawCommonStorages m_storage{};\n    // 先析构DrawCommon再析构DrawBuffer\n    UniqueIDrawBuffer m_unique_draw_buffer{};\n    UniqueIDrawCommon m_unique_draw_common{};\n\n    AllInvolvedDrawCommonObjectsStorage() = default;\n    ~AllInvolvedDrawCommonObjectsStorage() = default;\n    // 禁用复制移动\n    AllInvolvedDrawCommonObjectsStorage(const AllInvolvedDrawCommonObjectsStorage&) = delete;\n    AllInvolvedDrawCommonObjectsStorage& operator=(const AllInvolvedDrawCommonObjectsStorage&) = delete;\n};\nusing AllInvolvedDrawCommonObjectsInitializer = std::function<void(IDrawBuffer*, IDrawCommon*)>;\nusing TaggedAllInvolvedDrawCommonObjectsInitializer =\n    std::pair<DrawCommonHelper::RenderType, AllInvolvedDrawCommonObjectsInitializer>;\n\n/**\n * @brief 从栈内存中使用对应RenderType的函数初始化渲染器和缓冲器\n *\n * @param ref_object_storage 栈内存对象，其中包含具有该内存独占所有权的指针\n * @param render_type 渲染器类型枚举\n * @param initializer_list 渲染器类型枚举和对应的初始化函数的总的集合\n * @return std::tuple<IDrawBuffer*, IDrawCommon*> 不具有所有权的裸指针\n */\nauto GetInterfaceFromAllInvolvedDrawCommonObjects(\n    AllInvolvedDrawCommonObjectsStorage& ref_object_storage,\n    DrawCommonHelper::RenderType render_type,\n    std::initializer_list<TaggedAllInvolvedDrawCommonObjectsInitializer> initializer_list)\n    -> std::tuple<IDrawBuffer*, IDrawCommon*>;\n"
  },
  {
    "path": "TrafficMonitor/DrawTextManager.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"DrawTextManager.h\"\n#include <memoryapi.h>\n\nEnableWriteMemoryGuard::~EnableWriteMemoryGuard()\n{\n    m_state = ::VirtualProtect(m_p_memory, m_memory_size, m_last_flag, &m_last_flag);\n}\n\nbool EnableWriteMemoryGuard::GetState()\n{\n    return m_state;\n}\n\nint WINAPI User32DrawTextManager::A::CustomDrawTextA(HDC hdc, LPCSTR lpchText, int cchText, LPRECT lprc, UINT format)\n{\n    if (BaseSettings::GetEnable())\n    {\n        return BaseSettings::m_replaced_function(hdc, lpchText, cchText, lprc, format);\n    }\n    else\n    {\n        return (BaseSettings::GetOriginalFunction())(hdc, lpchText, cchText, lprc, format);\n    }\n}\n\nauto User32DrawTextManager::A::GetFunction() noexcept\n    -> Function\n{\n    return &CustomDrawTextA;\n}\n\nint WINAPI User32DrawTextManager::W::CustomDrawTextW(HDC hdc, LPCWSTR lpchText, int cchText, LPRECT lprc, UINT format)\n{\n    if (BaseSettings::GetEnable())\n    {\n        return BaseSettings::m_replaced_function(hdc, lpchText, cchText, lprc, format);\n    }\n    else\n    {\n        return (BaseSettings::GetOriginalFunction())(hdc, lpchText, cchText, lprc, format);\n    }\n}\n\nauto User32DrawTextManager::W::GetFunction() noexcept\n    -> Function\n{\n    return &CustomDrawTextW;\n}\n\nint WINAPI User32DrawTextManager::ExA::CustomDrawTextExA(HDC hdc, LPSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp)\n{\n    if (BaseSettings::GetEnable())\n    {\n        return BaseSettings::m_replaced_function(hdc, lpchText, cchText, lprc, format, lpdtp);\n    }\n    else\n    {\n        return (BaseSettings::GetOriginalFunction())(hdc, lpchText, cchText, lprc, format, lpdtp);\n    }\n}\n\nauto User32DrawTextManager::ExA::GetFunction() noexcept\n    -> Function\n{\n    return &CustomDrawTextExA;\n}\n\nint WINAPI User32DrawTextManager::ExW::CustomDrawTextExW(HDC hdc, LPWSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp)\n{\n    if (BaseSettings::GetEnable())\n    {\n        return BaseSettings::m_replaced_function(hdc, lpchText, cchText, lprc, format, lpdtp);\n    }\n    else\n    {\n        return (BaseSettings::GetOriginalFunction())(hdc, lpchText, cchText, lprc, format, lpdtp);\n    }\n}\n\nauto User32DrawTextManager::ExW::GetFunction() noexcept\n    -> Function\n{\n    return &CustomDrawTextExW;\n}\n"
  },
  {
    "path": "TrafficMonitor/DrawTextManager.h",
    "content": "﻿#pragma once\n#include <Windows.h>\n#include <type_traits>\n#include <functional>\n\nclass EnableWriteMemoryGuard\n{\nprivate:\n    void* const m_p_memory;\n    const std::size_t m_memory_size;\n    DWORD m_last_flag;\n    bool m_state;\n\npublic:\n    template <class T>\n    EnableWriteMemoryGuard(T* p_memory, std::size_t memory_size = sizeof(T))\n        : m_p_memory{p_memory}, m_memory_size{memory_size}\n    {\n        m_state = ::VirtualProtect(m_p_memory, m_memory_size, PAGE_EXECUTE_READWRITE, &m_last_flag);\n    }\n    ~EnableWriteMemoryGuard();\n    bool GetState();\n};\n\ntemplate <class FunctionPointer>\nstruct to_std_function;\ntemplate <class R, class... Parameters>\nstruct to_std_function<R (WINAPI *)(Parameters...)>\n{\n    using type = std::function<R(Parameters...)>;\n};\ntemplate <class FunctionPointer>\nusing to_std_function_t = typename to_std_function<FunctionPointer>::type;\n\n/**\n * @brief 用于管理hook后的User32.dll中的DrawText系列函数的行为，目前只有D2D渲染在使用\n *\n */\nclass User32DrawTextManager\n{\nprivate:\n    enum class DrawTextType\n    {\n        DrawTextA,\n        DrawTextW,\n        DrawTextExA,\n        DrawTextExW\n    };\n\n    /**\n     * @brief 各个类的设置数据合集，为了方便内部的非成员函数访问，内部都是静态成员\n     *\n     * @tparam Owner 拥有设置数据的类类型，防止多个类共享一套数据\n     * @tparam Function 要储存的函数指针类型\n     */\n    template <class Owner, class Function, class = std::enable_if_t<std::is_pointer<Function>{}>>\n    struct CommonSettings\n    {\n    private:\n        static bool m_enabled;\n\n    protected:\n        using ReplacedFunction = to_std_function_t<Function>;\n        static ReplacedFunction m_replaced_function;\n\n    public:\n        static void** m_p_iat_old_function_pointer;\n        static Function m_old_function_pointer;\n\n        struct State\n        {\n            bool m_is_enabled;\n            ReplacedFunction m_replaced_function;\n        };\n\n        static void SetEnable(bool is_enabled) noexcept\n        {\n            m_enabled = is_enabled;\n        }\n        static bool GetEnable() noexcept\n        {\n            return m_enabled;\n        }\n        static void SetReplacedFunction(ReplacedFunction replaced_function) noexcept\n        {\n            m_replaced_function = replaced_function;\n        }\n        static auto GetReplacedFunction() noexcept\n            -> ReplacedFunction\n        {\n            return m_replaced_function;\n        }\n        static void SetState(const State& state) noexcept\n        {\n            m_enabled = state.m_is_enabled;\n            if (state.m_is_enabled)\n            {\n                m_replaced_function = state.m_replaced_function;\n            }\n            else\n            {\n                m_replaced_function = nullptr;\n            }\n        }\n        static auto GetOriginalFunction() noexcept\n            -> Function\n        {\n            return m_old_function_pointer;\n        }\n    };\n\n    template <class T>\n    static inline void FunctionReplacer(void** p_found_function_pointer, void* p_args) noexcept\n    {\n        //保存原始的函数指针\n        decltype(T::BaseSettings::m_p_iat_old_function_pointer) p_iat_function = &*p_found_function_pointer;\n        T::BaseSettings::m_p_iat_old_function_pointer = p_iat_function;\n        //保存原始函数指针的地址\n        decltype(T::BaseSettings::m_old_function_pointer) iat_function =\n            reinterpret_cast<typename T::Function>(*p_found_function_pointer);\n        T::BaseSettings::m_old_function_pointer = iat_function;\n        //替换IAT中的函数\n        EnableWriteMemoryGuard enable_write{p_found_function_pointer};\n        auto p_custom_function = T::GetFunction();\n        //规避msvc扩展\n        ::memcpy(p_found_function_pointer, &p_custom_function, sizeof(p_custom_function));\n    }\n\npublic:\n    constexpr static int CUSTOM_SUCCESS = 0x7777;\n\n    class A : public CommonSettings<A, decltype(&::DrawTextA)>\n    {\n    private:\n        static int WINAPI\n        CustomDrawTextA(HDC hdc, LPCSTR lpchText, int cchText, LPRECT lprc, UINT format);\n\n    public:\n        using BaseSettings = CommonSettings<A, decltype(&::DrawTextA)>;\n        using Function = decltype(&CustomDrawTextA);\n        using ReplacedFunction = typename BaseSettings::ReplacedFunction;\n\n        static auto GetFunction() noexcept\n            -> Function;\n        static auto GetReplaceOperation()\n        {\n            return [](void** p_found_function_pointer, void* p_args) noexcept\n            {\n                FunctionReplacer<A>(p_found_function_pointer, p_args);\n            };\n        }\n    };\n\n    class W : public CommonSettings<W, decltype(&::DrawTextW)>\n    {\n    private:\n        static int WINAPI\n        CustomDrawTextW(HDC hdc, LPCWSTR lpchText, int cchText, LPRECT lprc, UINT format);\n\n    public:\n        using BaseSettings = CommonSettings<W, decltype(&::DrawTextW)>;\n        using Function = decltype(&CustomDrawTextW);\n        using ReplacedFunction = typename BaseSettings::ReplacedFunction;\n\n        static auto GetFunction() noexcept\n            -> Function;\n        static auto GetReplaceOperation()\n        {\n            return [](void** p_found_function_pointer, void* p_args) noexcept\n            {\n                FunctionReplacer<W>(p_found_function_pointer, p_args);\n            };\n        }\n    };\n\n    class ExA : public CommonSettings<ExA, decltype(&::DrawTextExA)>\n    {\n    private:\n        static int WINAPI\n        CustomDrawTextExA(HDC hdc, LPSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp);\n\n    public:\n        using BaseSettings = CommonSettings<ExA, decltype(&::DrawTextExA)>;\n        using Function = decltype(&CustomDrawTextExA);\n        using ReplacedFunction = typename BaseSettings::ReplacedFunction;\n\n        static auto GetFunction() noexcept\n            -> Function;\n        static auto GetReplaceOperation()\n        {\n            return [](void** p_found_function_pointer, void* p_args) noexcept\n            {\n                FunctionReplacer<ExA>(p_found_function_pointer, p_args);\n            };\n        }\n    };\n\n    class ExW : public CommonSettings<ExW, decltype(&::DrawTextExW)>\n    {\n    private:\n        static int WINAPI\n        CustomDrawTextExW(HDC hdc, LPWSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp);\n\n    public:\n        using BaseSettings = CommonSettings<ExW, decltype(&::DrawTextExW)>;\n        using Function = decltype(&CustomDrawTextExW);\n        using ReplacedFunction = typename BaseSettings::ReplacedFunction;\n\n        static auto GetFunction() noexcept\n            -> Function;\n        static auto GetReplaceOperation()\n        {\n            return [](void** p_found_function_pointer, void* p_args) noexcept\n            {\n                FunctionReplacer<ExW>(p_found_function_pointer, p_args);\n            };\n        }\n    };\n\n    User32DrawTextManager() = delete;\n    ~User32DrawTextManager() = delete;\n};\n\ntemplate <class Owner, class Function, class Checker>\nbool ::User32DrawTextManager::CommonSettings<Owner, Function, Checker>::m_enabled = false;\ntemplate <class Owner, class Function, class Checker>\nFunction(::User32DrawTextManager::CommonSettings<Owner, Function, Checker>::m_old_function_pointer) = nullptr;\ntemplate <class Owner, class Function, class Checker>\nvoid**(::User32DrawTextManager::CommonSettings<Owner, Function, Checker>::m_p_iat_old_function_pointer) = nullptr;\ntemplate <class Owner, class Function, class Checker>\nto_std_function_t<Function>(::User32DrawTextManager::CommonSettings<Owner, Function, Checker>::m_replaced_function) = {};\n"
  },
  {
    "path": "TrafficMonitor/Dxgi1Support2.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"Dxgi1Support2.h\"\n#include \"Common.h\"\n#include \"DllFunctions.h\"\n\nvoid CDxgiSwapChain1::Recreate(Microsoft::WRL::ComPtr<IUnknown> p_device, const DXGI_SWAP_CHAIN_DESC1& ref_desc1, IDXGIOutput* p_output)\n{\n    CallFunctionForEachResource<TRAFFICMONITOR_DV_V_ARGS(&Resource::OnSwapChainResizeBegin)>(m_resource_tracker);\n\n    ThrowIfFailed<CDxgiException>(\n        CDxgi1Support2::GetFactory()->CreateSwapChainForComposition(\n            p_device.Get(),\n            &ref_desc1,\n            p_output,\n            &m_p_swap_chain1),\n        TRAFFICMONITOR_ERROR_STR(\"Create swap chain for composition failed.\"));\n\n    CallFunctionForEachResource<TRAFFICMONITOR_DV_V_ARGS(&Resource::OnSwapChainResizeEnd)>(m_resource_tracker, m_p_swap_chain1);\n}\n\nauto CDxgiSwapChain1::GetStorage()\n    -> std::shared_ptr<Storage>\n{\n    return m_resource_tracker.GetSharedResourceTrackerStorage();\n}\n\nvoid CDxgiSwapChain1::Resize(std::uint32_t width, std::uint32_t height)\n{\n    CallFunctionForEachResource<TRAFFICMONITOR_DV_V_ARGS(&Resource::OnSwapChainResizeBegin)>(m_resource_tracker);\n\n    ThrowIfFailed<CDxgiException>(\n        m_p_swap_chain1->ResizeBuffers(\n            0,\n            width,\n            height,\n            DXGI_FORMAT_R8G8B8A8_UNORM,\n            0),\n        TRAFFICMONITOR_ERROR_STR(\"Resize swap chain failed.\"));\n\n    CallFunctionForEachResource<TRAFFICMONITOR_DV_V_ARGS(&Resource::OnSwapChainResizeEnd)>(m_resource_tracker, m_p_swap_chain1);\n}\n\nbool CDxgi1Support2::CheckSupport()\n{\n    const static auto result =\n        FunctionChecker::CheckFunctionExist(_T(\"dxgi.dll\"), \"CreateDXGIFactory2\");\n    return result;\n}\n\nIDXGIFactory2* CDxgi1Support2::GetFactory()\n{\n    static auto result = MakeStaticVariableWrapper<IDXGIFactory2*>(\n        [](auto pp_factory)\n        {\n            *pp_factory = nullptr;\n            auto flags = 0;\n#ifdef DEBUG\n            flags |= DXGI_CREATE_FACTORY_DEBUG;\n#endif\n            ThrowIfFailed<CDxgiException>(\n                CDllFunctions::CreateDXGIFactory2(\n                    flags,\n                    IID_PPV_ARGS(pp_factory)),\n                TRAFFICMONITOR_ERROR_STR(\"Create dxgi factory2 failed.\"));\n        },\n        [](auto pp_factory)\n        { RELEASE_COM(*pp_factory); });\n\n    return result.Get();\n}\n"
  },
  {
    "path": "TrafficMonitor/Dxgi1Support2.h",
    "content": "﻿#pragma once\n#include <dxgi1_3.h>\n#include \"HResultException.h\"\n#include \"RenderAPISupport.h\"\n\n#pragma comment(lib, \"DXGI.lib\")\n\nclass CDxgiException final : public CHResultException\n{\n    using CHResultException::CHResultException;\n};\n\ntemplate <class SwapChain>\nclass CDxgiSwapChainResource : public CDeviceResourceBase<SwapChain>\n{\npublic:\n    using Base = CDeviceResourceBase<SwapChain>;\n    using Base::Base;\n    using typename Base::DeviceType;\n\n    /**\n     * @brief 在准备Resize交换链时，此函数将被调用，用于释放所有和交换链相关的资源。\\n\n     注意：此函数可能被多次调用，且调用次数不一定与OnSwapChainResizeEnd的次数相匹配，\n     因此必须保证资源可以被反复执行释放操作\n     *\n     */\n    virtual void OnSwapChainResizeBegin() noexcept = 0;\n    /**\n     * @brief 在交换链完成Resize后，此函数将被调用，用于重建所有和交换链相关的资源\n     *\n     */\n    virtual void OnSwapChainResizeEnd(DeviceType p_resized_swap_chain) noexcept = 0;\n};\n\n/**\n * @brief 此类对应的资源为CDxgiSwapChainResource<CDxgiSwapChain1>，而非CDeviceResource<CDxgiSwapChain1>\n *\n */\nclass CDxgiSwapChain1\n{\npublic:\n    using Resource = CDxgiSwapChainResource<CDxgiSwapChain1>;\n    using Type = Microsoft::WRL::ComPtr<IDXGISwapChain1>;\n    using Storage = storage_t<CResourceTracker<Resource>>;\n\nprivate:\n    Type m_p_swap_chain1{};\n    CResourceTracker<Resource> m_resource_tracker{std::make_shared<Storage>()};\n\npublic:\n    void Recreate(Microsoft::WRL::ComPtr<IUnknown> p_device, const DXGI_SWAP_CHAIN_DESC1& ref_desc1, IDXGIOutput* p_output = nullptr);\n    auto GetStorage()\n        -> std::shared_ptr<Storage>;\n    void Resize(std::uint32_t width, std::uint32_t height);\n};\n\nclass CDxgi1Support2\n{\npublic:\n    static bool CheckSupport();\n    static IDXGIFactory2* GetFactory();\n};\n"
  },
  {
    "path": "TrafficMonitor/FileDialogEx.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"FileDialogEx.h\"\n#include <sstream>\n\nCFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCWSTR lpszDefExt, LPCWSTR lpszFilter)\n    : pFileDialog(nullptr), m_bOpenFileDialog(bOpenFileDialog)\n{\n    // 创建 IFileDialog 实例\n    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileDialog));\n\n    if (pFileDialog)\n    {\n        // 设置对话框选项\n        DWORD dwOptions;\n        pFileDialog->GetOptions(&dwOptions);\n        pFileDialog->SetOptions(dwOptions | FOS_FORCEFILESYSTEM);  // 仅文件系统项\n\n        if (bOpenFileDialog)\n        {\n            pFileDialog->SetOptions(dwOptions | FOS_FILEMUSTEXIST); // 打开文件时文件必须存在\n        }\n\n        // 设置默认扩展名\n        if (lpszDefExt)\n        {\n            pFileDialog->SetDefaultExtension(lpszDefExt);\n        }\n\n        // 解析并设置过滤器\n        if (lpszFilter)\n        {\n            ParseFilter(lpszFilter);\n            for (size_t i = 0; i < m_filterDescriptions.size() && i < m_filterSpecsStrings.size(); i++)\n            {\n                COMDLG_FILTERSPEC filterSpec = { m_filterDescriptions[i].c_str(), m_filterSpecsStrings[i].c_str()};\n                m_filterSpecs.push_back(filterSpec);\n            }\n            pFileDialog->SetFileTypes(m_filterSpecs.size(), m_filterSpecs.data());\n        }\n    }\n}\n\nCFileDialogEx::~CFileDialogEx()\n{\n    if (pFileDialog)\n    {\n        pFileDialog->Release();\n    }\n}\n\nint CFileDialogEx::DoModal(HWND hWndOwner)\n{\n    if (!pFileDialog) return -1;\n\n    // 显示对话框\n    HRESULT hr = pFileDialog->Show(hWndOwner);\n    if (FAILED(hr))\n        return -1;\n\n    // 获取选定的文件路径\n    IShellItem* pItem = nullptr;\n    hr = pFileDialog->GetResult(&pItem);\n    if (SUCCEEDED(hr))\n    {\n        PWSTR pszFilePath = nullptr;\n        hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);\n        if (SUCCEEDED(hr))\n        {\n            m_filePath = pszFilePath;\n            CoTaskMemFree(pszFilePath);\n        }\n        pItem->Release();\n    }\n\n    return (SUCCEEDED(hr)) ? 1 : 0;\n}\n\nstd::wstring CFileDialogEx::GetPathName() const\n{\n    return m_filePath;\n}\n\nstd::wstring CFileDialogEx::GetFileName() const\n{\n    // 获取文件名\n    size_t pos = m_filePath.find_last_of(L\"\\\\\");\n    if (pos != std::wstring::npos) {\n        return m_filePath.substr(pos + 1);\n    }\n    return m_filePath;\n}\n\nvoid CFileDialogEx::ParseFilter(LPCWSTR lpszFilter)\n{\n    m_filterSpecs.clear();\n    m_filterDescriptions.clear();\n    m_filterSpecsStrings.clear();\n\n    // 使用 | 分割过滤器字符串\n    std::wstringstream filterStream(lpszFilter);\n    std::wstring description, spec;\n\n    while (std::getline(filterStream, description, L'|'))\n    {\n        if (std::getline(filterStream, spec, L'|'))\n        {\n            // 将描述和模式存储在 m_filterDescriptions 和 m_filterSpecsStrings 中\n            m_filterDescriptions.push_back(description);\n            m_filterSpecsStrings.push_back(spec);\n        }\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/FileDialogEx.h",
    "content": "﻿#pragma once\n\nclass CFileDialogEx {\npublic:\n    CFileDialogEx(BOOL bOpenFileDialog, LPCWSTR lpszDefExt = NULL, LPCWSTR lpszFilter = NULL);\n    ~CFileDialogEx();\n\n    // 显示对话框\n    int DoModal(HWND hWndOwner = NULL);\n\n    // 获取选定的文件路径和文件名\n    std::wstring GetPathName() const;\n    std::wstring GetFileName() const;\n\nprivate:\n    void ParseFilter(LPCWSTR lpszFilter);\n\nprivate:\n    IFileDialog* pFileDialog;\n    std::wstring m_filePath;\n    BOOL m_bOpenFileDialog;\n    std::vector<COMDLG_FILTERSPEC> m_filterSpecs;  // 存储过滤器描述和模式\n    std::vector<std::wstring> m_filterDescriptions;  // 存储过滤器描述\n    std::vector<std::wstring> m_filterSpecsStrings;  // 存储过滤器模式\n};\n"
  },
  {
    "path": "TrafficMonitor/FilePathHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"FilePathHelper.h\"\n#include \"Common.h\"\n\n\nCFilePathHelper::CFilePathHelper(const wstring & file_path)\n\t: m_file_path{ file_path }\n{\n}\n\nCFilePathHelper::~CFilePathHelper()\n{\n}\n\nwstring CFilePathHelper::GetFileExtension(bool upper, bool width_dot) const\n{\n\tsize_t index;\n\tindex = m_file_path.rfind('.');\n\tif (index == wstring::npos || index == m_file_path.size() - 1)\n\t\treturn wstring();\n\twstring file_extension{ m_file_path.substr(width_dot ? index : index + 1) };\n\tCCommon::StringTransform(file_extension, upper);\n\treturn file_extension;\n}\n\nwstring CFilePathHelper::GetFileName() const\n{\n\tsize_t index;\n\tindex = m_file_path.rfind('\\\\');\n\tif (index == wstring::npos)\n\t\tindex = m_file_path.rfind('/');\n\treturn m_file_path.substr(index + 1);\n}\n\nwstring CFilePathHelper::GetFileNameWithoutExtension() const\n{\n\tsize_t index, index1;\n\tindex = m_file_path.rfind('.');\n\tindex1 = m_file_path.rfind('\\\\');\n\tif (index1 == wstring::npos)\n\t\tindex1 = m_file_path.rfind('/');\n\treturn m_file_path.substr(index1 + 1, (index - index1 - 1));\n}\n\nwstring CFilePathHelper::GetFolderName() const\n{\n\tint index, index1;\n\tindex = m_file_path.find_last_of(L\"\\\\/\");\n\tif (index == wstring::npos || index == 0)\n\t\treturn wstring();\n\n\tindex1 = m_file_path.find_last_of(L\"\\\\/\", index - 1);\n\tif (index1 == wstring::npos || index1 == 0)\n\t\treturn wstring();\n\n\treturn m_file_path.substr(index1 + 1, (index - index1 - 1));\n}\n\nwstring CFilePathHelper::GetDir() const\n{\n\tif (!m_file_path.empty() && (m_file_path.back() == L'\\\\' || m_file_path.back() == L'/'))\n\t\treturn m_file_path;\n\tsize_t index;\n\tindex = m_file_path.rfind('\\\\');\n\tif (index == wstring::npos)\n\t\tindex = m_file_path.rfind('/');\n\treturn m_file_path.substr(0, index + 1);\n}\n\nwstring CFilePathHelper::GetParentDir() const\n{\n\twstring dir{ GetDir() };\n\tsize_t index;\n\tif (!dir.empty() && (dir.back() == L'\\\\' || dir.back() == L'/'))\n\t\tdir.pop_back();\n\tindex = dir.rfind('\\\\');\n\tif (index == wstring::npos)\n\t\tindex = dir.rfind('/');\n\treturn m_file_path.substr(0, index + 1);\n}\n\nconst wstring& CFilePathHelper::ReplaceFileExtension(const wchar_t * new_extension)\n{\n\tsize_t index, index1;\n\tindex = m_file_path.rfind('.');\n\tindex1 = m_file_path.rfind('\\\\');\n\tif (index == wstring::npos || (index1 != wstring::npos && index < index1))\t\t//如果没有找到“.”，或者“.”在反斜杠的左边，则在末尾添加一个“.”\n\t{\n\t\tm_file_path.push_back(L'.');\n\t}\n\telse if (index != m_file_path.size() - 1)\t//如果“.”不在最后的位置，则删除“.”后面的字符串\n\t{\n\t\tm_file_path.erase(index + 1);\n\t}\n    if (new_extension == nullptr || *new_extension == L'\\0')\n    {\n        if (!m_file_path.empty() && m_file_path.back() == L'.')\n            m_file_path.pop_back();\n    }\n    else\n    {\n        m_file_path.append(new_extension);\t\t//在末尾添加扩展名\n    }\n\treturn m_file_path;\n}\n\nwstring CFilePathHelper::GetFilePathWithoutExtension() const\n{\n    size_t index;\n    index = m_file_path.rfind('.');\n    return m_file_path.substr(0, index);\n}\n"
  },
  {
    "path": "TrafficMonitor/FilePathHelper.h",
    "content": "﻿#pragma once\nclass CFilePathHelper\n{\npublic:\n\tCFilePathHelper(const wstring& file_path);\n\tCFilePathHelper(){}\n\t~CFilePathHelper();\n\n\tvoid SetFilePath(const wstring& file_path) { m_file_path = file_path; }\n\n\twstring GetFileExtension(bool upper = false, bool width_dot = false) const;\t\t//获取文件的扩展名(upper:是否大写; width_dot:是否包含“.”)\n\twstring GetFileName() const;\t\t\t\t\t\t\t//获取文件名\n\twstring GetFileNameWithoutExtension() const;\t\t\t//获取文件名（不含扩展名）\n\twstring GetFolderName() const;\t\t\t\t\t\t\t//获取文件夹名\n\twstring GetDir() const;\t\t\t\t\t\t\t\t\t//获取目录\n\twstring GetParentDir() const;\t\t\t\t\t\t\t//获取上级目录\n\twstring GetFilePath() const { return m_file_path; }\t\t//获取完整路径\n\tconst wstring& ReplaceFileExtension(const wchar_t* new_extension);\t\t//替换文件的扩展名，返回文件完整路径\n    wstring GetFilePathWithoutExtension() const;            //获取文件路径（不含扩展名）\nprotected:\n\twstring m_file_path;\n};\n\n"
  },
  {
    "path": "TrafficMonitor/GeneralSettingsDlg.cpp",
    "content": "﻿// GeneralSettingsDlg.cpp : implementation file\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"TrafficMonitorDlg.h\"\n#include \"GeneralSettingsDlg.h\"\n#include \"PluginManagerDlg.h\"\n#include \"SelectConnectionsDlg.h\"\n\n\n// CGeneralSettingsDlg dialog\n\nstatic const int MONITOR_SPAN_STEP = 100;\n\nIMPLEMENT_DYNAMIC(CGeneralSettingsDlg, CTabDlg)\n\nCGeneralSettingsDlg::CGeneralSettingsDlg(CWnd* pParent /*=NULL*/)\n    : CTabDlg(IDD_GENERAL_SETTINGS_DIALOG, pParent)\n{\n\n}\n\nCGeneralSettingsDlg::~CGeneralSettingsDlg()\n{\n}\n\nvoid CGeneralSettingsDlg::CheckTaskbarDisplayItem()\n{\n    //如果选项设置中关闭了某个硬件监控，则不显示对应的温度监控相关项目\n    if (!theApp.m_general_data.IsHardwareEnable(HI_CPU))\n    {\n        theApp.m_taskbar_data.display_item.Remove(TDI_CPU_TEMP);\n    }\n    if (!theApp.m_general_data.IsHardwareEnable(HI_GPU))\n    {\n        theApp.m_taskbar_data.display_item.Remove(TDI_GPU_TEMP);\n    }\n    if (!theApp.m_general_data.IsHardwareEnable(HI_HDD))\n    {\n        theApp.m_taskbar_data.display_item.Remove(TDI_HDD_TEMP);\n    }\n    if (!theApp.m_general_data.IsHardwareEnable(HI_MBD))\n        theApp.m_taskbar_data.display_item.Remove(TDI_MAIN_BOARD_TEMP);\n}\n\nvoid CGeneralSettingsDlg::SetControlMouseWheelEnable(bool enable)\n{\n    m_traffic_tip_combo.SetMouseWheelEnable(enable);\n    m_language_combo.SetMouseWheelEnable(enable);\n    m_traffic_tip_edit.SetMouseWheelEnable(enable);\n    m_memory_tip_edit.SetMouseWheelEnable(enable);\n    m_monitor_span_edit.SetMouseWheelEnable(enable);\n    m_cpu_temp_tip_edit.SetMouseWheelEnable(enable);\n    m_gpu_temp_tip_edit.SetMouseWheelEnable(enable);\n    m_hdd_temp_tip_edit.SetMouseWheelEnable(enable);\n    m_mbd_temp_tip_edit.SetMouseWheelEnable(enable);\n    m_hard_disk_combo.SetMouseWheelEnable(enable);\n    m_select_cpu_combo.SetMouseWheelEnable(enable);\n}\n\nvoid CGeneralSettingsDlg::OnSettingsApplied()\n{\n    //当设置被应用时，重置xxxx_ori的值\n    m_monitor_time_span_ori = m_data.monitor_time_span;\n    m_update_source_ori = m_data.update_source;\n}\n\nbool CGeneralSettingsDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_CHECK_NOW_BUTTON, CtrlTextInfo::W16 }\n        });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_UPDATE_SORUCE_STATIC },\n        { CtrlTextInfo::L3, IDC_GITHUB_RADIO },\n        { CtrlTextInfo::L2, IDC_GITEE_RADIO }\n        });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_RESET_AUTO_RUN_BUTTON, CtrlTextInfo::W16 }\n        });\n\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_LANGUAGE_STATIC },\n        { CtrlTextInfo::L3, IDC_LANGUAGE_COMBO }\n        });\n\n    //调整“今日使用流量已达到”这一行控件的水平位置\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_TODAY_TRAFFIC_TIP_CHECK, CtrlTextInfo::W24 },\n        { CtrlTextInfo::L3, IDC_TODAY_TRAFFIC_TIP_EDIT },\n        { CtrlTextInfo::L2, IDC_TODAY_TRAFFIC_TIP_COMBO },\n        { CtrlTextInfo::L1, IDC_TODAY_TRAFFIC_BACK_STATIC}\n        });\n    //调整“内存使用率已达到”、“温度已达到”这几行控件的水平位置\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_MEMORY_USAGE_TIP_CHECK, CtrlTextInfo::W24 },\n        { CtrlTextInfo::L3, IDC_MEMORY_USAGE_TIP_EDIT },\n        { CtrlTextInfo::L2, IDC_MEMORY_USAGE_BACK_STATIC },\n        { CtrlTextInfo::L4, IDC_CPU_TEMP_TIP_CHECK, CtrlTextInfo::W24 },\n        { CtrlTextInfo::L3, IDC_CPU_TEMP_TIP_EDIT },\n        { CtrlTextInfo::L2, IDC_CPU_TEMP_STATIC },\n        { CtrlTextInfo::L4, IDC_GPU_TEMP_TIP_CHECK, CtrlTextInfo::W24 },\n        { CtrlTextInfo::L3, IDC_GPU_TEMP_TIP_EDIT },\n        { CtrlTextInfo::L2, IDC_GPU_TEMP_STATIC },\n        { CtrlTextInfo::L4, IDC_HDD_TEMP_TIP_CHECK, CtrlTextInfo::W24 },\n        { CtrlTextInfo::L3, IDC_HDD_TIP_EDIT },\n        { CtrlTextInfo::L2, IDC_HDD_STATIC },\n        { CtrlTextInfo::L4, IDC_MBD_TEMP_TIP_CHECK, CtrlTextInfo::W24 },\n        { CtrlTextInfo::L3, IDC_MBD_TEMP_TIP_EDIT },\n        { CtrlTextInfo::L2, IDC_MBD_TEMP_STATIC },\n        });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_SELECT_HDD_STATIC },\n        { CtrlTextInfo::C0, IDC_SELECT_HARD_DISK_COMBO },\n        { CtrlTextInfo::L1, IDC_SELECT_CPU_STATIC },\n        { CtrlTextInfo::C0, IDC_SELECT_CPU_COMBO },\n    });\n\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_SELECT_CONNECTIONS_BUTTON, CtrlTextInfo::W32 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_MONITOR_INTERVAL_STATIC },\n        { CtrlTextInfo::L3, IDC_MONITOR_SPAN_EDIT },\n        { CtrlTextInfo::L2, IDC_MILLISECONDS_STATIC },\n        { CtrlTextInfo::L1, IDC_RESTORE_DEFAULT_TIME_SPAN_BUTTON, CtrlTextInfo::W16 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_PLUGIN_MANAGE_BUTTON, CtrlTextInfo::W32 }\n    });\n\n    return true;\n}\n\nbool CGeneralSettingsDlg::ShowHardwareMonitorWarning()\n{\n    //如果已经有硬件监控项目被勾选了，则不再弹出提示\n    if (m_data.hardware_monitor_item != 0)\n        return true;\n\n    if (SHMessageBoxCheck(m_hWnd, CCommon::LoadText(IDS_HARDWARE_MONITOR_WARNING), APP_NAME, MB_OKCANCEL | MB_ICONWARNING, IDOK, _T(\"{B8A281A7-76DF-4F0F-BF6A-1A394EF8BAD5}\")) == IDOK)\n        return true;\n\n    return false;\n}\n\nvoid CGeneralSettingsDlg::AddOrUpdateAutoRunTooltip(bool add)\n{\n    CString str_tool_tip;\n#ifdef WITHOUT_TEMPERATURE\n    str_tool_tip = CCommon::LoadText(IDS_AUTO_RUN_METHOD_REGESTRY);\n#else\n    str_tool_tip = CCommon::LoadText(IDS_AUTO_RUN_METHOD_TASK_SCHEDULE);\n#endif\n    if (!m_auto_run_path.empty())\n    {\n        str_tool_tip += _T(\"\\r\\n\");\n        str_tool_tip += CCommon::LoadText(IDS_PATH, _T(\": \"));\n        str_tool_tip += m_auto_run_path.c_str();\n    }\n    if (add)\n        m_toolTip.AddTool(GetDlgItem(IDC_AUTO_RUN_CHECK), str_tool_tip);\n    else\n        m_toolTip.UpdateTipText(str_tool_tip, GetDlgItem(IDC_AUTO_RUN_CHECK));\n\n}\n\nbool CGeneralSettingsDlg::IsMonitorTimeSpanModified() const\n{\n    return m_data.monitor_time_span != m_monitor_time_span_ori;\n}\n\nvoid CGeneralSettingsDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CTabDlg::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_TODAY_TRAFFIC_TIP_EDIT, m_traffic_tip_edit);\n    DDX_Control(pDX, IDC_TODAY_TRAFFIC_TIP_COMBO, m_traffic_tip_combo);\n    DDX_Control(pDX, IDC_MEMORY_USAGE_TIP_EDIT, m_memory_tip_edit);\n    DDX_Control(pDX, IDC_LANGUAGE_COMBO, m_language_combo);\n    DDX_Control(pDX, IDC_MONITOR_SPAN_EDIT, m_monitor_span_edit);\n    DDX_Control(pDX, IDC_CPU_TEMP_TIP_EDIT, m_cpu_temp_tip_edit);\n    DDX_Control(pDX, IDC_GPU_TEMP_TIP_EDIT, m_gpu_temp_tip_edit);\n    DDX_Control(pDX, IDC_HDD_TIP_EDIT, m_hdd_temp_tip_edit);\n    DDX_Control(pDX, IDC_MBD_TEMP_TIP_EDIT, m_mbd_temp_tip_edit);\n    DDX_Control(pDX, IDC_SELECT_HARD_DISK_COMBO, m_hard_disk_combo);\n    DDX_Control(pDX, IDC_SELECT_CPU_COMBO, m_select_cpu_combo);\n    DDX_Control(pDX, IDC_PLUGIN_MANAGE_BUTTON, m_plugin_manager_btn);\n    DDX_Control(pDX, IDC_SELECT_CONNECTIONS_BUTTON, m_select_connection_btn);\n}\n\nvoid CGeneralSettingsDlg::SetControlEnable()\n{\n    m_traffic_tip_edit.EnableWindow(m_data.traffic_tip_enable);\n    m_traffic_tip_combo.EnableWindow(m_data.traffic_tip_enable);\n    m_memory_tip_edit.EnableWindow(m_data.memory_usage_tip.enable);\n    m_cpu_temp_tip_edit.EnableWindow(m_data.cpu_temp_tip.enable);\n    m_gpu_temp_tip_edit.EnableWindow(m_data.gpu_temp_tip.enable);\n    m_hdd_temp_tip_edit.EnableWindow(m_data.hdd_temp_tip.enable);\n    m_mbd_temp_tip_edit.EnableWindow(m_data.mainboard_temp_tip.enable);\n\n    //m_hard_disk_combo.EnableWindow(m_data.IsHardwareEnable(HI_HDD));\n    m_select_cpu_combo.EnableWindow(m_data.IsHardwareEnable(HI_CPU));\n\n    EnableDlgCtrl(IDC_SELECT_CONNECTIONS_BUTTON, !m_data.show_all_interface);\n}\n\n\nBEGIN_MESSAGE_MAP(CGeneralSettingsDlg, CTabDlg)\n    ON_BN_CLICKED(IDC_CHECK_NOW_BUTTON, &CGeneralSettingsDlg::OnBnClickedCheckNowButton)\n    ON_BN_CLICKED(IDC_CHECK_UPDATE_CHECK, &CGeneralSettingsDlg::OnBnClickedCheckUpdateCheck)\n    ON_BN_CLICKED(IDC_AUTO_RUN_CHECK, &CGeneralSettingsDlg::OnBnClickedAutoRunCheck)\n    ON_BN_CLICKED(IDC_TODAY_TRAFFIC_TIP_CHECK, &CGeneralSettingsDlg::OnBnClickedTodayTrafficTipCheck)\n    ON_BN_CLICKED(IDC_MEMORY_USAGE_TIP_CHECK, &CGeneralSettingsDlg::OnBnClickedMemoryUsageTipCheck)\n    ON_BN_CLICKED(IDC_OPEN_CONFIG_PATH_BUTTON, &CGeneralSettingsDlg::OnBnClickedOpenConfigPathButton)\n    ON_BN_CLICKED(IDC_SHOW_ALL_CONNECTION_CHECK, &CGeneralSettingsDlg::OnBnClickedShowAllConnectionCheck)\n    ON_BN_CLICKED(IDC_USE_CPU_TIME_RADIO, &CGeneralSettingsDlg::OnBnClickedUseCpuTimeRadio)\n    ON_BN_CLICKED(IDC_USE_PDH_RADIO, &CGeneralSettingsDlg::OnBnClickedUsePdhRadio)\n    ON_EN_KILLFOCUS(IDC_MONITOR_SPAN_EDIT, &CGeneralSettingsDlg::OnEnKillfocusMonitorSpanEdit)\n    ON_BN_CLICKED(IDC_CPU_TEMP_TIP_CHECK, &CGeneralSettingsDlg::OnBnClickedCpuTempTipCheck)\n    ON_BN_CLICKED(IDC_GPU_TEMP_TIP_CHECK, &CGeneralSettingsDlg::OnBnClickedGpuTempTipCheck)\n    ON_BN_CLICKED(IDC_HDD_TEMP_TIP_CHECK, &CGeneralSettingsDlg::OnBnClickedHddTempTipCheck)\n    ON_BN_CLICKED(IDC_MBD_TEMP_TIP_CHECK, &CGeneralSettingsDlg::OnBnClickedMbdTempTipCheck)\n    ON_BN_CLICKED(IDC_GITHUB_RADIO, &CGeneralSettingsDlg::OnBnClickedGithubRadio)\n    ON_BN_CLICKED(IDC_GITEE_RADIO, &CGeneralSettingsDlg::OnBnClickedGiteeRadio)\n    ON_BN_CLICKED(IDC_RESTORE_DEFAULT_TIME_SPAN_BUTTON, &CGeneralSettingsDlg::OnBnClickedRestoreDefaultTimeSpanButton)\n    ON_CBN_SELCHANGE(IDC_SELECT_HARD_DISK_COMBO, &CGeneralSettingsDlg::OnCbnSelchangeSelectHardDiskCombo)\n    ON_BN_CLICKED(IDC_CPU_CHECK, &CGeneralSettingsDlg::OnBnClickedCpuCheck)\n    ON_BN_CLICKED(IDC_GPU_CHECK, &CGeneralSettingsDlg::OnBnClickedGpuCheck)\n    ON_BN_CLICKED(IDC_HDD_CHECK, &CGeneralSettingsDlg::OnBnClickedHddCheck)\n    ON_BN_CLICKED(IDC_MBD_CHECK, &CGeneralSettingsDlg::OnBnClickedMbdCheck)\n    ON_CBN_SELCHANGE(IDC_SELECT_CPU_COMBO, &CGeneralSettingsDlg::OnCbnSelchangeSelectCpuCombo)\n    ON_BN_CLICKED(IDC_PLUGIN_MANAGE_BUTTON, &CGeneralSettingsDlg::OnBnClickedPluginManageButton)\n    ON_BN_CLICKED(IDC_SHOW_NOTIFY_ICON_CHECK, &CGeneralSettingsDlg::OnBnClickedShowNotifyIconCheck)\n    ON_BN_CLICKED(IDC_SELECT_CONNECTIONS_BUTTON, &CGeneralSettingsDlg::OnBnClickedSelectConnectionsButton)\n    ON_BN_CLICKED(IDC_RESET_AUTO_RUN_BUTTON, &CGeneralSettingsDlg::OnBnClickedResetAutoRunButton)\n    ON_BN_CLICKED(IDC_USE_HARDWARE_MONITOR_RADIO, &CGeneralSettingsDlg::OnBnClickedUseHardwareMonitorRadio)\n    ON_EN_CHANGE(IDC_MONITOR_SPAN_EDIT, &CGeneralSettingsDlg::OnEnChangeMonitorSpanEdit)\n    ON_MESSAGE(WM_SPIN_EDIT_POS_CHANGED, &CGeneralSettingsDlg::OnSpinEditPosChanged)\nEND_MESSAGE_MAP()\n\n\n// CGeneralSettingsDlg 消息处理程序\n\n\nBOOL CGeneralSettingsDlg::OnInitDialog()\n{\n    CTabDlg::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n\n    ((CButton*)GetDlgItem(IDC_CHECK_UPDATE_CHECK))->SetCheck(m_data.check_update_when_start);\n    if (theApp.IsForceShowNotifyIcon())\n    {\n        m_data.show_notify_icon = true;\n        EnableDlgCtrl(IDC_SHOW_NOTIFY_ICON_CHECK, FALSE);\n    }\n    CheckDlgButton(IDC_SHOW_NOTIFY_ICON_CHECK, m_data.show_notify_icon);\n\n    if (m_data.update_source == 0)\n        CheckDlgButton(IDC_GITHUB_RADIO, TRUE);\n    else\n        CheckDlgButton(IDC_GITEE_RADIO, TRUE);\n\n    //检查开始菜单的“启动”目录下有没有程序的快捷方式，如果有则设置开机自启动，然后删除快捷方式\n    wstring start_up_path = CCommon::GetStartUpPath();\n    bool shortcut_exist = CCommon::FileExist((start_up_path + L\"\\\\TrafficMonitor.lnk\").c_str());\n    if (shortcut_exist)\n    {\n        theApp.SetAutoRun(true);\n        m_data.auto_run = true;\n        DeleteFile((start_up_path + L\"\\\\TrafficMonitor.lnk\").c_str());\n    }\n    else\n    {\n        m_data.auto_run = theApp.GetAutoRun(&m_auto_run_path);\n    }\n\n    ((CButton*)GetDlgItem(IDC_SAVE_TO_APPDATA_RADIO))->SetCheck(!m_data.portable_mode);\n    ((CButton*)GetDlgItem(IDC_SAVE_TO_PROGRAM_DIR_RADIO))->SetCheck(m_data.portable_mode);\n    GetDlgItem(IDC_SAVE_TO_PROGRAM_DIR_RADIO)->EnableWindow(theApp.m_module_dir_writable);\n\n    ((CButton*)GetDlgItem(IDC_AUTO_RUN_CHECK))->SetCheck(m_data.auto_run);\n\n    ((CButton*)GetDlgItem(IDC_TODAY_TRAFFIC_TIP_CHECK))->SetCheck(m_data.traffic_tip_enable);\n    m_traffic_tip_edit.SetRange(1, 32767);\n    m_traffic_tip_edit.SetValue(m_data.traffic_tip_value);\n    m_traffic_tip_combo.AddString(_T(\"MB\"));\n    m_traffic_tip_combo.AddString(_T(\"GB\"));\n    m_traffic_tip_combo.SetCurSel(m_data.traffic_tip_unit);\n    CheckDlgButton(IDC_MEMORY_USAGE_TIP_CHECK, m_data.memory_usage_tip.enable);\n    m_memory_tip_edit.SetRange(1, 100);\n    m_memory_tip_edit.SetValue(m_data.memory_usage_tip.tip_value);\n\n    CheckDlgButton(IDC_CPU_TEMP_TIP_CHECK, m_data.cpu_temp_tip.enable);\n    m_cpu_temp_tip_edit.SetRange(1, 120);\n    m_cpu_temp_tip_edit.SetValue(m_data.cpu_temp_tip.tip_value);\n\n    CheckDlgButton(IDC_GPU_TEMP_TIP_CHECK, m_data.gpu_temp_tip.enable);\n    m_gpu_temp_tip_edit.SetRange(1, 120);\n    m_gpu_temp_tip_edit.SetValue(m_data.gpu_temp_tip.tip_value);\n\n    CheckDlgButton(IDC_HDD_TEMP_TIP_CHECK, m_data.hdd_temp_tip.enable);\n    m_hdd_temp_tip_edit.SetRange(1, 120);\n    m_hdd_temp_tip_edit.SetValue(m_data.hdd_temp_tip.tip_value);\n\n    CheckDlgButton(IDC_MBD_TEMP_TIP_CHECK, m_data.mainboard_temp_tip.enable);\n    m_mbd_temp_tip_edit.SetRange(1, 120);\n    m_mbd_temp_tip_edit.SetValue(m_data.mainboard_temp_tip.tip_value);\n\n    SetControlEnable();\n\n    m_language_combo.AddString(CCommon::LoadText(IDS_FOLLOWING_SYSTEM));\n    int current_language_index{ -1 };       //当前语言在所有语言列表中的序号\n    for (size_t i = 0; i < theApp.m_str_table.GetLanguageList().size(); i++)\n    {\n        const CStrTable::LanguageInfo& language_info = theApp.m_str_table.GetLanguageList()[i];\n        m_language_combo.AddString(language_info.display_name.c_str());\n        if (language_info.language_id == m_data.language)\n            current_language_index = static_cast<int>(i);\n    }\n    m_language_combo.SetCurSel(current_language_index + 1);     //由于ComboBox第一项是“跟随系统”，因此ComboBox的序号需要加1\n\n    ((CButton*)GetDlgItem(IDC_SHOW_ALL_CONNECTION_CHECK))->SetCheck(m_data.show_all_interface);\n\n    m_toolTip.Create(this);\n    m_toolTip.SetMaxTipWidth(theApp.DPI(300));\n    m_toolTip.AddTool(GetDlgItem(IDC_SHOW_ALL_CONNECTION_CHECK), CCommon::LoadText(IDS_SHOW_ALL_INFO_TIP));\n    m_toolTip.AddTool(GetDlgItem(IDC_SAVE_TO_APPDATA_RADIO), theApp.m_appdata_dir.c_str());\n    m_toolTip.AddTool(GetDlgItem(IDC_SAVE_TO_PROGRAM_DIR_RADIO), theApp.m_module_dir.c_str());\n    AddOrUpdateAutoRunTooltip(true);\n\n    if (m_data.cpu_usage_acquire_method == GeneralSettingData::CA_CPU_TIME)\n    {\n        CheckDlgButton(IDC_USE_CPU_TIME_RADIO, TRUE);\n    }\n    else if (m_data.cpu_usage_acquire_method == GeneralSettingData::CA_PDH)\n    {\n        CheckDlgButton(IDC_USE_PDH_RADIO, TRUE);\n    }\n    else if (m_data.cpu_usage_acquire_method == GeneralSettingData::CA_HARDWARE_MONITOR)\n    {\n        if (m_data.IsHardwareEnable(HI_CPU))\n            CheckDlgButton(IDC_USE_HARDWARE_MONITOR_RADIO, TRUE);\n        else\n            CheckDlgButton(IDC_USE_CPU_TIME_RADIO, TRUE);\n    }\n\n#ifndef WITHOUT_TEMPERATURE\n    EnableDlgCtrl(IDC_USE_HARDWARE_MONITOR_RADIO, m_data.IsHardwareEnable(HI_CPU));\n#else\n    EnableDlgCtrl(IDC_USE_HARDWARE_MONITOR_RADIO, false);\n#endif\n\n    m_monitor_span_edit.SetRange(MONITOR_TIME_SPAN_MIN, MONITOR_TIME_SPAN_MAX, MONITOR_SPAN_STEP);\n    m_monitor_span_edit.SetValue(m_data.monitor_time_span);\n\n    m_monitor_time_span_ori = m_data.monitor_time_span;\n    m_update_source_ori = m_data.update_source;\n\n    if (CTrafficMonitorDlg::Instance()->IsGetDiskUsageByPdh())\n    {\n        const auto& disk_names = CTrafficMonitorDlg::Instance()->GetPdhDiskUsageHelper().GetDiskNames();\n        for (const auto& hdd_name : disk_names)\n            m_hard_disk_combo.AddString(hdd_name);\n        int cur_index = m_hard_disk_combo.FindString(-1, m_data.hard_disk_name.c_str());\n        m_hard_disk_combo.SetCurSel(cur_index);\n    }\n#ifndef WITHOUT_TEMPERATURE\n    //初始化硬件监控Check box\n    CheckDlgButton(IDC_CPU_CHECK, m_data.IsHardwareEnable(HI_CPU));\n    CheckDlgButton(IDC_GPU_CHECK, m_data.IsHardwareEnable(HI_GPU));\n    CheckDlgButton(IDC_HDD_CHECK, m_data.IsHardwareEnable(HI_HDD));\n    CheckDlgButton(IDC_MBD_CHECK, m_data.IsHardwareEnable(HI_MBD));\n\n    if (theApp.m_pMonitor != nullptr)\n    {\n        CSingleLock sync(&theApp.m_minitor_lib_critical, TRUE);\n        //初始化选择硬盘下拉列表\n        if (!CTrafficMonitorDlg::Instance()->IsGetDiskUsageByPdh())\n        {\n            for (const auto& hdd_item : theApp.m_pMonitor->AllHDDTemperature())\n                m_hard_disk_combo.AddString(hdd_item.first.c_str());\n            int cur_index = m_hard_disk_combo.FindString(-1, m_data.hard_disk_name.c_str());\n            m_hard_disk_combo.SetCurSel(cur_index);\n        }\n        //初始化选择CPU下拉列表\n        m_select_cpu_combo.AddString(CCommon::LoadText(IDS_AVREAGE_TEMPERATURE));\n        for (const auto& cpu_item : theApp.m_pMonitor->AllCpuTemperature())\n            m_select_cpu_combo.AddString(cpu_item.first.c_str());\n        int cur_index = m_select_cpu_combo.FindString(-1, m_data.cpu_core_name.c_str());\n        if (cur_index < 0)\n            cur_index = 0;\n        m_select_cpu_combo.SetCurSel(cur_index);\n    }\n#endif\n\n    //不含温度监控的版本，禁用温度相关的控件\n#ifdef WITHOUT_TEMPERATURE\n    EnableDlgCtrl(IDC_CPU_TEMP_TIP_CHECK, false);\n    EnableDlgCtrl(IDC_CPU_TEMP_TIP_EDIT, false);\n    EnableDlgCtrl(IDC_GPU_TEMP_TIP_CHECK, false);\n    EnableDlgCtrl(IDC_GPU_TEMP_TIP_EDIT, false);\n    EnableDlgCtrl(IDC_HDD_TEMP_TIP_CHECK, false);\n    EnableDlgCtrl(IDC_HDD_TIP_EDIT, false);\n    EnableDlgCtrl(IDC_MBD_TEMP_TIP_CHECK, false);\n    EnableDlgCtrl(IDC_MBD_TEMP_TIP_EDIT, false);\n    EnableDlgCtrl(IDC_CPU_CHECK, false);\n    EnableDlgCtrl(IDC_GPU_CHECK, false);\n    EnableDlgCtrl(IDC_HDD_CHECK, false);\n    EnableDlgCtrl(IDC_MBD_CHECK, false);\n    //EnableDlgCtrl(IDC_SELECT_HARD_DISK_COMBO, false);\n    EnableDlgCtrl(IDC_SELECT_CPU_COMBO, false);\n    EnableDlgCtrl(IDC_CPU_TEMP_STATIC, false);\n    EnableDlgCtrl(IDC_GPU_TEMP_STATIC, false);\n    EnableDlgCtrl(IDC_HDD_STATIC, false);\n    EnableDlgCtrl(IDC_MBD_TEMP_STATIC, false);\n    //EnableDlgCtrl(IDC_SELECT_HDD_STATIC, false);\n    EnableDlgCtrl(IDC_SELECT_CPU_STATIC, false);\n    EnableDlgCtrl(IDC_HARDWARE_MONITOR_STATIC, false);\n#endif\n\n    m_plugin_manager_btn.SetIcon(theApp.GetMenuIcon(IDI_PLUGINS));\n    m_select_connection_btn.SetIcon(theApp.GetMenuIcon(IDI_CONNECTION));\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedCheckNowButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    theApp.CheckUpdateInThread(true);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedCheckUpdateCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.check_update_when_start = (((CButton*)GetDlgItem(IDC_CHECK_UPDATE_CHECK))->GetCheck() != 0);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedAutoRunCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.auto_run = (((CButton*)GetDlgItem(IDC_AUTO_RUN_CHECK))->GetCheck() != 0);\n    m_auto_run_modified = true;\n}\n\n\nvoid CGeneralSettingsDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //获取消息提示的设置\n    m_data.traffic_tip_value = m_traffic_tip_edit.GetValue();\n    if (m_data.traffic_tip_value < 1) m_data.traffic_tip_value = 1;\n    if (m_data.traffic_tip_value > 32767) m_data.traffic_tip_value = 32767;\n    m_data.traffic_tip_unit = m_traffic_tip_combo.GetCurSel();\n\n    auto checkTipValue = [](int& value)\n    {\n        if (value < 1) value = 1;\n        if (value > 100) value = 100;\n    };\n    auto checkTempTipValue = [](int& value)\n    {\n        if (value < 1) value = 1;\n        if (value > 120) value = 120;\n    };\n    m_data.memory_usage_tip.tip_value = m_memory_tip_edit.GetValue();\n    checkTipValue(m_data.memory_usage_tip.tip_value);\n\n    m_data.cpu_temp_tip.tip_value = m_cpu_temp_tip_edit.GetValue();\n    checkTempTipValue(m_data.cpu_temp_tip.tip_value);\n\n    m_data.gpu_temp_tip.tip_value = m_gpu_temp_tip_edit.GetValue();\n    checkTempTipValue(m_data.gpu_temp_tip.tip_value);\n\n    m_data.hdd_temp_tip.tip_value = m_hdd_temp_tip_edit.GetValue();\n    checkTempTipValue(m_data.hdd_temp_tip.tip_value);\n\n    m_data.mainboard_temp_tip.tip_value = m_mbd_temp_tip_edit.GetValue();\n    checkTempTipValue(m_data.mainboard_temp_tip.tip_value);\n\n    //获取语言的设置\n    m_data.language = 0;\n    if (m_language_combo.GetCurSel() > 0)\n    {\n        //选择的不是“跟随系统”\n        int current_language_index = m_language_combo.GetCurSel() - 1;\n        if (current_language_index >= 0 && current_language_index < static_cast<int>(theApp.m_str_table.GetLanguageList().size()))\n        {\n            m_data.language = theApp.m_str_table.GetLanguageList()[current_language_index].language_id;\n        }\n    }\n    if (m_data.language != theApp.m_general_data.language)\n    {\n        MessageBox(CCommon::LoadText(IDS_LANGUAGE_CHANGE_INFO), NULL, MB_ICONINFORMATION | MB_OK);\n    }\n    m_show_all_interface_modified = (m_data.show_all_interface != theApp.m_general_data.show_all_interface);\n\n    //获取数据文件保存位置的设置\n    m_data.portable_mode = (((CButton*)GetDlgItem(IDC_SAVE_TO_PROGRAM_DIR_RADIO))->GetCheck() != 0);\n    if (m_data.portable_mode != theApp.m_general_data.portable_mode)\n    {\n        MessageBox(CCommon::LoadText(IDS_CFG_DIR_CHANGED_INFO), NULL, MB_ICONINFORMATION | MB_OK);\n    }\n\n    //m_taskbar_item_modified = (theApp.m_taskbar_data.display_item != taskbar_displat_item_ori);\n\n    CTabDlg::OnOK();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedTodayTrafficTipCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.traffic_tip_enable = (((CButton*)GetDlgItem(IDC_TODAY_TRAFFIC_TIP_CHECK))->GetCheck() != 0);\n    SetControlEnable();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedMemoryUsageTipCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.memory_usage_tip.enable = (((CButton*)GetDlgItem(IDC_MEMORY_USAGE_TIP_CHECK))->GetCheck() != 0);\n    SetControlEnable();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedOpenConfigPathButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    ShellExecute(NULL, _T(\"explore\"), theApp.m_config_dir.c_str(), NULL, NULL, SW_SHOWNORMAL);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedShowAllConnectionCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.show_all_interface = (((CButton*)GetDlgItem(IDC_SHOW_ALL_CONNECTION_CHECK))->GetCheck() != 0);\n    SetControlEnable();\n}\n\n\nBOOL CGeneralSettingsDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    if (pMsg->message == WM_MOUSEMOVE)\n        m_toolTip.RelayEvent(pMsg);\n\n    return CTabDlg::PreTranslateMessage(pMsg);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedUseCpuTimeRadio()\n{\n    m_data.cpu_usage_acquire_method = GeneralSettingData::CA_CPU_TIME;\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedUsePdhRadio()\n{\n    m_data.cpu_usage_acquire_method = GeneralSettingData::CA_PDH;\n}\n\nvoid CGeneralSettingsDlg::OnBnClickedUseHardwareMonitorRadio()\n{\n    m_data.cpu_usage_acquire_method = GeneralSettingData::CA_HARDWARE_MONITOR;\n}\n\nafx_msg LRESULT CGeneralSettingsDlg::OnSpinEditPosChanged(WPARAM wParam, LPARAM lParam)\n{\n    CSpinButtonCtrl* pSpin = (CSpinButtonCtrl*)wParam;\n    if (pSpin == nullptr)\n        return 0;\n    CWnd* pEdit = pSpin->GetBuddy();\n    if (pEdit == &m_monitor_span_edit)       //当用户点击了“监控时间间隔”的微调按钮时\n    {\n        LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(lParam);\n        if (pNMUpDown->iDelta == -1)\n        {\n            // 用户按下了spin控件的向下箭头\n            int value = m_monitor_span_edit.GetValue();\n            value -= MONITOR_SPAN_STEP;\n            value /= MONITOR_SPAN_STEP;\n            value *= MONITOR_SPAN_STEP;\n            m_monitor_span_edit.SetValue(value);\n        }\n        else if (pNMUpDown->iDelta == 1)\n        {\n            // 用户按下了spin控件的向上箭头\n            int value = m_monitor_span_edit.GetValue();\n            value += MONITOR_SPAN_STEP;\n            value /= MONITOR_SPAN_STEP;\n            value *= MONITOR_SPAN_STEP;\n            m_monitor_span_edit.SetValue(value);\n        }\n        pNMUpDown->iDelta = 0;\n    }\n    return 0;\n}\n\n\n\nvoid CGeneralSettingsDlg::OnEnKillfocusMonitorSpanEdit()\n{\n    // TODO: 在此添加控件通知处理程序代码\n\n    //这里限制监控时间间隔只能输入100的倍数\n    CString str;\n    GetDlgItemText(IDC_MONITOR_SPAN_EDIT, str);\n    str.Replace(_T(\",\"), _T(\"\"));\n    int value = _ttoi(str.GetString());\n    if (value < MONITOR_TIME_SPAN_MIN || value > MONITOR_TIME_SPAN_MAX)\n    {\n        value = 1000;\n    }\n    else\n    {\n        value /= MONITOR_SPAN_STEP;\n        value *= MONITOR_SPAN_STEP;\n    }\n    m_monitor_span_edit.SetValue(value);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedCpuTempTipCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.cpu_temp_tip.enable = (IsDlgButtonChecked(IDC_CPU_TEMP_TIP_CHECK) != 0);\n    SetControlEnable();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedGpuTempTipCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.gpu_temp_tip.enable = (IsDlgButtonChecked(IDC_GPU_TEMP_TIP_CHECK) != 0);\n    SetControlEnable();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedHddTempTipCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.hdd_temp_tip.enable = (IsDlgButtonChecked(IDC_HDD_TEMP_TIP_CHECK) != 0);\n    SetControlEnable();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedMbdTempTipCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.mainboard_temp_tip.enable = (IsDlgButtonChecked(IDC_MBD_TEMP_TIP_CHECK) != 0);\n    SetControlEnable();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedGithubRadio()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.update_source = 0;\n    theApp.m_general_data.update_source = 0;        //点击“更新源”的单选按钮时，同时更改theApp中的设置，以确保点击“立即检查”按钮时使用选择的更新源更新\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedGiteeRadio()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.update_source = 1;\n    theApp.m_general_data.update_source = 1;\n}\n\n\nvoid CGeneralSettingsDlg::OnCancel()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    theApp.m_general_data.update_source = m_update_source_ori;      //点击“取消”时恢复开始的“更新源”选项\n\n    CTabDlg::OnCancel();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedRestoreDefaultTimeSpanButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_monitor_span_edit.SetValue(1000);\n}\n\n\nvoid CGeneralSettingsDlg::OnCbnSelchangeSelectHardDiskCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CString hard_disk_name;\n    m_hard_disk_combo.GetWindowText(hard_disk_name);\n    m_data.hard_disk_name = hard_disk_name.GetString();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedCpuCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    bool checked = IsDlgButtonChecked(IDC_CPU_CHECK) != 0;\n    if (checked && !ShowHardwareMonitorWarning())\n    {\n        checked = false;\n        CheckDlgButton(IDC_CPU_CHECK, FALSE);\n    }\n    m_data.SetHardwareEnable(HI_CPU, checked);\n    EnableDlgCtrl(IDC_USE_HARDWARE_MONITOR_RADIO, checked);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedGpuCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    bool checked = IsDlgButtonChecked(IDC_GPU_CHECK) != 0;\n    if (checked && !ShowHardwareMonitorWarning())\n    {\n        checked = false;\n        CheckDlgButton(IDC_GPU_CHECK, FALSE);\n    }\n    m_data.SetHardwareEnable(HI_GPU, checked);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedHddCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    bool checked = IsDlgButtonChecked(IDC_HDD_CHECK) != 0;\n    if (checked && !ShowHardwareMonitorWarning())\n    {\n        checked = false;\n        CheckDlgButton(IDC_HDD_CHECK, FALSE);\n    }\n    m_data.SetHardwareEnable(HI_HDD, checked);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedMbdCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    bool checked = IsDlgButtonChecked(IDC_MBD_CHECK) != 0;\n    if (checked && !ShowHardwareMonitorWarning())\n    {\n        checked = false;\n        CheckDlgButton(IDC_MBD_CHECK, FALSE);\n    }\n    m_data.SetHardwareEnable(HI_MBD, checked);\n\n}\n\n\nvoid CGeneralSettingsDlg::OnCbnSelchangeSelectCpuCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CString cpu_core_name;\n    m_select_cpu_combo.GetWindowText(cpu_core_name);\n    m_data.cpu_core_name = cpu_core_name.GetString();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedPluginManageButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CPluginManagerDlg dlg;\n    dlg.DoModal();\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedShowNotifyIconCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.show_notify_icon = (IsDlgButtonChecked(IDC_SHOW_NOTIFY_ICON_CHECK) != 0);\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedSelectConnectionsButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CSelectConnectionsDlg dlg(m_data.connections_hide);\n    if (dlg.DoModal() == IDOK)\n    {\n        m_data.connections_hide = dlg.GetData();\n    }\n}\n\n\nvoid CGeneralSettingsDlg::OnBnClickedResetAutoRunButton()\n{\n    //先删除开机自动运行\n    theApp.SetAutoRunByRegistry(false);\n    theApp.SetAutoRunByTaskScheduler(false);\n    if (!theApp.SetAutoRun(true))    //重新设置开机自动运行\n    {\n        MessageBox(CCommon::LoadText(IDS_SET_AUTO_RUN_FAILED_WARNING), NULL, MB_ICONWARNING | MB_OK);\n        return;\n    }\n    //获取开机自动运行的路径\n    bool auto_run = theApp.GetAutoRun(&m_auto_run_path);\n    //重新勾选“开机自动运行”复选框\n    CheckDlgButton(IDC_AUTO_RUN_CHECK, auto_run);\n    //更新鼠标提示\n    AddOrUpdateAutoRunTooltip(false);\n}\n\n\nvoid CGeneralSettingsDlg::OnEnChangeMonitorSpanEdit()\n{\n    m_data.monitor_time_span = m_monitor_span_edit.GetValue();\n}\n"
  },
  {
    "path": "TrafficMonitor/GeneralSettingsDlg.h",
    "content": "﻿#pragma once\n#include \"TabDlg.h\"\n#include \"SpinEdit.h\"\n#include \"ComboBox2.h\"\n\n// CGeneralSettingsDlg dialog\n\nclass CGeneralSettingsDlg : public CTabDlg\n{\n    DECLARE_DYNAMIC(CGeneralSettingsDlg)\n\npublic:\n    CGeneralSettingsDlg(CWnd* pParent = NULL);   // standard constructor\n    virtual ~CGeneralSettingsDlg();\n\n    static void CheckTaskbarDisplayItem();\n\n    //选项设置数据\n    GeneralSettingData m_data;\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_GENERAL_SETTINGS_DIALOG };\n#endif\n\npublic:\n    bool IsAutoRunModified() const { return m_auto_run_modified; }\n    bool IsShowAllInterfaceModified() const { return m_show_all_interface_modified; }\n    bool IsMonitorTimeSpanModified() const;\n    //bool IsTaskbarItemModified() const { return m_taskbar_item_modified; }\n\nprotected:\n    bool m_auto_run_modified{ false };      //如果更改了开机自动运行的设置，则会置为true\n    bool m_show_all_interface_modified{ false };\n    int m_monitor_time_span_ori{};\n    int m_update_source_ori{};\n    //bool m_taskbar_item_modified{ false };\n    wstring m_auto_run_path;\n\n    //控件变量\n    CSpinEdit m_traffic_tip_edit;\n    CComboBox2 m_traffic_tip_combo;\n    CSpinEdit m_memory_tip_edit;\n    CComboBox2 m_language_combo;\n    CToolTipCtrl m_toolTip;\n    CSpinEdit m_monitor_span_edit;\n    CSpinEdit m_cpu_temp_tip_edit;\n    CSpinEdit m_gpu_temp_tip_edit;\n    CSpinEdit m_hdd_temp_tip_edit;\n    CSpinEdit m_mbd_temp_tip_edit;\n    CComboBox2 m_hard_disk_combo;\n    CComboBox2 m_select_cpu_combo;\n    CButton m_plugin_manager_btn;\n    CButton m_select_connection_btn;\n\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support\n\n    //设置控件的启用和禁用\n    void SetControlEnable();\n\n    virtual void SetControlMouseWheelEnable(bool enable) override;\n    virtual void OnSettingsApplied() override;\n    virtual bool InitializeControls() override;\n\n    //显示开启硬件监控时的提示，如果用户选择了“是”则返回true，否则返回false\n    //“以后不再显示该对话框”的标记保存在注册表“\\HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DontShowMeThisDialogAgain”\n    bool ShowHardwareMonitorWarning();\n\n    //添加或更新开机自动运行的鼠标提示\n    void AddOrUpdateAutoRunTooltip(bool add);\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    afx_msg void OnBnClickedCheckNowButton();\n    afx_msg void OnBnClickedCheckUpdateCheck();\n    afx_msg void OnBnClickedAutoRunCheck();\n    virtual void OnOK();\n    afx_msg void OnBnClickedTodayTrafficTipCheck();\n    afx_msg void OnBnClickedMemoryUsageTipCheck();\n    afx_msg void OnBnClickedOpenConfigPathButton();\n    afx_msg void OnBnClickedShowAllConnectionCheck();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    afx_msg void OnBnClickedUseCpuTimeRadio();\n    afx_msg void OnBnClickedUsePdhRadio();\n    afx_msg void OnBnClickedUseHardwareMonitorRadio();\n    afx_msg LRESULT OnSpinEditPosChanged(WPARAM wParam, LPARAM lParam);\n    afx_msg void OnEnKillfocusMonitorSpanEdit();\n    afx_msg void OnBnClickedCpuTempTipCheck();\n    afx_msg void OnBnClickedGpuTempTipCheck();\n    afx_msg void OnBnClickedHddTempTipCheck();\n    afx_msg void OnBnClickedMbdTempTipCheck();\n    afx_msg void OnBnClickedGithubRadio();\n    afx_msg void OnBnClickedGiteeRadio();\n    virtual void OnCancel();\n    afx_msg void OnBnClickedRestoreDefaultTimeSpanButton();\n    afx_msg void OnCbnSelchangeSelectHardDiskCombo();\n    afx_msg void OnBnClickedCpuCheck();\n    afx_msg void OnBnClickedGpuCheck();\n    afx_msg void OnBnClickedHddCheck();\n    afx_msg void OnBnClickedMbdCheck();\n    afx_msg void OnCbnSelchangeSelectCpuCombo();\n    afx_msg void OnBnClickedPluginManageButton();\n    afx_msg void OnBnClickedShowNotifyIconCheck();\n    afx_msg void OnBnClickedSelectConnectionsButton();\n    afx_msg void OnBnClickedResetAutoRunButton();\n    afx_msg void OnEnChangeMonitorSpanEdit();\nprotected:\n};\n"
  },
  {
    "path": "TrafficMonitor/HResultException.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"HResultException.h\"\n#include \"TrafficMonitor.h\"\n\nnamespace FunctionChecker\n{\n    namespace Details\n    {\n        template <class Strategy>\n        bool StrategicCheck(LPCTSTR p_library_name, Strategy strategy)\n        {\n            bool result = false;\n            auto hmodule = ::LoadLibrary(p_library_name);\n            if (hmodule)\n            {\n                result = strategy(hmodule);\n                ::FreeLibrary(hmodule);\n            }\n            return result;\n        }\n    }\n} // namespace FunctionChecker\n\nbool FunctionChecker::CheckLibraryExist(LPCTSTR p_library_name) noexcept\n{\n    return Details::StrategicCheck(p_library_name,\n                                   [](HMODULE)\n                                   { return true; });\n}\n\nbool FunctionChecker::CheckFunctionExist(LPCTSTR p_library_name, LPCSTR p_function_name) noexcept\n{\n    return Details::StrategicCheck(p_library_name,\n                                   [p_function_name](HMODULE h_library) -> bool\n                                   {\n                                       auto* p_test_function = ::GetProcAddress(h_library, p_function_name);\n                                       return p_test_function != NULL;\n                                   });\n}\n\nconst char* const ERROR_WHEN_CALL_COM_FUNCTION = \"Error occurred when call COM function.\";\n\nvoid ThrowIfFailed(HRESULT hr, const char* p_message)\n{\n    ThrowIfFailed<CHResultException>(hr, std::move(p_message));\n}\n\nCHResultException::CHResultException(HRESULT hr, const char* p_message)\n    : std::runtime_error{p_message}, m_hr{hr},\n      m_get_p_error_hr{::GetErrorInfo(0, &m_p_error)}\n{\n}\n\nauto CHResultException::GetError()\n    -> Microsoft::WRL::ComPtr<IErrorInfo>\n{\n    return m_p_error;\n}\n\nbool CHResultException::HasError() const noexcept\n{\n    return SUCCEEDED(m_hr);\n}\n\nauto CHResultException::GetHResult() const noexcept\n    -> HRESULT\n{\n    return m_hr;\n}\n\nvoid LogHResultException(CHResultException& ex)\n{\n    auto str_hr = \"HResult:\" + std::to_string(ex.GetHResult());\n    CCommon::WriteLog(str_hr.c_str(), theApp.m_log_path.c_str());\n    auto* log = ex.what();\n    CCommon::WriteLog(log, theApp.m_log_path.c_str());\n    auto* p_error = ex.GetError().Get();\n    if (p_error == NULL)\n    {\n        return;\n    }\n    BSTR p_description{NULL};\n    ThrowIfFailed(p_error->GetDescription(&p_description),\n                  TRAFFICMONITOR_ERROR_STR(\"Get description from IErrorInfo failed.\"));\n    CCommon::WriteLog(p_description, theApp.m_log_path.c_str());\n    ::SysFreeString(p_description);\n}"
  },
  {
    "path": "TrafficMonitor/HResultException.h",
    "content": "﻿#pragma once\n#include <stdexcept>\n#include <wrl/client.h>\n\n#define TRAFFICMONITOR_STR_IMPL(x) #x\n#define TRAFFICMONITOR_STR(x) TRAFFICMONITOR_STR_IMPL(x)\n\n#define TRAFFICMONITOR_ERROR_STR(x) \\\n    \"At file: \" TRAFFICMONITOR_STR(__FILE__) \" | line: \" TRAFFICMONITOR_STR(__LINE__) \".\\nError: \" x\n\n#define RELEASE_COM(p)      \\\n    {                       \\\n        if (p)              \\\n        {                   \\\n            (p)->Release(); \\\n            (p) = (NULL);   \\\n        }                   \\\n    }\n\nnamespace FunctionChecker\n{\n    bool CheckLibraryExist(LPCTSTR p_library_name) noexcept;\n    bool CheckFunctionExist(LPCTSTR p_library_name, LPCSTR p_function_name) noexcept;\n}\n\nclass CHResultException : public std::runtime_error\n{\npublic:\n    CHResultException(HRESULT hr, const char* p_message);\n    ~CHResultException() override = default;\n\n    auto GetError()\n        -> Microsoft::WRL::ComPtr<IErrorInfo>;\n    bool HasError() const noexcept;\n    auto GetHResult() const noexcept\n        -> HRESULT;\n\nprivate:\n    Microsoft::WRL::ComPtr<IErrorInfo> m_p_error;\n    HRESULT m_hr;\n    HRESULT m_get_p_error_hr;\n};\n\nextern const char* const ERROR_WHEN_CALL_COM_FUNCTION; /*The content should be \"Error occurred when call COM function.\" */\nvoid ThrowIfFailed(HRESULT hr, const char* p_message = ERROR_WHEN_CALL_COM_FUNCTION);\ntemplate <class Exception, class... Args>\nvoid ThrowIfFailed(HRESULT hr, const char* p_message, Args... args)\n{\n    if (FAILED(hr))\n    {\n        throw Exception{hr, p_message, std::forward<Args>(args)...};\n    }\n}\n\nvoid LogHResultException(CHResultException& ex);\n"
  },
  {
    "path": "TrafficMonitor/HighResolutionTimer.h",
    "content": "﻿#include <MMSYSTEM.H>\n#pragma comment(lib, \"WINMM.LIB\")\n\nclass CHighResolutionTimer\n{\n    typedef void(*TIMERCALLBACK)(DWORD_PTR);\n\nprivate:\n    DWORD_PTR m_dwUser;\n    MMRESULT m_nIDTimer;\n    UINT m_uDelay;\n    TIMERCALLBACK m_pfnCallback;\n\npublic:\n    void KillTimer()\n    {\n        if (m_nIDTimer != NULL)\n        {\n            timeKillEvent(m_nIDTimer);\n            m_nIDTimer = NULL;\n        }\n    }\n\n    CHighResolutionTimer()\n    {\n        m_nIDTimer = NULL;\n        m_uDelay = 0;\n        m_pfnCallback = 0;\n    }\n\n    virtual ~CHighResolutionTimer()\n    {\n        KillTimer();\n    }\n\n    static void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)\n    {\n        // dwUser contains ptr to Timer object\n        CHighResolutionTimer * ptimer = (CHighResolutionTimer *)dwUser;\n        // Call user-specified callback and pass back user specified data\n        (ptimer->m_pfnCallback) (ptimer->m_dwUser);\n    }\n\n    BOOL CreateTimer(DWORD_PTR dwUser, UINT uDelay, TIMERCALLBACK lpTimeProc)\n    {\n        ASSERT(dwUser);\n        ASSERT(lpTimeProc);\n\n        m_dwUser = dwUser;\n        m_pfnCallback = lpTimeProc;\n        BOOL ret = FALSE;\n        KillTimer();\n        m_nIDTimer = timeSetEvent(uDelay, 0, (LPTIMECALLBACK)TimeProc, (DWORD_PTR)this, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);\n\n        if (m_nIDTimer != NULL)\n            ret = TRUE;\n        return(ret);\n    }\n};\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficCalendarDlg.cpp",
    "content": "﻿// HistoryTrafficCalendarDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"HistoryTrafficCalendarDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// CHistoryTrafficCalendarDlg 对话框\n\nIMPLEMENT_DYNAMIC(CHistoryTrafficCalendarDlg, CTabDlg)\n\nCHistoryTrafficCalendarDlg::CHistoryTrafficCalendarDlg(deque<HistoryTraffic>& history_traffics, CWnd* pParent /*=nullptr*/)\n    : CTabDlg(IDD_HISTORY_TRAFFIC_CALENDAR_DIALOG, pParent), m_history_traffics(history_traffics)\n{\n\n}\n\nCHistoryTrafficCalendarDlg::~CHistoryTrafficCalendarDlg()\n{\n}\n\nvoid CHistoryTrafficCalendarDlg::SetDayTraffic()\n{\n    for (int i{}; i < CALENDAR_HEIGHT; i++)\n    {\n        for (int j{}; j < CALENDAR_WIDTH; j++)\n        {\n            HistoryTraffic history_traffic;\n            history_traffic.year = m_year;\n            history_traffic.month = m_month;\n            history_traffic.day = m_calendar[i][j].day;\n            //使用二分法查找日历中每一个日期的流量\n            if (history_traffic.day > 0)\n            {\n                if (std::binary_search(m_history_traffics.begin(), m_history_traffics.end(), history_traffic, HistoryTraffic::DateGreater))\n                {\n                    auto iter = std::lower_bound(m_history_traffics.begin(), m_history_traffics.end(), history_traffic, HistoryTraffic::DateGreater);\n                    if (iter != m_history_traffics.end())\n                    {\n                        m_calendar[i][j].up_traffic = iter->up_kBytes;\n                        m_calendar[i][j].down_traffic = iter->down_kBytes;\n                        m_calendar[i][j].mixed = iter->mixed;\n\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid CHistoryTrafficCalendarDlg::MonthSelectChanged()\n{\n    CCalendarHelper::GetCalendar(m_year, m_month, m_calendar, theApp.m_cfg_data.m_sunday_first);\n    SetDayTraffic();\n    CalculateMonthTotalTraffic();\n    InvalidateRect(m_draw_rect);\n}\n\nvoid CHistoryTrafficCalendarDlg::CalculateMonthTotalTraffic()\n{\n    m_month_total_upload = 0;\n    m_month_total_download = 0;\n    for (int i{}; i < CALENDAR_HEIGHT; i++)\n    {\n        for (int j{}; j < CALENDAR_WIDTH; j++)\n        {\n            m_month_total_upload += m_calendar[i][j].up_traffic;\n            m_month_total_download += m_calendar[i][j].down_traffic;\n        }\n    }\n}\n\nvoid CHistoryTrafficCalendarDlg::SetComboSel()\n{\n    int cnt{};\n    int year_selected;\n    for (int i{ m_year_max }; i >= m_year_min; i--)\n    {\n        if (i == m_year)\n            year_selected = cnt;\n        cnt++;\n    }\n    m_year_combo.SetCurSel(year_selected);\n    m_month_combo.SetCurSel(m_month - 1);\n}\n\nvoid CHistoryTrafficCalendarDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CTabDlg::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_YEAR_COMBO, m_year_combo);\n    DDX_Control(pDX, IDC_MONTH_COMBO, m_month_combo);\n}\n\n\nbool CHistoryTrafficCalendarDlg::IsWeekend(int index)\n{\n    if (theApp.m_cfg_data.m_sunday_first)\n        return (index == 0 || index == 6);\n    else\n        return (index == 5 || index == 6);\n}\n\nCString CHistoryTrafficCalendarDlg::GetWeekdayString(int index)\n{\n    if (!theApp.m_cfg_data.m_sunday_first)\n    {\n        index++;\n        if (index > 6)\n            index = 0;\n    }\n    switch (index)\n    {\n    case 0:\n        return CCommon::LoadText(IDS_SUNDAY);\n    case 1:\n        return CCommon::LoadText(IDS_MONDAY);\n    case 2:\n        return CCommon::LoadText(IDS_TUESDAY);\n    case 3:\n        return CCommon::LoadText(IDS_WEDNESDAY);\n    case 4:\n        return CCommon::LoadText(IDS_THURSDAY);\n    case 5:\n        return CCommon::LoadText(IDS_FRIDAY);\n    case 6:\n        return CCommon::LoadText(IDS_SATURDAY);\n    }\n    return CString();\n}\n\nBEGIN_MESSAGE_MAP(CHistoryTrafficCalendarDlg, CTabDlg)\n    ON_WM_PAINT()\n    ON_CBN_SELCHANGE(IDC_YEAR_COMBO, &CHistoryTrafficCalendarDlg::OnCbnSelchangeYearCombo)\n    ON_CBN_SELCHANGE(IDC_MONTH_COMBO, &CHistoryTrafficCalendarDlg::OnCbnSelchangeMonthCombo)\n    ON_WM_MOUSEMOVE()\n    ON_BN_CLICKED(IDC_PREVIOUS_BUTTON, &CHistoryTrafficCalendarDlg::OnBnClickedPreviousButton)\n    ON_BN_CLICKED(IDC_NEXT_BUTTON, &CHistoryTrafficCalendarDlg::OnBnClickedNextButton)\n    ON_WM_MOUSEWHEEL()\n    ON_BN_CLICKED(IDC_MENU_BUTTON, &CHistoryTrafficCalendarDlg::OnBnClickedMenuButton)\n    ON_WM_INITMENU()\n    ON_COMMAND(ID_FIRST_DAY_OF_WEEK_SUNDAY, &CHistoryTrafficCalendarDlg::OnFirstDayOfWeekSunday)\n    ON_COMMAND(ID_FIRST_DAY_OF_WEEK_MONDAY, &CHistoryTrafficCalendarDlg::OnFirstDayOfWeekMonday)\n    ON_COMMAND(ID_CALENDAR_JUMP_TO_TODAY, &CHistoryTrafficCalendarDlg::OnCalendarJumpToToday)\nEND_MESSAGE_MAP()\n\n\n// CHistoryTrafficCalendarDlg 消息处理程序\n\n\nBOOL CHistoryTrafficCalendarDlg::OnInitDialog()\n{\n    CTabDlg::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    m_year = m_history_traffics[0].year;\n    m_month = m_history_traffics[0].month;\n    CCalendarHelper::GetCalendar(m_year, m_month, m_calendar, theApp.m_cfg_data.m_sunday_first);\n    SetDayTraffic();\n    CalculateMonthTotalTraffic();\n\n    //初始化Combo Box\n    m_year_max = m_history_traffics[0].year;\n    m_year_min = m_history_traffics.back().year;\n    for (int i{ m_year_max }; i >= m_year_min; i--)\n    {\n        m_year_combo.AddString(CCommon::IntToString(i));\n    }\n    m_year_combo.SetCurSel(0);\n    for (int i{ 1 }; i <= 12; i++)\n    {\n        m_month_combo.AddString(CCommon::IntToString(i));\n    }\n    m_month_combo.SetCurSel(m_month - 1);\n\n    //初始化鼠标提示\n    m_tool_tips.Create(this, TTS_ALWAYSTIP | TTS_NOPREFIX);\n    m_tool_tips.SetMaxTipWidth(800);        //为鼠标提示设置一个最大宽度，以允许其换行\n    m_tool_tips.AddTool(this, _T(\"\"));\n\n    CCommon::LoadMenuResource(m_menu, IDR_HISTORY_TRAFFIC_MENU);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnPaint()\n{\n    CPaintDC dc(this); // device context for painting\n                       // TODO: 在此处添加消息处理程序代码\n                       // 不为绘图消息调用 CTabDlg::OnPaint()\n    CRect wndRect;\n    GetWindowRect(wndRect);\n    const int width = theApp.DPI(40);       //日历中每一个格子的宽度\n    const int height = theApp.DPI(30);      //日历中第一个格子的高度\n    m_draw_rect.left = m_start_x;\n    m_draw_rect.top = m_start_y;\n    //m_draw_rect.right = m_draw_rect.left + (CALENDAR_WIDTH*width);\n    m_draw_rect.right = wndRect.Width() - m_start_x;\n    m_draw_rect.bottom = m_draw_rect.top + ((CALENDAR_HEIGHT + 2) * height) + theApp.DPI(20);\n\n    //使用双缓冲绘图\n    CDrawDoubleBuffer draw_double_buffer(&dc, m_draw_rect);\n\n    //绘图\n    CDrawCommon draw;\n    draw.Create(draw_double_buffer.GetMemDC(), this);\n    draw.FillRect(CRect(0, 0, m_draw_rect.Width(), m_draw_rect.Height()), RGB(255, 255, 255));      //填充白色背景色\n    CRect rect{};\n    rect.left = 0;\n    rect.top = 0;\n    rect.right = rect.left + width;\n    rect.bottom = rect.top + height;\n    //画星期的行\n    for (int i{}; i < CALENDAR_WIDTH; i++)\n    {\n        rect.MoveToX(i * width);\n\n        if (IsWeekend(i))\n            draw.SetBackColor(RGB(217, 86, 86));\n        else if (i % 2 == 0)\n            draw.SetBackColor(RGB(1, 84, 151));\n        else\n            draw.SetBackColor(RGB(1, 107, 191));\n        CString str = GetWeekdayString(i);\n        draw.DrawWindowText(rect, str, RGB(255, 255, 255), IDrawCommon::Alignment::CENTER, true);\n    }\n\n    //绘制日历\n    for (int i{}; i < CALENDAR_HEIGHT; i++)\n    {\n        for (int j{}; j < CALENDAR_WIDTH; j++)\n        {\n            //设置日历中每一天的矩形的位置\n            rect.MoveToXY(j * width, height + theApp.DPI(2) + i * height);\n            //保存矩形的位置\n            m_calendar[i][j].rect = rect;\n            //绘制日期的数据\n            //绘制格子的背景颜色\n            if (IsWeekend(j))       //是周末时\n            {\n                if ((i + j) % 2 == 0)\n                    draw.SetBackColor(RGB(250, 234, 234));\n                else\n                    draw.SetBackColor(RGB(252, 242, 242));\n            }\n            else\n            {\n                if ((i + j) % 2 == 0)\n                    draw.SetBackColor(RGB(226, 241, 254));\n                else\n                    draw.SetBackColor(RGB(236, 246, 254));\n            }\n            draw.FillRectWithBackColor(rect);\n            //绘制格子上的日期的数字\n            CRect day_rect{ rect };\n            day_rect.bottom -= (rect.Height() / 2);\n            COLORREF text_color;\n            if (IsWeekend(j))\n                text_color = RGB(131, 29, 28);\n            else\n                text_color = RGB(0, 57, 107);\n            if (m_calendar[i][j].day != 0)\n                draw.DrawWindowText(day_rect, CCommon::IntToString(m_calendar[i][j].day), text_color, IDrawCommon::Alignment::CENTER, true);\n            //在今天的日期上画一个矩形框\n            COLORREF frame_color;\n            if (IsWeekend(j))\n                frame_color = RGB(218, 91, 91);\n            else\n                frame_color = RGB(1, 133, 238);\n            if (m_year == m_history_traffics[0].year && m_month == m_history_traffics[0].month && m_calendar[i][j].day == m_history_traffics[0].day)\n                draw.DrawRectOutLine(rect, frame_color, theApp.DPI(2));\n\n            //绘制指示流量大小的矩形\n            COLORREF color;\n            if (m_calendar[i][j].traffic() < 1024 * 1024)       //流量小于1GB时绘制蓝色\n                color = TRAFFIC_COLOR_BLUE;\n            else if (m_calendar[i][j].traffic() < 10 * 1024 * 1024) //流量小于10GB时绘制绿色\n                color = TRAFFIC_COLOR_GREEN;\n            else if (m_calendar[i][j].traffic() < 100 * 1024 * 1024)    //流量小于100GB时绘制黄色\n                color = TRAFFIC_COLOR_YELLOE;\n            else if (m_calendar[i][j].traffic() < 1024 * 1024 * 1024)   //流量小于1TB时绘制红色\n                color = TRAFFIC_COLOR_RED;\n            else        //流量超过1TB时显示深红色\n                color = TRAFFIC_COLOR_DARK_RED;\n            if (m_calendar[i][j].traffic() > 0)\n            {\n                CRect traffic_rect;\n                traffic_rect.left = rect.left + theApp.DPI(14);\n                traffic_rect.right = traffic_rect.left + theApp.DPI(12);\n                traffic_rect.top = rect.top + theApp.DPI(16);\n                traffic_rect.bottom = traffic_rect.top + theApp.DPI(12);\n                draw.FillRect(traffic_rect, color);\n            }\n        }\n    }\n\n    const COLORREF text_color{ RGB(0, 57, 107) };\n    //画当前月总流量\n    CString info;\n    info.Format(_T(\"%s %s (%s: %s, %s: %s)\"), CCommon::LoadText(IDS_CURRENT_MONTH_TOTAL_TRAFFIC),\n        CCommon::KBytesToString(m_month_total_upload + m_month_total_download),\n        CCommon::LoadText(IDS_UPLOAD), CCommon::KBytesToString(m_month_total_upload),\n        CCommon::LoadText(IDS_DOWNLOAD), CCommon::KBytesToString(m_month_total_download)\n    );\n    CRect info_rect;\n    info_rect.left = 0;\n    info_rect.top = height * (CALENDAR_HEIGHT + 1) + theApp.DPI(5);\n    info_rect.right = info_rect.left + m_draw_rect.Width();\n    info_rect.bottom = info_rect.top + theApp.DPI(36);\n    draw.SetBackColor(RGB(255, 255, 255));\n    draw.DrawWindowText(info_rect, info, text_color, IDrawCommon::Alignment::LEFT, true, true);\n\n    //画图例\n    CRect rc_legend{ info_rect };\n    rc_legend.MoveToXY(CALENDAR_WIDTH * width + theApp.DPI(32), theApp.DPI(16));\n    rc_legend.right = m_draw_rect.Width();\n    rc_legend.bottom = rc_legend.top + theApp.DPI(16);\n\n    draw.DrawWindowText(rc_legend, CCommon::LoadText(IDS_LEGEND, _T(\":\")), text_color, IDrawCommon::Alignment::LEFT, true, true);\n    rc_legend.MoveToY(rc_legend.bottom + theApp.DPI(6));\n    CRect rc_legend_box{ rc_legend };\n    const int box_side{ theApp.DPI(12) };\n    const int line_gap{ theApp.DPI(6) };\n    rc_legend_box.top = rc_legend.top + (rc_legend.Height() - box_side) / 2;\n    rc_legend_box.bottom = rc_legend_box.top + box_side;\n    rc_legend_box.right = rc_legend_box.left + box_side;\n    rc_legend.left = rc_legend_box.right + theApp.DPI(4);\n    //蓝色图例\n    draw.FillRect(rc_legend_box, TRAFFIC_COLOR_BLUE);\n    draw.DrawWindowText(rc_legend, _T(\"0~1GB\"), text_color);\n    //绿色图例\n    rc_legend.MoveToY(rc_legend.bottom + line_gap);\n    rc_legend_box.MoveToY(rc_legend.top + (rc_legend.Height() - box_side) / 2);\n    draw.FillRect(rc_legend_box, TRAFFIC_COLOR_GREEN);\n    draw.DrawWindowText(rc_legend, _T(\"1GB~10GB\"), text_color);\n    //黄色图例\n    rc_legend.MoveToY(rc_legend.bottom + line_gap);\n    rc_legend_box.MoveToY(rc_legend.top + (rc_legend.Height() - box_side) / 2);\n    draw.FillRect(rc_legend_box, TRAFFIC_COLOR_YELLOE);\n    draw.DrawWindowText(rc_legend, _T(\"10GB~100GB\"), text_color);\n    //红色图例\n    rc_legend.MoveToY(rc_legend.bottom + line_gap);\n    rc_legend_box.MoveToY(rc_legend.top + (rc_legend.Height() - box_side) / 2);\n    draw.FillRect(rc_legend_box, TRAFFIC_COLOR_RED);\n    draw.DrawWindowText(rc_legend, _T(\"100GB~1TB\"), text_color);\n    //深红色图例\n    rc_legend.MoveToY(rc_legend.bottom + line_gap);\n    rc_legend_box.MoveToY(rc_legend.top + (rc_legend.Height() - box_side) / 2);\n    draw.FillRect(rc_legend_box, TRAFFIC_COLOR_DARK_RED);\n    draw.DrawWindowText(rc_legend, _T(\"1TB~\"), text_color);\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnCbnSelchangeYearCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    int index = m_year_combo.GetCurSel();\n    CString str;\n    m_year_combo.GetLBText(index, str);\n    m_year = _ttoi(str);\n    MonthSelectChanged();\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnCbnSelchangeMonthCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_month = m_month_combo.GetCurSel() + 1;\n    MonthSelectChanged();\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnMouseMove(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    int tip_day{};      //要显示鼠标提示的日期\n    DayTraffic tip_traffic{};\n    static int last_tip_day{};\n    //查找鼠标指针在哪个日期的矩形内\n    for (int i{}; i < CALENDAR_HEIGHT; i++)\n    {\n        for (int j{}; j < CALENDAR_WIDTH; j++)\n        {\n            CRect rect{ m_calendar[i][j].rect };\n            rect.OffsetRect(m_start_x, m_start_y);\n            if (rect.PtInRect(point))\n            {\n                tip_day = m_calendar[i][j].day;\n                tip_traffic = m_calendar[i][j];\n            }\n        }\n    }\n    bool show_tip = (tip_day > 0);\n    if (show_tip && last_tip_day != tip_day)\n    {\n        CString tip_info;\n        tip_info.Format(_T(\"%d/%d/%d\\r\\n\"), m_year, m_month, tip_day);\n        tip_info += CCommon::LoadText(IDS_TRAFFIC_USED1);\n        tip_info += CCommon::KBytesToString(tip_traffic.traffic());\n        if (!tip_traffic.mixed && tip_traffic.traffic() > 0)\n        {\n            tip_info += _T(\"\\r\\n\");\n            tip_info += CCommon::LoadText(IDS_UPLOAD, _T(\": \"));\n            tip_info += CCommon::KBytesToString(tip_traffic.up_traffic);\n            tip_info += _T(\"\\r\\n\");\n            tip_info += CCommon::LoadText(IDS_DOWNLOAD, _T(\": \"));\n            tip_info += CCommon::KBytesToString(tip_traffic.down_traffic);\n        }\n\n        m_tool_tips.AddTool(this, tip_info);\n        m_tool_tips.Pop();\n        last_tip_day = tip_day;\n    }\n    if (!show_tip)\n    {\n        m_tool_tips.AddTool(this, _T(\"\"));\n        m_tool_tips.Pop();\n        last_tip_day = 0;\n    }\n\n    CTabDlg::OnMouseMove(nFlags, point);\n}\n\n\nBOOL CHistoryTrafficCalendarDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    if (m_tool_tips.GetSafeHwnd() != 0)\n    {\n        m_tool_tips.RelayEvent(pMsg);\n    }\n\n    if (pMsg->message == WM_KEYDOWN)\n    {\n        if (pMsg->wParam == VK_LEFT)\n        {\n            OnBnClickedPreviousButton();\n            return TRUE;\n        }\n        if (pMsg->wParam == VK_RIGHT)\n        {\n            OnBnClickedNextButton();\n            return TRUE;\n        }\n    }\n\n    return CTabDlg::PreTranslateMessage(pMsg);\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnBnClickedPreviousButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    if (m_year == m_year_min && m_month == 1)\n        return;\n    m_month--;\n    if (m_month <= 0)\n    {\n        m_month = 12;\n        m_year--;\n    }\n    SetComboSel();\n    MonthSelectChanged();\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnBnClickedNextButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    if (m_year == m_year_max && m_month == 12)\n        return;\n    m_month++;\n    if (m_month > 12)\n    {\n        m_month = 1;\n        m_year++;\n    }\n    SetComboSel();\n    MonthSelectChanged();\n}\n\n\nBOOL CHistoryTrafficCalendarDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    //通过鼠标滚轮翻页\n    if (zDelta > 0)\n    {\n        OnBnClickedPreviousButton();\n    }\n    if (zDelta < 0)\n    {\n        OnBnClickedNextButton();\n    }\n\n    return CTabDlg::OnMouseWheel(nFlags, zDelta, pt);\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnBnClickedMenuButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CWnd* pBtn = GetDlgItem(IDC_MENU_BUTTON);\n    if (pBtn != nullptr)\n    {\n        CRect rect;\n        pBtn->GetWindowRect(rect);\n        CPoint point;\n        point.x = rect.left;\n        point.y = rect.bottom;\n        CMenu* pMenu = m_menu.GetSubMenu(1);\n        if (pMenu != NULL)\n            pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);\n    }\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnInitMenu(CMenu* pMenu)\n{\n    CTabDlg::OnInitMenu(pMenu);\n\n    // TODO: 在此处添加消息处理程序代码\n    if (theApp.m_cfg_data.m_sunday_first)\n        pMenu->CheckMenuRadioItem(ID_FIRST_DAY_OF_WEEK_SUNDAY, ID_FIRST_DAY_OF_WEEK_MONDAY, ID_FIRST_DAY_OF_WEEK_SUNDAY, MF_BYCOMMAND | MF_CHECKED);\n    else\n        pMenu->CheckMenuRadioItem(ID_FIRST_DAY_OF_WEEK_SUNDAY, ID_FIRST_DAY_OF_WEEK_MONDAY, ID_FIRST_DAY_OF_WEEK_MONDAY, MF_BYCOMMAND | MF_CHECKED);\n\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnFirstDayOfWeekSunday()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_cfg_data.m_sunday_first = true;\n    MonthSelectChanged();\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnFirstDayOfWeekMonday()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_cfg_data.m_sunday_first = false;\n    MonthSelectChanged();\n}\n\n\nvoid CHistoryTrafficCalendarDlg::OnCalendarJumpToToday()\n{\n    // TODO: 在此添加命令处理程序代码\n    m_year = m_history_traffics[0].year;\n    m_month = m_history_traffics[0].month;\n    SetComboSel();\n    MonthSelectChanged();\n\n}\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficDlg.cpp",
    "content": "﻿// HistoryTrafficDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"HistoryTrafficDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// CHistoryTrafficDlg 对话框\n\nIMPLEMENT_DYNAMIC(CHistoryTrafficDlg, CBaseDialog)\n\nCHistoryTrafficDlg::CHistoryTrafficDlg(deque<HistoryTraffic>& history_traffics, CWnd* pParent /*=NULL*/)\n    : CBaseDialog(IDD_HISTORY_TRAFFIC_DIALOG, pParent), m_history_traffics(history_traffics), m_tab1_dlg(history_traffics, this), m_tab2_dlg(history_traffics, this)\n{\n\n}\n\nCHistoryTrafficDlg::~CHistoryTrafficDlg()\n{\n}\n\n\nCString CHistoryTrafficDlg::GetDialogName() const\n{\n    return _T(\"HistoryTrafficDlg\");\n}\n\nvoid CHistoryTrafficDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_TAB1, m_tab);\n}\n\nvoid CHistoryTrafficDlg::SetTabWndSize()\n{\n    CRect rect;\n    m_tab.GetClientRect(rect);\n    CRect rcTabItem;\n    m_tab.GetItemRect(0, rcTabItem);\n    rect.top += rcTabItem.Height() + 4;\n    rect.left += 4;\n    rect.bottom -= 4;\n    rect.right -= 4;\n    m_tab1_dlg.MoveWindow(&rect);\n    m_tab2_dlg.MoveWindow(&rect);\n}\n\n\nBEGIN_MESSAGE_MAP(CHistoryTrafficDlg, CBaseDialog)\n    ON_WM_GETMINMAXINFO()\n    ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, &CHistoryTrafficDlg::OnTcnSelchangeTab1)\n    ON_WM_SIZE()\nEND_MESSAGE_MAP()\n\n\n// CHistoryTrafficDlg 消息处理程序\n\n\nBOOL CHistoryTrafficDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_STATISTICS), FALSE);\t\t// 设置小图标\n\n    //插入标签\n    m_tab.InsertItem(0, CCommon::LoadText(IDS_LIST_VIEW));\n    m_tab.InsertItem(1, CCommon::LoadText(IDS_CALENDAR_VIEW));\n    //创建子对话框\n    m_tab1_dlg.Create(IDD_HISTORY_TRAFFIC_LIST_DIALOG, &m_tab);\n    m_tab2_dlg.Create(IDD_HISTORY_TRAFFIC_CALENDAR_DIALOG, &m_tab);\n    //调整子对话框的大小和位置\n    SetTabWndSize();\n    //设置默认选中的标签\n    switch (m_tab_selected)\n    {\n    case 0:\n        m_tab1_dlg.ShowWindow(SW_SHOW);\n        break;\n    case 1:\n        m_tab2_dlg.ShowWindow(SW_SHOW);\n        break;\n    }\n    m_tab.SetCurFocus(m_tab_selected);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\n\nBOOL CHistoryTrafficDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //if (GetKeyState(VK_CONTROL) & 0x80)\n    //{\n    //\tif (pMsg->wParam == 'D')\n    //\t{\n    //\t\tHistoryTraffic h{};\n    //\t\th.year = 2018;\n    //\t\th.month = 4;\n    //\t\th.day = 29;\n    //\t\tauto iter = std::lower_bound(m_history_traffics.begin(), m_history_traffics.end(), h, HistoryTraffic::DateGreater);\n    //\t\tint index = iter - m_history_traffics.begin();\n    //\t}\n    //}\n\n    return CBaseDialog::PreTranslateMessage(pMsg);\n}\n\nvoid CHistoryTrafficDlg::OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_tab_selected = m_tab.GetCurSel();\n    switch (m_tab_selected)\n    {\n    case 0:\n        m_tab1_dlg.ShowWindow(SW_SHOW);\n        m_tab2_dlg.ShowWindow(SW_HIDE);\n        m_tab1_dlg.SetFocus();\n        break;\n    case 1:\n        m_tab2_dlg.ShowWindow(SW_SHOW);\n        m_tab1_dlg.ShowWindow(SW_HIDE);\n        m_tab2_dlg.SetFocus();\n        break;\n    }\n    *pResult = 0;\n}\n\n\nvoid CHistoryTrafficDlg::OnSize(UINT nType, int cx, int cy)\n{\n    CBaseDialog::OnSize(nType, cx, cy);\n\n    // TODO: 在此处添加消息处理程序代码\n    if (nType != SIZE_MINIMIZED && m_tab1_dlg.GetSafeHwnd() != NULL && m_tab2_dlg.GetSafeHwnd() != NULL)\n    {\n        SetTabWndSize();\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficDlg.h",
    "content": "﻿#pragma once\n#include \"afxcmn.h\"\n#include \"Common.h\"\n#include \"HistoryTrafficListDlg.h\"\n#include \"HistoryTrafficCalendarDlg.h\"\n#include \"BaseDialog.h\"\n\n// CHistoryTrafficDlg 对话框\n\nclass CHistoryTrafficDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CHistoryTrafficDlg)\n\npublic:\n    CHistoryTrafficDlg(deque<HistoryTraffic>& history_traffics, CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~CHistoryTrafficDlg();\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_HISTORY_TRAFFIC_DIALOG };\n#endif\n\npublic:\n    CHistoryTrafficListDlg m_tab1_dlg;\n    CHistoryTrafficCalendarDlg m_tab2_dlg;\n\nprotected:\n    deque<HistoryTraffic>& m_history_traffics;\n\n    CTabCtrl m_tab;\n    int m_tab_selected;\n\nprotected:\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    void SetTabWndSize();\n    virtual CString GetDialogName() const override;\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    afx_msg void OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnSize(UINT nType, int cx, int cy);\n};\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficFile.cpp",
    "content": "#include \"stdafx.h\"\n#include \"HistoryTrafficFile.h\"\n#include \"Common.h\"\n\nCHistoryTrafficFile::CHistoryTrafficFile(const wstring& file_path)\n\t: m_file_path(file_path)\n{\n}\n\nCHistoryTrafficFile::~CHistoryTrafficFile()\n{\n}\n\nvoid CHistoryTrafficFile::Save() const\n{\n\tofstream file{ m_file_path };\n\tchar buff[64];\n\tsprintf_s(buff, \"lines: \\\"%u\\\"\", static_cast<unsigned int>(m_history_traffics.size()));\t\t\t//ڵһд\n\tfile << buff << std::endl;\n\tfor (const auto& history_traffic : m_history_traffics)\n\t{\n\t\tif (history_traffic.mixed)\n\t\t\tsprintf_s(buff, \"%.4d/%.2d/%.2d %llu\", history_traffic.year, history_traffic.month, history_traffic.day, history_traffic.down_kBytes);\n\t\telse\n\t\t\tsprintf_s(buff, \"%.4d/%.2d/%.2d %llu/%llu\", history_traffic.year, history_traffic.month, history_traffic.day, history_traffic.up_kBytes, history_traffic.down_kBytes);\n\t\tfile << buff << std::endl;\n\t}\n\tfile.close();\n}\n\nvoid CHistoryTrafficFile::Load()\n{\n\tifstream file{ m_file_path };\n\tstring current_line, temp;\n\tHistoryTraffic traffic;\n\t//bool first_line{ true };\n\tif (CCommon::FileExist(m_file_path.c_str()))\n\t{\n\t\twhile (!file.eof())\n\t\t{\n\t\t\tif (m_history_traffics.size() > 9999) break;\t\t//ȡ10000ʷ¼\n\t\t\tstd::getline(file, current_line);\n\t\t\t//if (first_line)\n\t\t\t//{\n\t\t\t//\tfirst_line = false;\n\t\t\t//\tsize_t index = current_line.find(\"lines:\");\n\t\t\t//\tif(index != wstring::npos)\n\t\t\t//\t{\n\t\t\t//\t\tindex = current_line.find(\"\\\"\", index + 6);\n\t\t\t//\t\tsize_t index1 = current_line.find(\"\\\"\", index + 1);\n\t\t\t//\t\ttemp = current_line.substr(index + 1, index1 - index - 1);\n\t\t\t//\t\tm_size = atoll(temp.c_str());\n\t\t\t//\t\tcontinue;\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\tif (current_line.size() < 12) continue;\n\t\t\ttemp = current_line.substr(0, 4);\n\t\t\ttraffic.year = atoi(temp.c_str());\n\t\t\tif (traffic.year < 1900 || traffic.year > 3000)\n\t\t\t\tcontinue;\n\t\t\ttemp = current_line.substr(5, 2);\n\t\t\ttraffic.month = atoi(temp.c_str());\n\t\t\tif (traffic.month < 1 || traffic.month > 12)\n\t\t\t\tcontinue;\n\t\t\ttemp = current_line.substr(8, 2);\n\t\t\ttraffic.day = atoi(temp.c_str());\n\t\t\tif (traffic.day < 1 || traffic.day > 31)\n\t\t\t\tcontinue;\n\n\t\t\tint index = current_line.find(L'/', 11);\n\t\t\ttraffic.mixed = (index == wstring::npos);\n\t\t\tif (traffic.mixed)\n\t\t\t{\n\t\t\t\ttemp = current_line.substr(11);\n\t\t\t\ttraffic.down_kBytes = atoll(temp.c_str());\n\t\t\t\ttraffic.up_kBytes = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttemp = current_line.substr(11, index - 11);\n\t\t\t\ttraffic.up_kBytes = atoll(temp.c_str());\n\t\t\t\ttemp = current_line.substr(index + 1);\n\t\t\t\ttraffic.down_kBytes = atoll(temp.c_str());\n\t\t\t}\n\t\t\tif (traffic.year > 0 && traffic.month > 0 && traffic.day > 0 && traffic.kBytes() > 0)\n\t\t\t\tm_history_traffics.push_back(traffic);\n\t\t}\n\t}\n\n\tMormalizeData();\n}\n\nvoid CHistoryTrafficFile::LoadSize()\n{\n\tifstream file{ m_file_path };\n\tstring current_line, temp;\n\tif (CCommon::FileExist(m_file_path.c_str()))\n\t{\n\t\tstd::getline(file, current_line);\t\t\t//ȡһ\n\t\tsize_t index = current_line.find(\"lines:\");\n\t\tif (index != wstring::npos)\n\t\t{\n\t\t\tindex = current_line.find(\"\\\"\", index + 6);\n\t\t\tsize_t index1 = current_line.find(\"\\\"\", index + 1);\n\t\t\ttemp = current_line.substr(index + 1, index1 - index - 1);\n\t\t\tm_size = atoll(temp.c_str());\n\t\t}\n\t}\n}\n\nvoid CHistoryTrafficFile::Merge(const CHistoryTrafficFile& history_traffic, bool ignore_same_data)\n{\n\tfor (const HistoryTraffic& traffic : history_traffic.m_history_traffics)\n\t{\n\t\tif(ignore_same_data)\n\t\t{\n\t\t\t//Ҫͬڵʹöַͬҵˣ\n\t\t\tif (std::binary_search(m_history_traffics.begin(), m_history_traffics.end(), traffic, HistoryTraffic::DateGreater))\n\t\t\t{\n\t\t\t\tauto iter = std::lower_bound(m_history_traffics.begin(), m_history_traffics.end(), traffic, HistoryTraffic::DateGreater);\n\t\t\t\tif (iter != m_history_traffics.end())\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tm_history_traffics.push_back(traffic);\n\t}\n\tMormalizeData();\n}\n\nvoid CHistoryTrafficFile::MormalizeData()\n{\n\tSYSTEMTIME current_time;\n\tGetLocalTime(&current_time);\n\tHistoryTraffic traffic;\n\ttraffic.year = current_time.wYear;\n\ttraffic.month = current_time.wMonth;\n\ttraffic.day = current_time.wDay;\n\ttraffic.up_kBytes = 0;\n\ttraffic.down_kBytes = 0;\n\ttraffic.mixed = false;\n\n\tif (m_history_traffics.empty())\n\t{\n\t\tm_history_traffics.push_front(traffic);\n\t}\n\n\tif (m_history_traffics.size() >= 2)\n\t{\n\t\t//ȡʷбڴӴС\n\t\tstd::sort(m_history_traffics.begin(), m_history_traffics.end(), HistoryTraffic::DateGreater);\n\n\t\t//бͬڵĿϲ\n\t\tfor (int i{}; i < static_cast<int>(m_history_traffics.size() - 1); i++)\n\t\t{\n\t\t\tif (HistoryTraffic::DateEqual(m_history_traffics[i], m_history_traffics[i + 1]))\n\t\t\t{\n\t\t\t\tm_history_traffics[i].up_kBytes += m_history_traffics[i + 1].up_kBytes;\n\t\t\t\tm_history_traffics[i].down_kBytes += m_history_traffics[i + 1].down_kBytes;\n\t\t\t\tm_history_traffics.erase(m_history_traffics.begin() + i + 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t//бһĿǽ죬򽫵һĿͳƵΪʹõбǰһΪĿ\n\tif (HistoryTraffic::DateEqual(m_history_traffics[0], traffic))\n\t{\n\t\tm_today_up_traffic = static_cast<__int64>(m_history_traffics[0].up_kBytes) * 1024;\n\t\tm_today_down_traffic = static_cast<__int64>(m_history_traffics[0].down_kBytes) * 1024;\n\t\tm_history_traffics[0].mixed = false;\n\t}\n\telse\n\t{\n\t\tm_history_traffics.push_front(traffic);\n\t}\n\tm_size = m_history_traffics.size();\n}\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficFile.h",
    "content": "#pragma once\n#include \"CommonData.h\"\nclass CHistoryTrafficFile\n{\npublic:\n\tCHistoryTrafficFile(const wstring& file_path);\n\t~CHistoryTrafficFile();\n\n\tvoid Save() const;\n\tvoid Load();\n\tvoid LoadSize();\t\t\t//ȡļĴС\n\tvoid Merge(const CHistoryTrafficFile& history_traffic, bool ignore_same_data = false);\t\t//ϲһCHistoryTrafficFileignore_same_dataΪtrueͬڵͬڵ\n\n\tconst wstring& GetFilePath() const { return m_file_path; }\n\tconst void SetFilePath(const wstring& file_path) { m_file_path = file_path; }\n\tdeque<HistoryTraffic>& GetTraffics() { return m_history_traffics; }\n\t__int64 GetTodayUpTraffic() const { return m_today_up_traffic; }\n\t__int64 GetTodayDownTraffic() const { return m_today_down_traffic; }\n\tsize_t Size() { return m_size; }\n\nprivate:\n\tvoid MormalizeData();\t\t//ʷ򲢺ϲͬ\n\nprivate:\n\twstring m_file_path;\n\tdeque<HistoryTraffic> m_history_traffics;\t//ʷ\n\t__int64 m_today_up_traffic{};\t//ʹõϴ\n\t__int64 m_today_down_traffic{};\t//ʹõ\n\tsize_t m_size{};\t\t\t\t//ݵ\n};\n\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficListCtrl.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"HistoryTrafficListCtrl.h\"\n\nIMPLEMENT_DYNAMIC(CHistoryTrafficListCtrl, CListCtrl)\n\nCHistoryTrafficListCtrl::CHistoryTrafficListCtrl()\n{\n}\n\n\nCHistoryTrafficListCtrl::~CHistoryTrafficListCtrl()\n{\n}\nvoid CHistoryTrafficListCtrl::SetDrawItemRangeData(int item, double range, COLORREF color)\n{\n\tif (item < 0) return;\n\tif (item >= static_cast<int>(m_item_rage_data.size()))\n\t\tm_item_rage_data.resize(item + 1);\n\tm_item_rage_data[item].data_value = range;\n\tm_item_rage_data[item].color = color;\n}\n\nvoid CHistoryTrafficListCtrl::SetDrawItemRangInLogScale(bool log_scale)\n{\n\tm_use_log_scale = log_scale;\n\tInvalidate();\n}\n\nBEGIN_MESSAGE_MAP(CHistoryTrafficListCtrl, CListCtrl)\n\tON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CHistoryTrafficListCtrl::OnNMCustomdraw)\nEND_MESSAGE_MAP()\n\n\nvoid CHistoryTrafficListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)\n{\n\tif (m_draw_item_range)\n\t{\n\t\t*pResult = CDRF_DODEFAULT;\n\t\tLPNMLVCUSTOMDRAW lplvdr = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);\n\t\tNMCUSTOMDRAW& nmcd = lplvdr->nmcd;\n\t\tswitch (lplvdr->nmcd.dwDrawStage)\t//判断状态   \n\t\t{\n\t\tcase CDDS_PREPAINT:\n\t\t\t*pResult = CDRF_NOTIFYITEMDRAW;\n\t\t\tbreak;\n\t\tcase CDDS_ITEMPREPAINT:\t\t\t//如果为画ITEM之前就要进行颜色的改变\n\t\t\tif (nmcd.dwItemSpec >= 0 && nmcd.dwItemSpec < m_item_rage_data.size())\n\t\t\t{\n\t\t\t\tdouble range = m_item_rage_data[nmcd.dwItemSpec].data_value;\n\t\t\t\tCDC* pDC = CDC::FromHandle(nmcd.hdc);\t\t//获取绘图DC\n\t\t\t\tCRect item_rect, draw_rect;\n\t\t\t\tGetSubItemRect(nmcd.dwItemSpec,m_draw_item_range_row, LVIR_BOUNDS, item_rect);\t//获取绘图单元格的矩形区域\n\t\t\t\tCDrawCommon::SetDrawRect(pDC, item_rect);\t\t//设置绘图区域为当前列\n                //使用双缓冲绘图\n                {\n                    CDrawDoubleBuffer draw_double_buffer(pDC, item_rect);\n                    //填充背景\n                    draw_rect = item_rect;\n                    draw_rect.MoveToXY(0, 0);\n                    draw_double_buffer.GetMemDC()->FillSolidRect(draw_rect, GetSysColor(COLOR_WINDOW));\n                    if (draw_rect.Height() > 2 * m_margin)\n                    {\n                        draw_rect.top += m_margin;\n                        draw_rect.bottom -= m_margin;\n                    }\n                    int width;\n                    if (m_use_log_scale)\t//使用对数比例（y=ln(x+1)）\n                    {\n                        range = std::log(range + 1);\n                        width = static_cast<int>(range*draw_rect.Width() / std::log(1000 + 1));\n                    }\n                    else\t\t//使用线性比例（y=x）\n                    {\n                        width = static_cast<int>(range*draw_rect.Width() / 1000);\n                    }\n                    draw_rect.right = draw_rect.left + width;\n                    draw_double_buffer.GetMemDC()->FillSolidRect(draw_rect, m_item_rage_data[nmcd.dwItemSpec].color);\n                }\n\n\t\t\t\t//当前列绘制完成后将绘图区域设置为左边的区域，防止当前列的区域被覆盖\n\t\t\t\tCRect rect1{ item_rect };\n\t\t\t\trect1.left = 0;\n\t\t\t\trect1.right = item_rect.left;\n\t\t\t\tCDrawCommon::SetDrawRect(pDC, rect1);\n\t\t\t}\n\t\t\t*pResult = CDRF_DODEFAULT;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficListCtrl.h",
    "content": "#pragma once\n#include \"afxcmn.h\"\n#include \"DrawCommon.h\"\nclass CHistoryTrafficListCtrl :\n\tpublic CListCtrl\n{\nDECLARE_DYNAMIC(CHistoryTrafficListCtrl)\npublic:\n\tCHistoryTrafficListCtrl();\n\t~CHistoryTrafficListCtrl();\n\n\tvoid EnableDrawItemRange(bool draw = true) { m_draw_item_range = draw; }\t//ǷҪĳһеԪлƱʾֵСľ\n\tvoid SetDrawItemRangeRow(int row) { m_draw_item_range_row = row; }\t\t\t//ҪƱʾֵСľεУעбΪұߵУ򣬴ұߵн޷ʾ\n\tvoid SetDrawItemRangeData(int item, double range, COLORREF color);\t\t\t//ĳһеĿݴСȡֵΪ1~1000ɫ\n\tvoid SetDrawItemRangMargin(int margin) { m_margin = margin; }\t\t\t//ûƻƵľεıԵԪ߿ľΣֵԽƵľԽϸǲܳбоһ\n\tvoid SetDrawItemRangInLogScale(bool log_scale);\t\t\t\t//ҪƱʾֵСľʱǷʹöʹԱ\n\nprotected:\n\tstruct ItemData\n\t{\n\t\tdouble data_value;\t\t//ҪƵľαʾֵСΧΪ0~1000\n\t\tCOLORREF color;\t\t//ҪƵľεɫ\n\t};\n\tbool m_draw_item_range{ false };\t\t//ǷҪĳһеԪлƱʾֵСľ\n\tint m_draw_item_range_row{};\t\t//ҪƱʾֵСľε\n\tint m_margin{};\n\tvector<ItemData> m_item_rage_data;\t//ڱʾÿһҪƵݴСͻͼɫ\n\tbool m_use_log_scale{ false };\t\t//ΪtrueʹöƾΣʹԱ\n\n\tDECLARE_MESSAGE_MAP()\n\tafx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);\n};\n\n"
  },
  {
    "path": "TrafficMonitor/HistoryTrafficListDlg.cpp",
    "content": "﻿// HistoryTrafficList.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"HistoryTrafficListDlg.h\"\n#include \"afxdialogex.h\"\n#include \"CalendarHelper.h\"\n\n\n// CHistoryTrafficListDlgDlg 对话框\n\nIMPLEMENT_DYNAMIC(CHistoryTrafficListDlg, CTabDlg)\n\nCHistoryTrafficListDlg::CHistoryTrafficListDlg(deque<HistoryTraffic>& history_traffics, CWnd* pParent /*=nullptr*/)\n\t: CTabDlg(IDD_HISTORY_TRAFFIC_LIST_DIALOG, pParent), m_history_traffics(history_traffics)\n{\n\n}\n\nCHistoryTrafficListDlg::~CHistoryTrafficListDlg()\n{\n}\n\n\nbool CHistoryTrafficListDlg::CalculateColumeWidth(std::vector<int>& widths)\n{\n    if (!IsWindow(m_history_list.GetSafeHwnd()))\n        return false;\n    CRect rect;\n    m_history_list.GetWindowRect(rect);\n    if (rect.Width() <= 0)\n        return false;\n    const int MAX_COLUME{ 5 };\n\tint width_date;\t\t//“日期”列的宽度\n    int width0;\t\t\t//“上传”、“下载”、“总流量”列的宽度\n    int width1;\t\t\t//“图表”列的宽度\n\twidth_date = rect.Width() * 3 / 11;\n    width0 = rect.Width() * 2 / 11;\n    if (width_date > theApp.DPI(150))\n\t\twidth_date = theApp.DPI(150);\n\tif (width0 > theApp.DPI(120))\n\t\twidth0 = theApp.DPI(120);\n    width1 = rect.Width() - (MAX_COLUME - 2) * width0 - width_date - theApp.DPI(20) - 1;\n    widths.resize(MAX_COLUME);\n\twidths[0] = width_date;\n    widths[1] = widths[2] = widths[3] = width0;\n    widths[4] = width1;\n    return true;\n}\n\nvoid CHistoryTrafficListDlg::AddListRow(const ListRowData& data, unsigned __int64 max_traffic)\n{\n    unsigned __int64 total_kbytes = data.up_kBytes + data.down_kBytes;\n    int index = m_history_list.GetItemCount();\n    m_history_list.InsertItem(index, data.str);\n    if (data.mixed)\n    {\n        m_history_list.SetItemText(index, 1, _T(\"-\"));\n        m_history_list.SetItemText(index, 2, _T(\"-\"));\n    }\n    else\n    {\n        m_history_list.SetItemText(index, 1, CCommon::KBytesToString(data.up_kBytes));\n        m_history_list.SetItemText(index, 2, CCommon::KBytesToString(data.down_kBytes));\n    }\n    m_history_list.SetItemText(index, 3, CCommon::KBytesToString(total_kbytes));\n\n    double range = static_cast<double>(total_kbytes) * 1000 / max_traffic;\n    COLORREF color;\n    if (total_kbytes < 1024 * 1024)\t\t//流量小于1GB时绘制蓝色\n        color = TRAFFIC_COLOR_BLUE;\n    else if (total_kbytes < 10 * 1024 * 1024)\t//流量小于10GB时绘制绿色\n        color = TRAFFIC_COLOR_GREEN;\n    else if (total_kbytes < 100 * 1024 * 1024)\t//流量小于100GB时绘制黄色\n        color = TRAFFIC_COLOR_YELLOE;\n    else if (total_kbytes < 1024 * 1024 * 1024)\t//流量小于1TB时绘制红色\n        color = TRAFFIC_COLOR_RED;\n    else\t\t//流量超过1TB时显示深红色\n        color = TRAFFIC_COLOR_DARK_RED;\n    m_history_list.SetDrawItemRangeData(index, range, color);\n}\n\nvoid CHistoryTrafficListDlg::ShowListData()\n{\n    m_history_list.DeleteAllItems();\n\n    //显示日视图\n    if(theApp.m_cfg_data.m_view_type == HistoryTrafficViewType::HV_DAY)\n    {\n        //获取历史流量列表中流量的最大值\n        unsigned __int64 max_traffic{};\n        for (const auto& traffic : m_history_traffics)\n        {\n            if (traffic.kBytes() > max_traffic)\n                max_traffic = traffic.kBytes();\n        }\n\n        for (size_t i{}; i < m_history_traffics.size(); i++)\n        {\n            CString date_str;\n            //CString k_bytes_str;\n            date_str.Format(_T(\"%.4d/%.2d/%.2d (\"), m_history_traffics[i].year, m_history_traffics[i].month, m_history_traffics[i].day);\n\n            int week_day = CCalendarHelper::CaculateWeekDay(m_history_traffics[i].year, m_history_traffics[i].month, m_history_traffics[i].day);\n            switch (week_day)\n            {\n            case 0:\n                date_str += CCommon::LoadText(IDS_SUNDAY);\n                break;\n            case 1:\n                date_str += CCommon::LoadText(IDS_MONDAY);\n                break;\n            case 2:\n                date_str += CCommon::LoadText(IDS_TUESDAY);\n                break;\n            case 3:\n                date_str += CCommon::LoadText(IDS_WEDNESDAY);\n                break;\n            case 4:\n                date_str += CCommon::LoadText(IDS_THURSDAY);\n                break;\n            case 5:\n                date_str += CCommon::LoadText(IDS_FRIDAY);\n                break;\n            case 6:\n                date_str += CCommon::LoadText(IDS_SATURDAY);\n                break;\n            default:\n                break;\n            }\n            date_str += _T(')');\n\n            ListRowData data;\n            data.str = date_str;\n            data.up_kBytes = m_history_traffics[i].up_kBytes;\n            data.down_kBytes = m_history_traffics[i].down_kBytes;\n            data.mixed = m_history_traffics[i].mixed;\n            AddListRow(data, max_traffic);\n        }\n    }\n\n    //显示月/季/年视图\n    else\n    {\n        std::vector<ListRowData> list_data;\n        unsigned __int64 max_traffic{};\n        for (const auto& traffic : m_history_traffics)\n        {\n            CString date_str;\n            if (theApp.m_cfg_data.m_view_type == HistoryTrafficViewType::HV_WEEK)\n            {\n                date_str.Format(_T(\"%.4d/\"), traffic.year);\n                date_str += CCommon::LoadTextFormat(IDS_WEEK_NUM, { traffic.week() });\n            }\n            else if (theApp.m_cfg_data.m_view_type == HistoryTrafficViewType::HV_MONTH)      //月视图\n            {\n                date_str.Format(_T(\"%.4d/%.2d\"), traffic.year, traffic.month);\n            }\n            else if (theApp.m_cfg_data.m_view_type == HistoryTrafficViewType::HV_QUARTER)   //季视图\n            {\n                date_str.Format(_T(\"%.4d/\"), traffic.year);\n                if (traffic.month <= 3)\n                    date_str += _T(\"Q1\");\n                else if (traffic.month <= 6)\n                    date_str += _T(\"Q2\");\n                else if (traffic.month <= 9)\n                    date_str += _T(\"Q3\");\n                else\n                    date_str += _T(\"Q4\");\n            }\n            else    //年视图\n            {\n                date_str.Format(_T(\"%.4d\"), traffic.year);\n            }\n            if (list_data.empty() || list_data.back().str != date_str)\n            {\n                if(!list_data.empty())\n                {\n                    unsigned __int64 cur_traffic{ list_data.back().up_kBytes + list_data.back().down_kBytes };\n                    if (cur_traffic > max_traffic)\n                        max_traffic = cur_traffic;\n                }\n                ListRowData data;\n                data.str = date_str;\n                data.up_kBytes = traffic.up_kBytes;\n                data.down_kBytes = traffic.down_kBytes;\n                list_data.push_back(data);\n            }\n            else\n            {\n                list_data.back().up_kBytes += traffic.up_kBytes;\n                list_data.back().down_kBytes += traffic.down_kBytes;\n            }\n        }\n\n        for (const auto& data : list_data)\n        {\n            AddListRow(data, max_traffic);\n        }\n    }\n}\n\nvoid CHistoryTrafficListDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CTabDlg::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_HISTORY_INFO_LIST, m_history_list);\n    DDX_Control(pDX, IDC_VIEW_TYPE_COMBO, m_view_type_combo);\n    DDX_Control(pDX, IDC_VIEW_SCALE_COMBO, m_view_scale_combo);\n}\n\n\nBEGIN_MESSAGE_MAP(CHistoryTrafficListDlg, CTabDlg)\n\tON_WM_INITMENU()\n\tON_COMMAND(ID_USE_LINEAR_SCALE, &CHistoryTrafficListDlg::OnUseLinearScale)\n\tON_COMMAND(ID_USE_LOG_SCALE, &CHistoryTrafficListDlg::OnUseLogScale)\n    ON_WM_SIZE()\n    ON_CBN_SELCHANGE(IDC_VIEW_TYPE_COMBO, &CHistoryTrafficListDlg::OnCbnSelchangeViewTypeCombo)\n    ON_CBN_SELCHANGE(IDC_VIEW_SCALE_COMBO, &CHistoryTrafficListDlg::OnCbnSelchangeViewScaleCombo)\nEND_MESSAGE_MAP()\n\n\n// CHistoryTrafficListDlgDlg 消息处理程序\n\n\nBOOL CHistoryTrafficListDlg::OnInitDialog()\n{\n\tCTabDlg::OnInitDialog();\n\n\t// TODO:  在此添加额外的初始化\n\n\t//初始化列表控件\n\tm_history_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);\n    std::vector<int> widths;\n    CalculateColumeWidth(widths);\n    m_history_list.InsertColumn(0, CCommon::LoadText(IDS_DATE), LVCFMT_LEFT, widths[0]);\n\tm_history_list.InsertColumn(1, CCommon::LoadText(IDS_UPLOAD), LVCFMT_RIGHT, widths[1]);\n\tm_history_list.InsertColumn(2, CCommon::LoadText(IDS_DOWNLOAD), LVCFMT_RIGHT, widths[2]);\n\tm_history_list.InsertColumn(3, CCommon::LoadText(IDS_TRAFFIC_USED), LVCFMT_RIGHT, widths[3]);\n\tm_history_list.InsertColumn(4, CCommon::LoadText(IDS_FIGURE), LVCFMT_LEFT, widths[4]);\n\n    m_history_list.EnableDrawItemRange();\n    m_history_list.SetDrawItemRangeRow(4);\n    m_history_list.SetDrawItemRangMargin(theApp.DPI(4));\n    m_history_list.SetDrawItemRangInLogScale(theApp.m_cfg_data.m_use_log_scale);\n\n    //初始化控件\n    m_view_type_combo.AddString(CCommon::LoadText(IDS_DAY_VIEW));\n    m_view_type_combo.AddString(CCommon::LoadText(IDS_WEEK_VIEW));\n    m_view_type_combo.AddString(CCommon::LoadText(IDS_MONTH_VIEW));\n    m_view_type_combo.AddString(CCommon::LoadText(IDS_QUARTER_VIEW));\n    m_view_type_combo.AddString(CCommon::LoadText(IDS_YEAR_VIEW));\n    m_view_type_combo.SetCurSel(static_cast<int>(theApp.m_cfg_data.m_view_type));\n\n    m_view_scale_combo.AddString(CCommon::LoadText(IDS_LINEAR_SCALE));\n    m_view_scale_combo.AddString(CCommon::LoadText(IDS_LOG_SCALE));\n    m_view_scale_combo.SetCurSel(theApp.m_cfg_data.m_use_log_scale ? 1 : 0);\n\n    //显示列表数据\n    ShowListData();\n\n    CCommon::LoadMenuResource(m_menu, IDR_HISTORY_TRAFFIC_MENU);\n\n\treturn TRUE;  // return TRUE unless you set the focus to a control\n\t\t\t\t  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nBOOL CHistoryTrafficListDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)\n{\n\t// TODO: 在此添加专用代码和/或调用基类\n\n\tLPNMHDR lpnmhdr = (LPNMHDR)lParam;\n\tif (lpnmhdr->code == NM_RCLICK)\n\t{\n\t\tCPoint point;\n\t\tGetCursorPos(&point);//获得光标的位置\n\t\tm_history_list.ScreenToClient(&point);//获得list控件在窗口上的坐标\n\t\tCWnd* pWnd = m_history_list.ChildWindowFromPoint(point);\n\t\tCHeaderCtrl* pHeader = m_history_list.GetHeaderCtrl();//获取列表视图控件的标题控件\n\t\tCRect item_rect;\n\t\tpHeader->GetItemRect(4, item_rect);\t\t//获取列表标题控件第2列的矩形区域，只有光标在第4列点击时才弹出右键菜单\n\t\tif (pWnd && (pWnd->GetSafeHwnd() == pHeader->GetSafeHwnd()) && item_rect.PtInRect(point))\n\t\t{\n\t\t\tHDHITTESTINFO info{};\n\t\t\tinfo.pt = point;\n\t\t\tpHeader->SendMessage(HDM_HITTEST, 0, (LPARAM)&info);\n\t\t\tCMenu * pMenu = m_menu.GetSubMenu(0);\n\t\t\tGetCursorPos(&point);\n\t\t\tpMenu->TrackPopupMenu(TPM_RIGHTBUTTON, point.x, point.y, this);\n\t\t}\n\t}\n\treturn CTabDlg::OnNotify(wParam, lParam, pResult);\n}\n\n\nvoid CHistoryTrafficListDlg::OnInitMenu(CMenu* pMenu)\n{\n\tCTabDlg::OnInitMenu(pMenu);\n\n\t// TODO: 在此处添加消息处理程序代码\n\tif (theApp.m_cfg_data.m_use_log_scale)\n\t\tpMenu->CheckMenuRadioItem(ID_USE_LINEAR_SCALE, ID_USE_LOG_SCALE, ID_USE_LOG_SCALE, MF_BYCOMMAND | MF_CHECKED);\n\telse\n\t\tpMenu->CheckMenuRadioItem(ID_USE_LINEAR_SCALE, ID_USE_LOG_SCALE, ID_USE_LINEAR_SCALE, MF_BYCOMMAND | MF_CHECKED);\n}\n\n\nvoid CHistoryTrafficListDlg::OnUseLinearScale()\n{\n\t// TODO: 在此添加命令处理程序代码\n\ttheApp.m_cfg_data.m_use_log_scale = false;\n\tm_history_list.SetDrawItemRangInLogScale(theApp.m_cfg_data.m_use_log_scale);\n}\n\n\nvoid CHistoryTrafficListDlg::OnUseLogScale()\n{\n\t// TODO: 在此添加命令处理程序代码\n\ttheApp.m_cfg_data.m_use_log_scale = true;\n\tm_history_list.SetDrawItemRangInLogScale(theApp.m_cfg_data.m_use_log_scale);\n}\n\n\nvoid CHistoryTrafficListDlg::OnSize(UINT nType, int cx, int cy)\n{\n    CTabDlg::OnSize(nType, cx, cy);\n\n    // TODO: 在此处添加消息处理程序代码\n    if (nType != SIZE_MINIMIZED)\n    {\n        std::vector<int> widths;\n        if(CalculateColumeWidth(widths))\n        {\n            for (size_t i{}; i < widths.size(); i++)\n            {\n                m_history_list.SetColumnWidth(i, widths[i]);\n            }\n        }\n    }\n}\n\n\nvoid CHistoryTrafficListDlg::OnCbnSelchangeViewTypeCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    theApp.m_cfg_data.m_view_type = static_cast<HistoryTrafficViewType>(m_view_type_combo.GetCurSel());\n    ShowListData();\n}\n\n\nvoid CHistoryTrafficListDlg::OnCbnSelchangeViewScaleCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    theApp.m_cfg_data.m_use_log_scale = (m_view_scale_combo.GetCurSel() != 0);\n    m_history_list.SetDrawItemRangInLogScale(theApp.m_cfg_data.m_use_log_scale);\n}\n"
  },
  {
    "path": "TrafficMonitor/IDrawCommon.h",
    "content": "﻿#pragma once\n#include \"CommonData.h\"\n\nclass IDrawBuffer\n{\npublic:\n    virtual ~IDrawBuffer() = default;\n};\n\nclass IDrawCommon\n{\npublic:\n    // 拉伸模式\n    enum class StretchMode\n    {\n        STRETCH, // 拉伸，会改变比例\n        FILL,    // 填充，不改变比例，会裁剪长边\n        FIT      // 适应，不会改变比例，不裁剪\n    };\n\n    //对齐方式\n    enum class Alignment\n    {\n        LEFT,       //左对齐\n        RIGHT,      //右对齐\n        CENTER,     //居中\n    };\n\n    virtual void SetBackColor(COLORREF back_color, BYTE alpha = 255) = 0;\n    // 设置绘制文本的字体\n    virtual void SetFont(CFont* pfont) = 0;\n    // 在指定的矩形区域内绘制文本\n    virtual void DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align = Alignment::LEFT, bool draw_back_ground = false, bool multi_line = false, BYTE alpha = 255) = 0;\n    // 设置绘图剪辑区域\n    virtual void SetDrawRect(CRect rect) = 0;\n    // 用纯色填充矩形\n    virtual void FillRect(CRect rect, COLORREF color, BYTE alpha = 255) = 0;\n    // 绘制矩形边框。如果dot_line为true，则为虚线\n    virtual void DrawRectOutLine(CRect rect, COLORREF color, int width = 1, bool dot_line = false, BYTE alpha = 255) = 0;\n    // 使用当前画笔画线\n    virtual void DrawLine(CPoint start_point, int height, COLORREF color, BYTE alpha = 255) = 0;\n    virtual void SetTextColor(const COLORREF color, BYTE alpha = 255) = 0;\n    // 绘制一个位图\n    // （注意：当stretch_mode设置为StretchMode::FILL（填充）时，会设置绘图剪辑区域，如果之后需要绘制其他图形，\n    // 需要重新设置绘图剪辑区域，否则图片外的区域会无法绘制）\n    virtual void DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode = StretchMode::STRETCH, BYTE alpha = 255) = 0;\n    virtual ~IDrawCommon() = default;\n\n    //获取绘图上下文句柄。仅在GDI或GDI+时有效\n    virtual CDC* GetDC() { return nullptr; }\n    //获取文本宽度\n    virtual int GetTextWidth(LPCTSTR lpszString) { return 0; }\n};\n\nnamespace DrawCommonHelper\n{\n    /**\n     * @brief 渲染器类型的枚举，新增渲染器类型时应当添加枚举到其中\n     *\n     */\n    enum class RenderType\n    {\n        // 使用GDI\n        DEFAULT,\n        // 如果支持，使用D2D1\n        D2D1,\n        // 如果系统大于win8.1，则在使用D2D1时利用DirectComposition呈现结果\n        D2D1_WITH_DCOMPOSITION\n    };\n\n    constexpr BYTE GDI_NO_MODIFIED_FLAG = 0x01;\n    constexpr BYTE OPAQUE_ALPHA_VALUE = 0xFF;\n    constexpr BYTE TRANSPARENT_ALPHA_VALUE = 0x00;\n    constexpr BYTE AVAILABLE_MINIMUM_ALPHA = 0x02;\n    constexpr BYTE GDI_MODIFIED_FLAG = 0x00;\n}\n\ntemplate <class... Ts>\nclass AlignedUnionStorage\n{\nprivate:\n    alignas(Ts...) std::byte m_buffer[(std::max)({sizeof(Ts)...})]{};\n\npublic:\n    AlignedUnionStorage() = default;\n    ~AlignedUnionStorage() = default;\n    std::byte* operator&() noexcept\n    {\n        return m_buffer;\n    }\n};\n"
  },
  {
    "path": "TrafficMonitor/IconSelectDlg.cpp",
    "content": "﻿// IconSelectDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"IconSelectDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// CIconSelectDlg 对话框\n\nIMPLEMENT_DYNAMIC(CIconSelectDlg, CBaseDialog)\n\nCIconSelectDlg::CIconSelectDlg(int icon_selected, CWnd* pParent /*=NULL*/)\n    : CBaseDialog(IDD_ICON_SELECT_DIALOG, pParent), m_icon_selected{ icon_selected }\n{\n\n}\n\nCIconSelectDlg::~CIconSelectDlg()\n{\n}\n\nint CIconSelectDlg::GetIconSelected() const\n{\n    if (m_icon_selected < 0 || m_icon_selected >= MAX_NOTIFY_ICON)\n        return 0;\n    return m_icon_selected;\n}\n\nvoid CIconSelectDlg::SetAutoAdaptNotifyIcon(bool val)\n{\n    m_atuo_adapt_notify_icon = val;\n}\n\nbool CIconSelectDlg::AutoAdaptNotifyIcon() const\n{\n    return m_atuo_adapt_notify_icon;\n}\n\nvoid CIconSelectDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_ICON_PREVIEW, m_preview_pic);\n    DDX_Control(pDX, IDC_COMBO1, m_icon_select_combo);\n    DDX_Control(pDX, IDC_AUTO_ADAPT_CHECK, m_auto_adapt_chk);\n}\n\nvoid CIconSelectDlg::DrawPreviewIcon(CDC* pDC)\n{\n    //pDC->FillSolidRect(CRect(CPoint(ICON_X, ICON_Y), CSize(theApp.DPI(16), theApp.DPI(16))), RGB(0, 0, 0));\n    //pDC->DrawIcon(ICON_X, ICON_Y, m_icons[m_icon_selected]);\n    ::DrawIconEx(pDC->m_hDC, ICON_X, ICON_Y, theApp.m_notify_icons[GetIconSelected()], theApp.DPI(16), theApp.DPI(16), 0, NULL, DI_NORMAL);\n}\n\n\nBEGIN_MESSAGE_MAP(CIconSelectDlg, CBaseDialog)\n    //ON_WM_TIMER()\n    ON_CBN_SELCHANGE(IDC_COMBO1, &CIconSelectDlg::OnCbnSelchangeCombo1)\n    ON_MESSAGE(WM_CONTROL_REPAINT, &CIconSelectDlg::OnControlRepaint)\n    ON_BN_CLICKED(IDC_AUTO_ADAPT_CHECK, &CIconSelectDlg::OnBnClickedAutoAdaptCheck)\nEND_MESSAGE_MAP()\n\n\n// CIconSelectDlg 消息处理程序\n\n\nBOOL CIconSelectDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_NOTIFY), FALSE);\t\t// 设置小图标\n\n    //设置预览图大小\n    m_preview_pic.SetWindowPos(nullptr, 0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT, SWP_NOZORDER | SWP_NOMOVE);\n    if (m_icon_selected == 4 || m_icon_selected == 5)\n        m_preview_pic.SetPicture((HBITMAP)LoadImage(AfxGetInstanceHandle(),\n            MAKEINTRESOURCE(IDB_NOTIFY_ICON_PREVIEW_LIGHT), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION));\n    else\n        m_preview_pic.SetPicture((HBITMAP)LoadImage(AfxGetInstanceHandle(),\n            MAKEINTRESOURCE(IDB_NOTIFY_ICON_PREVIEW), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION));\n\n    //初始化下拉列表\n    m_icon_select_combo.AddString(CCommon::LoadText(IDS_DEFAULT_ICON));\n    m_icon_select_combo.AddString(CCommon::LoadText(IDS_ICON, _T(\" 1\")));\n    m_icon_select_combo.AddString(CCommon::LoadText(IDS_ICON, _T(\" 2\")));\n    m_icon_select_combo.AddString(CCommon::LoadText(IDS_ICON, _T(\" 3\")));\n    m_icon_select_combo.AddString(CCommon::LoadText(IDS_ICON, _T(\" 4\")));\n    m_icon_select_combo.AddString(CCommon::LoadText(IDS_ICON, _T(\" 5\")));\n    m_icon_select_combo.SetCurSel(m_icon_selected);\n\n    m_auto_adapt_chk.SetCheck(m_atuo_adapt_notify_icon);\n    m_auto_adapt_chk.EnableWindow(theApp.m_win_version.GetMajorVersion() >= 10);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CIconSelectDlg::OnCbnSelchangeCombo1()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_icon_selected = m_icon_select_combo.GetCurSel();\n    if (m_icon_selected == 4 || m_icon_selected == 5)\n        m_preview_pic.SetPicture((HBITMAP)LoadImage(AfxGetInstanceHandle(),\n            MAKEINTRESOURCE(IDB_NOTIFY_ICON_PREVIEW_LIGHT), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION));\n    else\n        m_preview_pic.SetPicture((HBITMAP)LoadImage(AfxGetInstanceHandle(),\n            MAKEINTRESOURCE(IDB_NOTIFY_ICON_PREVIEW), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION));\n    DrawPreviewIcon(m_preview_pic.GetDC());\n}\n\n\nafx_msg LRESULT CIconSelectDlg::OnControlRepaint(WPARAM wParam, LPARAM lParam)\n{\n    CWnd* pControl = (CWnd*)wParam;\n    CDC* pDC = (CDC*)lParam;\n    if (pControl == &m_preview_pic)\n    {\n        //当收到m_preview_pic控件的重绘消息时，同时重绘图标\n        DrawPreviewIcon(pDC);\n    }\n    return 0;\n}\n\n\nvoid CIconSelectDlg::OnBnClickedAutoAdaptCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_atuo_adapt_notify_icon = (m_auto_adapt_chk.GetCheck() != 0);\n}\n\nCString CIconSelectDlg::GetDialogName() const\n{\n    return _T(\"IconSelectDlg\");\n}\n\nbool CIconSelectDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_SELECT_ICON_STATIC },\n        { CtrlTextInfo::C0, IDC_COMBO1 }\n    });\n    return true;\n}\n"
  },
  {
    "path": "TrafficMonitor/IconSelectDlg.h",
    "content": "﻿#pragma once\n#include \"afxwin.h\"\n#include \"PictureStatic.h\"\n#include \"BaseDialog.h\"\n\n// CIconSelectDlg 对话框\n\nclass CIconSelectDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CIconSelectDlg)\n\npublic:\n    CIconSelectDlg(int icon_selected, CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~CIconSelectDlg();\n\n    int GetIconSelected() const;\n\n    void SetAutoAdaptNotifyIcon(bool val);\n    bool AutoAdaptNotifyIcon() const;\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_ICON_SELECT_DIALOG };\n#endif\n\n#define PREVIEW_WIDTH theApp.DPI(200)\t\t//预览图的宽高\n#define PREVIEW_HEIGHT theApp.DPI(40)\n\n#define ICON_X theApp.DPI(46)\t\t//预览图中图标的位置\n#define ICON_Y theApp.DPI(12)\n\nprotected:\n    CPictureStatic m_preview_pic;\n    CComboBox m_icon_select_combo;\n    CButton m_auto_adapt_chk;\n\n    int m_icon_selected{};\n\n    bool m_atuo_adapt_notify_icon;\n\nprotected:\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    virtual CString GetDialogName() const override;\n    virtual bool InitializeControls() override;\n\n    void DrawPreviewIcon(CDC* pDC);\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    //afx_msg void OnTimer(UINT_PTR nIDEvent);\n    afx_msg void OnCbnSelchangeCombo1();\nprotected:\n    afx_msg LRESULT OnControlRepaint(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnBnClickedAutoAdaptCheck();\n};\n"
  },
  {
    "path": "TrafficMonitor/Image2DEffect.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"Image2DEffect.h\"\n#include \"Common.h\"\n\nnamespace D3DQuadrangle\n{\n    const std::array<std::uint16_t, 6> VERTEX_INDEX_LIST{\n        0, 1, 2,\n        2, 3, 0};\n\n    const CShader& GetVsShader()\n    {\n        static auto result = MakeStaticVariableWrapper<CShader>(\n            [](CShader* p_content)\n            {\n                p_content->SetCode(\n                             CIMAGE2DEFFECT_SHADER_VS_INPUT_DECLARATION\n                                 CIMAGE2DEFFECT_SHADER_VS_OUTPUT_DECLARATION\n                             R\"(\nVsOutput VS(VsInput input){\n   VsOutput result;\n   result.position = input.position;\n   result.texcoord = input.texcoord;\n   return result;\n}\n)\")\n                    .SetEntryPoint(\"VS\")\n                    .SetName(\"D3DQuadrangleDefaultVS\")\n                    .SetTarget(\"vs_4_1\")\n                    .SetFlags1(D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_WARNINGS_ARE_ERRORS);\n            });\n        return result.Get();\n    }\n\n}\n\nCImage2DEffect::CImage2DEffect(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1)\n    : m_p_owner_device1{p_device1}\n{\n    RecreateUnmodifiableResource(m_p_owner_device1);\n    RecreateVsByteCodeRelatedResources(m_p_vs_byte_code);\n}\n\nvoid CImage2DEffect::RecreateUnmodifiableResource(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1)\n{\n    constexpr static std::array<D3D10_INPUT_ELEMENT_DESC, 2> input_elements_desc{\n        {{\"POSITION\",\n          0,\n          DXGI_FORMAT_R32G32B32_FLOAT,\n          SLOT,\n          offsetof(Image2DVertex, position),\n          D3D10_INPUT_PER_VERTEX_DATA,\n          0},\n         {\"TEXCOORD\",\n          0,\n          DXGI_FORMAT_R32G32_FLOAT,\n          SLOT,\n          offsetof(Image2DVertex, texture0),\n          D3D10_INPUT_PER_VERTEX_DATA,\n          0}}};\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateInputLayout(\n            input_elements_desc.data(),\n            static_cast<UINT>(input_elements_desc.size()),\n            m_p_vs_byte_code->GetBufferPointer(),\n            m_p_vs_byte_code->GetBufferSize(),\n            &m_p_input_layout),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect call CreateInputLayout failed.\"));\n\n    QuadrangleVertexs vertexes;\n    float* vertex_position;\n    float* vertex_texture;\n\n    // 左上角\n    vertex_position = vertexes.GetLeftTopVertex().position;\n    vertex_position[0] = -1.f; // x\n    vertex_position[1] = 1.f;  // y\n    vertex_position[2] = .0f;  // z\n    vertex_texture = vertexes.GetLeftTopVertex().texture0;\n    vertex_texture[0] = 0.f; // u\n    vertex_texture[1] = 0.f; // v\n\n    // 右上角\n    vertex_position = vertexes.GetRightTopVertex().position;\n    vertex_position[0] = 1.f;\n    vertex_position[1] = 1.f;\n    vertex_position[2] = .0f;\n    vertex_texture = vertexes.GetRightTopVertex().texture0;\n    vertex_texture[0] = 1.f;\n    vertex_texture[1] = 0.f;\n\n    // 右下角\n    vertex_position = vertexes.GetRightBottomVertex().position;\n    vertex_position[0] = 1.f;\n    vertex_position[1] = -1.f;\n    vertex_position[2] = .0f;\n    vertex_texture = vertexes.GetRightBottomVertex().texture0;\n    vertex_texture[0] = 1.f;\n    vertex_texture[1] = 1.f;\n\n    // 左下角\n    vertex_position = vertexes.GetLeftBottomVertex().position;\n    vertex_position[0] = -1.f;\n    vertex_position[1] = -1.f;\n    vertex_position[2] = .0f;\n    vertex_texture = vertexes.GetLeftBottomVertex().texture0;\n    vertex_texture[0] = 0;\n    vertex_texture[1] = 1;\n\n    D3D10_BUFFER_DESC vertex_buffer_desc{};\n    vertex_buffer_desc.ByteWidth = static_cast<UINT>(vertexes.GetSize());\n    vertex_buffer_desc.Usage = D3D10_USAGE_IMMUTABLE;\n    vertex_buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;\n    D3D10_SUBRESOURCE_DATA vertex_data{};\n    vertex_data.pSysMem = vertexes.GetData();\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateBuffer(\n            &vertex_buffer_desc,\n            &vertex_data,\n            &m_p_vertex_buffer),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create vertex buffer failed.\"));\n\n    D3D10_BUFFER_DESC index_buffer_desc{};\n    index_buffer_desc.Usage = D3D10_USAGE_IMMUTABLE;\n    index_buffer_desc.ByteWidth = sizeof(D3DQuadrangle::VERTEX_INDEX_LIST);\n    index_buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;\n    D3D10_SUBRESOURCE_DATA index_data{};\n    index_data.pSysMem = &D3DQuadrangle::VERTEX_INDEX_LIST;\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateBuffer(\n            &index_buffer_desc,\n            &index_data,\n            &m_p_index_buffer),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create index buffer failed.\"));\n\n    D3D10_RASTERIZER_DESC rasterizer_desc{};\n    rasterizer_desc.FillMode = D3D10_FILL_SOLID;\n    rasterizer_desc.CullMode = D3D10_CULL_NONE;\n    rasterizer_desc.FrontCounterClockwise = FALSE;\n    rasterizer_desc.DepthBias = 0;\n    rasterizer_desc.DepthBiasClamp = 0.0f;\n    rasterizer_desc.SlopeScaledDepthBias = 0.0f;\n    rasterizer_desc.DepthClipEnable = FALSE;\n    rasterizer_desc.ScissorEnable = FALSE;\n    rasterizer_desc.MultisampleEnable = FALSE;\n    rasterizer_desc.AntialiasedLineEnable = FALSE;\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateRasterizerState(\n            &rasterizer_desc,\n            &m_p_rasterizer_state),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create rasterizer state failed.\"));\n\n    D3D10_SAMPLER_DESC tex0_sampler = {};\n    tex0_sampler.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;\n    tex0_sampler.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;\n    tex0_sampler.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;\n    tex0_sampler.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;\n    tex0_sampler.MipLODBias = 0.0f;\n    tex0_sampler.MaxAnisotropy = 1;\n    tex0_sampler.ComparisonFunc = D3D10_COMPARISON_NEVER;\n    tex0_sampler.MinLOD = -FLT_MAX;\n    tex0_sampler.MaxLOD = FLT_MAX;\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateSamplerState(\n            &tex0_sampler,\n            &m_p_ps_tex0_sampler_state),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create default sampler state failed.\"));\n\n    D3D10_BLEND_DESC1 blend_desc1{};\n    blend_desc1.AlphaToCoverageEnable = FALSE;\n    blend_desc1.IndependentBlendEnable = FALSE;\n    auto& render_target_blend_desc0 = blend_desc1.RenderTarget[0];\n    render_target_blend_desc0.BlendEnable = TRUE;\n    render_target_blend_desc0.SrcBlend = D3D10_BLEND_SRC_ALPHA;\n    render_target_blend_desc0.DestBlend = D3D10_BLEND_INV_DEST_ALPHA;\n    render_target_blend_desc0.BlendOp = D3D10_BLEND_OP_ADD;\n    render_target_blend_desc0.SrcBlendAlpha = D3D10_BLEND_ONE;\n    render_target_blend_desc0.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;\n    render_target_blend_desc0.BlendOpAlpha = D3D10_BLEND_OP_ADD;\n    render_target_blend_desc0.RenderTargetWriteMask = D3D10_COLOR_WRITE_ENABLE_ALL;\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateBlendState1(\n            &blend_desc1,\n            &m_p_blend_state1),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create D3D10.1 blend state for alpha blend failed.\"));\n\n    D3D10_DEPTH_STENCIL_DESC depth_stencil_desc{};\n    depth_stencil_desc.DepthEnable = FALSE;\n    depth_stencil_desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;\n    depth_stencil_desc.DepthFunc = D3D10_COMPARISON_LESS;\n    depth_stencil_desc.StencilEnable = FALSE;\n    depth_stencil_desc.StencilReadMask = 0xFF;\n    depth_stencil_desc.StencilWriteMask = 0xFF;\n    depth_stencil_desc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;\n    depth_stencil_desc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;\n    depth_stencil_desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;\n    depth_stencil_desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;\n    depth_stencil_desc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;\n    depth_stencil_desc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;\n    depth_stencil_desc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;\n    depth_stencil_desc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateDepthStencilState(\n            &depth_stencil_desc,\n            &m_p_depth_stencil_state),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect call CreateDepthStencilState failed.\"));\n}\n\nvoid CImage2DEffect::RecreateInputTextureRelatedResources(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_input)\n{\n    D3D10_SHADER_RESOURCE_VIEW_DESC tex0_shader_resource_view_desc = {};\n    tex0_shader_resource_view_desc.Format = PIXEL_FORMAT;\n    tex0_shader_resource_view_desc.ViewDimension = D3D10_1_SRV_DIMENSION_TEXTURE2D;\n    tex0_shader_resource_view_desc.Texture2D.MostDetailedMip = 0;\n    tex0_shader_resource_view_desc.Texture2D.MipLevels = 1;\n    ThrowIfFailed<CD3D10Exception1>(\n        m_p_owner_device1->CreateShaderResourceView(\n            p_input.Get(),\n            &tex0_shader_resource_view_desc,\n            &m_p_ps_tex0_resource_view),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create shader resource view1 failed.\"));\n}\n\nvoid CImage2DEffect::RecreateOutputTextureRelatedResources(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_output)\n{\n    ThrowIfFailed<CD3D10Exception1>(\n        m_p_owner_device1->CreateRenderTargetView(\n            p_output.Get(),\n            NULL,\n            &m_p_render_target_view),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create D3D10.1 render target view failed.\"));\n}\n\nvoid CImage2DEffect::RecreateVsByteCodeRelatedResources(Microsoft::WRL::ComPtr<ID3DBlob> p_vs_byte_code)\n{\n    ThrowIfFailed<CD3D10Exception1>(\n        m_p_owner_device1->CreateVertexShader(\n            p_vs_byte_code->GetBufferPointer(),\n            p_vs_byte_code->GetBufferSize(),\n            &m_p_vs),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create vertex shader failed.\"));\n}\n\nvoid CImage2DEffect::RecreatePsByteCodeRelatedResources(Microsoft::WRL::ComPtr<ID3DBlob> p_ps_byte_code)\n{\n    ThrowIfFailed<CD3D10Exception1>(\n        m_p_owner_device1->CreatePixelShader(\n            p_ps_byte_code->GetBufferPointer(),\n            p_ps_byte_code->GetBufferSize(),\n            &m_p_ps),\n        TRAFFICMONITOR_ERROR_STR(\"CImage2DEffect create pixel shader failed.\"));\n}\n\nauto CImage2DEffect::ApplyPipelineConfig() const\n    -> const CImage2DEffect&\n{\n    m_p_owner_device1->ClearState();\n\n    m_p_owner_device1->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);\n    m_p_owner_device1->IASetInputLayout(m_p_input_layout.Get());\n    auto raw_m_p_vertex_buffer = m_p_vertex_buffer.Get();\n    constexpr static std::array<UINT, 1> strides{static_cast<UINT>(QuadrangleVertexs::GetStride())};\n    constexpr static std::array<UINT, 1> offsets{0};\n    m_p_owner_device1->IASetVertexBuffers(\n        SLOT,\n        1,\n        &raw_m_p_vertex_buffer,\n        strides.data(),\n        offsets.data());\n    m_p_owner_device1->IASetIndexBuffer(\n        m_p_index_buffer.Get(),\n        DXGI_FORMAT_R16_UINT,\n        0);\n\n    m_p_owner_device1->VSSetShader(m_p_vs.Get());\n\n    D3D10_VIEWPORT viewport{};\n    viewport.Width = m_output_width;\n    viewport.Height = m_output_height;\n    viewport.MinDepth = 0.0f;\n    viewport.MaxDepth = 1.0f;\n    m_p_owner_device1->RSSetViewports(1, &viewport);\n    m_p_owner_device1->RSSetState(m_p_rasterizer_state.Get());\n\n    ID3D10SamplerState* raw_m_p_ps_tex0_sampler_state = m_p_ps_tex0_sampler_state.Get();\n    m_p_owner_device1->PSSetSamplers(\n        SLOT,\n        1,\n        &raw_m_p_ps_tex0_sampler_state);\n    auto raw_m_p_ps_tex0_resource_view = m_p_ps_tex0_resource_view.Get();\n    m_p_owner_device1->PSSetShaderResources(\n        SLOT,\n        1,\n        &raw_m_p_ps_tex0_resource_view);\n    m_p_owner_device1->PSSetShader(m_p_ps.Get());\n\n    m_p_owner_device1->OMSetBlendState(m_p_blend_state1.Get(), NULL, 0xffffffff);\n    m_p_owner_device1->OMSetDepthStencilState(m_p_depth_stencil_state.Get(), 0);\n    auto p_render_target_view = m_p_render_target_view.Get();\n    m_p_owner_device1->OMSetRenderTargets(1, &p_render_target_view, NULL);\n\n    return *this;\n}\n\nauto CImage2DEffect::RebindDevice1(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1)\n    -> CImage2DEffect&\n{\n    RecreateUnmodifiableResource(p_device1);\n    m_p_owner_device1 = p_device1;\n    m_p_input.Reset();\n    m_p_output.Reset();\n    if (m_p_vs_byte_code)\n    {\n        RecreateVsByteCodeRelatedResources(m_p_vs_byte_code);\n    }\n    if (m_p_ps_byte_code)\n    {\n        RecreatePsByteCodeRelatedResources(m_p_ps_byte_code);\n    }\n    return *this;\n}\n\nauto CImage2DEffect::SetOutputSize(UINT width, UINT height) noexcept\n    -> CImage2DEffect&\n{\n    m_output_width = width > 0 ? width : 1;\n    m_output_height = height > 0 ? height : 1;\n    return *this;\n}\n\nUINT CImage2DEffect::GetOutputWidth() const noexcept\n{\n    return m_output_width;\n}\n\nUINT CImage2DEffect::GetOutputHeight() const noexcept\n{\n    return m_output_height;\n}\n\nauto CImage2DEffect::SetInputTexture(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_input)\n    -> CImage2DEffect&\n{\n    if(m_p_input == p_input)\n    {\n        return *this;\n    }\n\n    RecreateInputTextureRelatedResources(p_input);\n    m_p_input = p_input;\n    return *this;\n}\n\nauto CImage2DEffect::GetInputTexture() noexcept\n    -> Microsoft::WRL::ComPtr<ID3D10Texture2D>\n{\n    return m_p_input;\n}\n\nauto CImage2DEffect::SetOutputTexture(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_output)\n    -> CImage2DEffect&\n{\n    if (m_p_output == p_output)\n    {\n        return *this;\n    }\n\n    RecreateOutputTextureRelatedResources(p_output);\n    m_p_output = p_output;\n    return *this;\n}\n\nauto CImage2DEffect::GetOutputTexture() noexcept\n    -> Microsoft::WRL::ComPtr<ID3D10Texture2D>\n{\n    return m_p_output;\n}\n\nauto CImage2DEffect::SetVsByteCode(Microsoft::WRL::ComPtr<ID3DBlob> p_vs_byte_code)\n    -> CImage2DEffect&\n{\n    RecreateVsByteCodeRelatedResources(p_vs_byte_code);\n    m_p_vs_byte_code = p_vs_byte_code;\n    return *this;\n}\n\nauto CImage2DEffect::GetVsByteCode() noexcept\n    -> Microsoft::WRL::ComPtr<ID3DBlob>\n{\n    return m_p_vs_byte_code;\n}\n\nauto CImage2DEffect::SetPsByteCode(Microsoft::WRL::ComPtr<ID3DBlob> p_ps_byte_code)\n    -> CImage2DEffect&\n{\n    RecreatePsByteCodeRelatedResources(p_ps_byte_code);\n    m_p_ps_byte_code = p_ps_byte_code;\n    return *this;\n}\n\nauto CImage2DEffect::GetPsByteCode() noexcept\n    -> Microsoft::WRL::ComPtr<ID3DBlob>\n{\n    return m_p_ps_byte_code;\n}\n\nauto CImage2DEffect::Draw() const\n    -> CD3D10DrawCallWaiter\n{\n    DrawOnly();\n    return CD3D10DrawCallWaiter{m_p_owner_device1};\n}\n\nvoid CImage2DEffect::DrawOnly() const noexcept\n{\n    constexpr auto index_count =\n        static_cast<UINT>(D3DQuadrangle::VERTEX_INDEX_LIST.size());\n    m_p_owner_device1->DrawIndexed(index_count, 0, 0);\n}\n\nauto CImage2DEffect::Clear(const std::array<FLOAT, 4>& color) const\n    -> CD3D10DrawCallWaiter\n{\n    ClearOnly(color);\n    return CD3D10DrawCallWaiter{m_p_owner_device1};\n}\n\nauto CImage2DEffect::ClearOnly(const std::array<FLOAT, 4>& color) const noexcept\n    -> const CImage2DEffect&\n{\n    m_p_owner_device1->ClearRenderTargetView(m_p_render_target_view.Get(), color.data());\n    return *this;\n}\n"
  },
  {
    "path": "TrafficMonitor/Image2DEffect.h",
    "content": "﻿#pragma once\n#include <cstddef>\n#include <array>\n#include \"D3D10Support1.h\"\n\nnamespace D3DQuadrangle\n{\n    extern const std::array<std::uint16_t, 6> VERTEX_INDEX_LIST;\n\n    const CShader& GetVsShader();\n\n    /**\n     * @brief 由三角形012和三角形132组成的四边形，顶点序号见VERTEX_INDEX_LIST\n     *\n     * @tparam Vertex 顶点类型\n     */\n    template <class Vertex>\n    struct QuadrangleVertexs\n    {\n        /**\n         * @brief 由三角形012和三角形123组成的四边形，下面是顶点排列顺序： \\n\n         * 1·--------------·2 \\n\n         *  |              |  \\n\n         *  |              |  \\n\n         * 0·--------------·3\n         */\n        std::array<Vertex, 4> vertexs{};\n\n        Vertex& GetLeftTopVertex() noexcept\n        {\n            return vertexs[1];\n        }\n        Vertex& GetRightTopVertex() noexcept\n        {\n            return vertexs[2];\n        }\n        Vertex& GetLeftBottomVertex() noexcept\n        {\n            return vertexs[0];\n        }\n        Vertex& GetRightBottomVertex() noexcept\n        {\n            return vertexs[3];\n        }\n        Vertex* GetData() noexcept\n        {\n            return vertexs.data();\n        }\n        static constexpr std::size_t GetSize() noexcept\n        {\n            return sizeof(vertexs);\n        }\n        static constexpr std::size_t GetStride() noexcept\n        {\n            return sizeof(Vertex);\n        }\n    };\n}\n\nstruct Image2DVertex\n{\n    float position[4];\n    float texture0[2];\n};\n\n/**\n * @brief 默认vertex shader的输入输出定义 \\n\n struct VsInput{                          \\n\n   float4 position : POSITION;            \\n\n   float2 texcoord : TEXCOORD;            \\n\n};                                        \\n\n                                          \\n\nstruct VsOutput{                          \\n\n   float4 position : SV_POSITION;         \\n\n   float2 texcoord : TEXCOORD;            \\n\n};\n *\n */\nclass CImage2DEffect\n{\nprivate:\n    Microsoft::WRL::ComPtr<ID3D10Device1> m_p_owner_device1{};\n    Microsoft::WRL::ComPtr<ID3DBlob> m_p_vs_byte_code{D3DQuadrangle::GetVsShader().Compile()};\n    Microsoft::WRL::ComPtr<ID3DBlob> m_p_ps_byte_code{};\n    Microsoft::WRL::ComPtr<ID3D10Texture2D> m_p_input{};\n    Microsoft::WRL::ComPtr<ID3D10Texture2D> m_p_output{};\n    //内部使用\n    Microsoft::WRL::ComPtr<ID3D10InputLayout> m_p_input_layout{};\n    Microsoft::WRL::ComPtr<ID3D10Buffer> m_p_vertex_buffer{};\n    Microsoft::WRL::ComPtr<ID3D10Buffer> m_p_index_buffer{};\n    Microsoft::WRL::ComPtr<ID3D10VertexShader> m_p_vs{};\n    Microsoft::WRL::ComPtr<ID3D10RasterizerState> m_p_rasterizer_state{};\n    Microsoft::WRL::ComPtr<ID3D10BlendState1> m_p_blend_state1{};\n    Microsoft::WRL::ComPtr<ID3D10DepthStencilState> m_p_depth_stencil_state{};\n    UINT m_output_width{};\n    UINT m_output_height{};\n    Microsoft::WRL::ComPtr<ID3D10ShaderResourceView> m_p_ps_tex0_resource_view{};\n    Microsoft::WRL::ComPtr<ID3D10SamplerState> m_p_ps_tex0_sampler_state{};\n    Microsoft::WRL::ComPtr<ID3D10PixelShader> m_p_ps{};\n    Microsoft::WRL::ComPtr<ID3D10RenderTargetView> m_p_render_target_view{};\n\nprotected:\n    void RecreateUnmodifiableResource(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1);\n    void RecreateInputTextureRelatedResources(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_input);\n    void RecreateOutputTextureRelatedResources(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_output);\n    void RecreateVsByteCodeRelatedResources(Microsoft::WRL::ComPtr<ID3DBlob> p_vs_byte_code);\n    void RecreatePsByteCodeRelatedResources(Microsoft::WRL::ComPtr<ID3DBlob> p_ps_byte_code);\n\npublic:\n    constexpr static auto PIXEL_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM;\n    constexpr static UINT SLOT = 0;\n    using QuadrangleVertexs = D3DQuadrangle::QuadrangleVertexs<Image2DVertex>;\n\n    CImage2DEffect(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1);\n    ~CImage2DEffect() = default;\n\n    auto RebindDevice1(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1)\n        -> CImage2DEffect&;\n\n    auto SetOutputSize(UINT width, UINT height) noexcept\n        -> CImage2DEffect&;\n    UINT GetOutputWidth() const noexcept;\n    UINT GetOutputHeight() const noexcept;\n\n    auto SetInputTexture(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_input)\n        -> CImage2DEffect&;\n    auto GetInputTexture() noexcept\n        -> Microsoft::WRL::ComPtr<ID3D10Texture2D>;\n\n    auto SetOutputTexture(Microsoft::WRL::ComPtr<ID3D10Texture2D> p_output)\n        -> CImage2DEffect&;\n    auto GetOutputTexture() noexcept\n        -> Microsoft::WRL::ComPtr<ID3D10Texture2D>;\n\n    auto SetVsByteCode(Microsoft::WRL::ComPtr<ID3DBlob> p_vs_byte_code)\n        -> CImage2DEffect&;\n    auto GetVsByteCode() noexcept\n        -> Microsoft::WRL::ComPtr<ID3DBlob>;\n\n    auto SetPsByteCode(Microsoft::WRL::ComPtr<ID3DBlob> p_ps_byte_code)\n        -> CImage2DEffect&;\n    auto GetPsByteCode() noexcept\n        -> Microsoft::WRL::ComPtr<ID3DBlob>;\n\n    auto ApplyPipelineConfig() const\n        -> const CImage2DEffect&;\n    [[nodiscard]] auto Draw() const\n        -> CD3D10DrawCallWaiter;\n    void DrawOnly() const noexcept;\n    [[nodiscard]] auto Clear(const std::array<FLOAT, 4>& color) const\n        -> CD3D10DrawCallWaiter;\n    auto ClearOnly(const std::array<FLOAT, 4>& color) const noexcept\n        -> const CImage2DEffect&;\n};\n#define CIMAGE2DEFFECT_SHADER_VS_INPUT_DECLARATION \\\n    \"struct VsInput\"                               \\\n    \"{\"                                            \\\n    \"   float4 position : POSITION;\"               \\\n    \"   float2 texcoord : TEXCOORD;\"               \\\n    \"};\"\n\n#define CIMAGE2DEFFECT_SHADER_VS_OUTPUT_DECLARATION \\\n    \"struct VsOutput\"                               \\\n    \"{\"                                             \\\n    \"   float4 position : SV_POSITION;\"             \\\n    \"   float2 texcoord : TEXCOORD;\"                \\\n    \"};\"\n"
  },
  {
    "path": "TrafficMonitor/IniHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"IniHelper.h\"\n#include \"Common.h\"\n\nCIniHelper::CIniHelper(const wstring& file_path, bool force_utf8)\n{\n    m_file_path = file_path;\n    ifstream file_stream{ file_path };\n    if (!file_stream.is_open())\n        return;\n    // 获取文件大小\n    file_stream.seekg(0, std::ios::end);\n    size_t file_size = static_cast<size_t>(file_stream.tellg());\n    file_stream.seekg(0, std::ios::beg);\n    // 读取文件内容\n    string ini_str;\n    ini_str.resize(file_size + 1);\n    file_stream.read(&ini_str[0], file_size);\n    // 检查并添加末尾的空行\n    if (!ini_str.empty() && ini_str.back() != L'\\n')\n        ini_str.push_back(L'\\n');\n    bool is_utf8;\n    if (force_utf8)\n    {\n        is_utf8 = true;\n    }\n    else\n    {\n        //判断文件是否是utf8编码\n        if (ini_str.size() >= 3 && ini_str[0] == -17 && ini_str[1] == -69 && ini_str[2] == -65)\n        {\n            //如果有UTF8的BOM，则删除BOM\n            is_utf8 = true;\n            ini_str = ini_str.substr(3);\n        }\n        else\n        {\n            is_utf8 = false;\n        }\n    }\n    //转换成Unicode\n    m_ini_str = CCommon::StrToUnicode(ini_str.c_str(), is_utf8);\n}\n\nCIniHelper::CIniHelper(UINT id, bool is_utf8)\n{\n    m_ini_str = CCommon::GetTextResource(id, is_utf8 ? 1 : 0);\n}\n\nCIniHelper::CIniHelper()\n{\n}\n\n\nCIniHelper::~CIniHelper()\n{\n}\n\nvoid CIniHelper::FromDirectString(const wstring& str_content)\n{\n    m_ini_str = str_content;\n}\n\nvoid CIniHelper::SetSaveAsUTF8(bool utf8)\n{\n    m_save_as_utf8 = utf8;\n}\n\nvoid CIniHelper::WriteString(const wchar_t * AppName, const wchar_t * KeyName, const wstring& str)\n{\n    wstring write_str{ str };\n    if (!write_str.empty() && (write_str[0] == L' ' || write_str.back() == L' '))       //如果字符串前后含有空格，则在字符串前后添加引号\n    {\n        write_str = DEF_CH + write_str;\n        write_str.push_back(DEF_CH);\n    }\n    _WriteString(AppName, KeyName, write_str);\n}\n\nwstring CIniHelper::GetString(const wchar_t * AppName, const wchar_t * KeyName, const wchar_t* default_str) const\n{\n    wstring rtn{ default_str };\n    GetString(AppName, KeyName, rtn);\n    return rtn;\n}\n\nbool CIniHelper::GetString(const wchar_t* AppName, const wchar_t* KeyName, wstring& str) const\n{\n    bool rtn = _GetString(AppName, KeyName, str);\n    //如果读取的字符串前后有指定的字符，则删除它\n    if (!str.empty() && (str.front() == L'$' || str.front() == DEF_CH))\n        str = str.substr(1);\n    if (!str.empty() && (str.back() == L'$' || str.back() == DEF_CH))\n        str.pop_back();\n    return rtn;\n}\n\nvoid CIniHelper::WriteInt(const wchar_t * AppName, const wchar_t * KeyName, int value)\n{\n    _WriteString(AppName, KeyName, std::to_wstring(value));\n}\n\nint CIniHelper::GetInt(const wchar_t * AppName, const wchar_t * KeyName, int default_value) const\n{\n    wstring rtn{ std::to_wstring(default_value) };\n    _GetString(AppName, KeyName, rtn);\n    return _ttoi(rtn.c_str());\n}\n\nvoid CIniHelper::WriteBool(const wchar_t * AppName, const wchar_t * KeyName, bool value)\n{\n    if(value)\n        _WriteString(AppName, KeyName, wstring(L\"true\"));\n    else\n        _WriteString(AppName, KeyName, wstring(L\"false\"));\n}\n\nbool CIniHelper::GetBool(const wchar_t * AppName, const wchar_t * KeyName, bool default_value) const\n{\n    wstring rtn{ default_value ? L\"true\" : L\"false\" };\n    _GetString(AppName, KeyName, rtn);\n    if (rtn == L\"true\")\n        return true;\n    else if (rtn == L\"false\")\n        return false;\n    else\n        return (_ttoi(rtn.c_str()) != 0);\n}\n\nvoid CIniHelper::WriteIntArray(const wchar_t * AppName, const wchar_t * KeyName, const int * values, int size)\n{\n    CString str, tmp;\n    for (int i{}; i < size; i++)\n    {\n        tmp.Format(_T(\"%d,\"), values[i]);\n        str += tmp;\n    }\n    _WriteString(AppName, KeyName, wstring(str));\n}\n\nvoid CIniHelper::GetIntArray(const wchar_t * AppName, const wchar_t * KeyName, int * values, int size, int default_value) const\n{\n    CString default_str;\n    default_str.Format(_T(\"%d\"), default_value);\n    wstring str{ default_str.GetString() };\n    _GetString(AppName, KeyName, str);\n    std::vector<wstring> split_result;\n    CCommon::StringSplit(str, L',', split_result);\n    for (int i = 0; i < size; i++)\n    {\n        if (i < split_result.size())\n            values[i] = _wtoi(split_result[i].c_str());\n        else if (i > 0)\n            values[i] = values[i - 1];\n        else\n            values[i] = default_value;\n    }\n}\n\nvoid CIniHelper::WriteBoolArray(const wchar_t * AppName, const wchar_t * KeyName, const bool * values, int size)\n{\n    int value{};\n    for (int i{}; i < size; i++)\n    {\n        if (values[i])\n            value |= (1 << i);\n    }\n    return WriteInt(AppName, KeyName, value);\n}\n\nvoid CIniHelper::GetBoolArray(const wchar_t * AppName, const wchar_t * KeyName, bool * values, int size, bool default_value) const\n{\n    int value = GetInt(AppName, KeyName, 0);\n    for (int i{}; i < size; i++)\n    {\n        values[i] = ((value >> i) % 2 != 0);\n    }\n}\n\nvoid CIniHelper::WriteStringList(const wchar_t* AppName, const wchar_t* KeyName, const vector<wstring>& values)\n{\n    wstring str_write = MergeStringList(values);\n    _WriteString(AppName, KeyName, str_write);\n}\n\nvoid CIniHelper::GetStringList(const wchar_t* AppName, const wchar_t* KeyName, vector<wstring>& values, const vector<wstring>& default_value) const\n{\n    wstring str_value = MergeStringList(default_value);\n    _GetString(AppName, KeyName, str_value);\n    SplitStringList(values, str_value);\n}\n\nvector<wstring> CIniHelper::GetAllAppName(const wstring& prefix) const\n{\n    vector<wstring> list;\n    size_t pos{};\n    while ((pos = m_ini_str.find(L\"\\n[\" + prefix, pos)) != wstring::npos)\n    {\n        size_t end = m_ini_str.find(L']', pos + 1);\n        if (end != wstring::npos)\n        {\n            wstring tmp(m_ini_str.begin() + pos + prefix.size() + 2, m_ini_str.begin() + end);\n            list.push_back(std::move(tmp));\n            pos = end + 1;\n        }\n    }\n    return list;\n}\n\nvoid CIniHelper::GetAllKeyValues(const wstring& AppName, std::map<wstring, wstring>& map) const\n{\n    wstring app_str{ L\"[\" };\n    app_str.append(AppName).append(L\"]\");\n    size_t app_pos{}, app_end_pos{};\n    app_pos = m_ini_str.find(app_str);\n    if (app_pos == wstring::npos)\n        return;\n    app_end_pos = m_ini_str.find(L\"\\n[\", app_pos + 2);\n    if (app_end_pos != wstring::npos)\n        app_end_pos++;\n    app_str = m_ini_str.substr(app_pos, app_end_pos - app_pos);\n    vector<wstring> line;\n    CCommon::StringSplit(app_str, L'\\n', line);\n    for (wstring str : line)\n    {\n        // CCommon::StringSplit会跳过空字符串，str一定非空\n        if (str[0] == L';' || str[0] == L'#')   // 跳过注释行（只支持行首注释）\n            continue;\n        size_t pos = str.find_first_of(L'=');\n        if (pos == wstring::npos)\n            continue;\n        wstring key{ str.substr(0, pos) };\n        wstring value{ str.substr(pos + 1) };\n        CCommon::StringNormalize(key);\n        CCommon::StringNormalize(value);\n        if (!key.empty() && !value.empty())\n        {\n            if (value.front() == L'\\\"' && value.back() == L'\\\"')\n                value = value.substr(1, value.size() - 2);\n            UnEscapeString(value);\n            map[key] = value;\n        }\n    }\n}\n\nbool CIniHelper::RemoveSection(const wstring& AppName)\n{\n    if (AppName.empty())\n        return false;\n    wstring app_str{ L\"[\" };\n    app_str.append(AppName).append(L\"]\");\n    size_t app_pos{}, app_end_pos{};\n    app_pos = m_ini_str.find(app_str);\n    if (app_pos == wstring::npos)       //找不到AppName，返回默认字符串\n        return false;\n\n    app_end_pos = m_ini_str.find(L\"\\n[\", app_pos + 2);\n    if (app_end_pos != wstring::npos)\n        app_end_pos++;\n\n    m_ini_str.erase(app_pos, app_end_pos - app_pos);\n\n    return true;\n}\n\nbool CIniHelper::Save()\n{\n    if (m_file_path.empty())\n        return false;\n    ofstream file_stream{ m_file_path };\n    if(file_stream.fail())\n        return false;\n    string ini_str{ CCommon::UnicodeToStr(m_ini_str.c_str(), m_save_as_utf8) };\n    if (m_save_as_utf8)     //如果以UTF8编码保存，先插入BOM\n    {\n        string utf8_bom;\n        utf8_bom.push_back(-17);\n        utf8_bom.push_back(-69);\n        utf8_bom.push_back(-65);\n        file_stream << utf8_bom;\n    }\n\n    file_stream << ini_str;\n    return true;\n}\n\nvoid CIniHelper::UnEscapeString(wstring& str)\n{\n    bool escape{ false };\n    wstring result;\n    result.reserve(str.size());\n    for (size_t i = 0; i < str.size(); i++)\n    {\n        wchar_t ch = str[i];\n        if (escape)\n        {\n            switch (ch)\n            {\n            case L'n': result += L'\\n'; break;\n            case L'r': result += L'\\r'; break;\n            case L't': result += L'\\t'; break;\n            case L'\"': result += L'\"'; break;\n            case L';': result += L';'; break;\n            case L'#': result += L'#'; break;\n            case L'\\\\': result += L'\\\\'; break;\n            default:result += '\\\\'; result += ch; break;\n            }\n            escape = false;\n        }\n        else if (ch == L'\\\\')\n            escape = true;\n        else if (i > 0 && ch == '\\\"' && str[i - 1] == '\\\"')     //两个连续的引号只保留一个引号\n            continue;\n        else\n            result += ch;\n    }\n    str.swap(result);\n}\n\nvoid CIniHelper::_WriteString(const wchar_t * AppName, const wchar_t * KeyName, const wstring & str)\n{\n    wstring app_str{ L\"[\" };\n    app_str.append(AppName).append(L\"]\");\n    size_t app_pos{}, app_end_pos, key_pos;\n    app_pos = m_ini_str.find(app_str);\n    if (app_pos == wstring::npos)       //找不到AppName，则在最后面添加\n    {\n        if (!m_ini_str.empty() && m_ini_str.back() != L'\\n')\n            m_ini_str += L\"\\n\";\n        app_pos = m_ini_str.size();\n        m_ini_str += app_str;\n        m_ini_str += L\"\\n\";\n    }\n    app_end_pos = m_ini_str.find(L\"\\n[\", app_pos + 2);\n    if (app_end_pos != wstring::npos)\n        app_end_pos++;\n\n    key_pos = m_ini_str.find(wstring(L\"\\n\") + KeyName + L' ', app_pos);     //查找“\\nkey_name ”\n    if (key_pos >= app_end_pos)     //如果找不到“\\nkey_name ”，则查找“\\nkey_name=”\n        key_pos = m_ini_str.find(wstring(L\"\\n\") + KeyName + L'=', app_pos);\n    if (key_pos >= app_end_pos)             //找不到KeyName，则插入一个\n    {\n        //wchar_t buff[256];\n        //swprintf_s(buff, L\"%s = %s\\n\", KeyName, str.c_str());\n        std::wstring str_temp = KeyName;\n        str_temp += L\" = \";\n        str_temp += str;\n        str_temp += L\"\\n\";\n        if (app_end_pos == wstring::npos)\n            m_ini_str += str_temp;\n        else\n            m_ini_str.insert(app_end_pos, str_temp);\n    }\n    else    //找到了KeyName，将等号到换行符之间的文本替换\n    {\n        size_t str_pos;\n        str_pos = m_ini_str.find(L'=', key_pos + 2);\n        size_t line_end_pos = m_ini_str.find(L'\\n', key_pos + 2);\n        if (str_pos > line_end_pos) //所在行没有等号，则插入一个等号\n        {\n            m_ini_str.insert(key_pos + wcslen(KeyName) + 1, L\" =\");\n            str_pos = key_pos + wcslen(KeyName) + 2;\n        }\n        else\n        {\n            str_pos++;\n        }\n        size_t str_end_pos;\n        str_end_pos = m_ini_str.find(L\"\\n\", str_pos);\n        m_ini_str.replace(str_pos, str_end_pos - str_pos, L\" \" + str);\n    }\n}\n\nbool CIniHelper::_GetString(const wchar_t* AppName, const wchar_t* KeyName, wstring& str) const\n{\n    wstring app_str{ L\"[\" };\n    app_str.append(AppName).append(L\"]\");\n    size_t app_pos{}, app_end_pos, key_pos;\n    app_pos = m_ini_str.find(app_str);\n    if (app_pos == wstring::npos)       //找不到AppName，返回默认字符串\n        return false;\n\n    app_end_pos = m_ini_str.find(L\"\\n[\", app_pos + 2);\n    if (app_end_pos != wstring::npos)\n        app_end_pos++;\n\n    key_pos = m_ini_str.find(wstring(L\"\\n\") + KeyName + L' ', app_pos);     //查找“\\nkey_name ”\n    if (key_pos >= app_end_pos)     //如果找不到“\\nkey_name ”，则查找“\\nkey_name=”\n        key_pos = m_ini_str.find(wstring(L\"\\n\") + KeyName + L'=', app_pos);\n    if (key_pos >= app_end_pos)             //找不到KeyName，返回默认字符串\n    {\n        return false;\n    }\n    else    //找到了KeyName，获取等号到换行符之间的文本\n    {\n        size_t str_pos;\n        str_pos = m_ini_str.find(L'=', key_pos + 2);\n        size_t line_end_pos = m_ini_str.find(L'\\n', key_pos + 2);\n        if (str_pos > line_end_pos) //所在行没有等号，返回默认字符串\n        {\n            return false;\n        }\n        else\n        {\n            str_pos++;\n        }\n        size_t str_end_pos;\n        str_end_pos = m_ini_str.find(L\"\\n\", str_pos);\n        //获取文本\n        wstring return_str{ m_ini_str.substr(str_pos, str_end_pos - str_pos) };\n        //如果前后有空格，则将其删除\n        CCommon::StringNormalize(return_str);\n        str = return_str;\n        return true;\n    }\n}\n\nwstring CIniHelper::MergeStringList(const vector<wstring>& values)\n{\n    wstring str_merge;\n    int index = 0;\n    //在每个字符串前后加上引号，再将它们用逗号连接起来\n    for (const wstring& str : values)\n    {\n        if (index > 0)\n            str_merge.push_back(L',');\n        str_merge.push_back(L'\\\"');\n        str_merge += str;\n        str_merge.push_back(L'\\\"');\n        index++;\n    }\n    return str_merge;\n}\n\nvoid CIniHelper::SplitStringList(vector<wstring>& values, const wstring& str_value)\n{\n    CCommon::StringSplit(str_value, wstring(L\"\\\",\\\"\"), values);\n    if (!values.empty())\n    {\n        //结果中第一项前面和最后一项的后面各还有一个引号，将它们删除\n        values.front() = values.front().substr(1);\n        values.back().pop_back();\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/IniHelper.h",
    "content": "﻿//ini读写类\n//使用时将ini文件路径通过构造函数参数传递\n//在向ini文件写入数据时，需要在最后调用Save()函数以将更改保存到文件\n//默认以UTF8_BOM编码保存，如果要以ANSI保存，请调用SetSaveAsUTF8(false);\n#pragma once\n\nclass CIniHelper\n{\npublic:\n\t// 从磁盘加载ini文件\n\t// file_path：文件路径\n\t// force_utf8：如果为true，则强制以UTF8编码解析，否则，仅当含有UTF8 BOM时才以UTF8编码解析\n\tCIniHelper(const wstring& file_path, bool force_utf8 = false);\n    // 从资源文件加载ini (只能读取)\n    CIniHelper(UINT id, bool is_utf8 = true);\n    CIniHelper();\n\t~CIniHelper();\n\n    void FromDirectString(const wstring& str_content);\n\n\tvoid SetSaveAsUTF8(bool utf8);\n\n\tvoid WriteString(const wchar_t* AppName, const wchar_t* KeyName, const wstring& str);\n\twstring GetString(const wchar_t* AppName, const wchar_t* KeyName, const wchar_t* default_str) const;\n\tbool GetString(const wchar_t* AppName, const wchar_t* KeyName, wstring& str) const;\n\tvoid WriteInt(const wchar_t * AppName, const wchar_t * KeyName, int value);\n\tint GetInt(const wchar_t * AppName, const wchar_t * KeyName, int default_value) const;\n\tvoid WriteBool(const wchar_t * AppName, const wchar_t * KeyName, bool value);\n\tbool GetBool(const wchar_t * AppName, const wchar_t * KeyName, bool default_value) const;\n\tvoid WriteIntArray(const wchar_t * AppName, const wchar_t * KeyName, const int* values, int size);\t\t//写入一个int数组，元素个数为size\n\tvoid GetIntArray(const wchar_t * AppName, const wchar_t * KeyName, int* values, int size, int default_value = 0) const;\t\t//读取一个int数组，储存到values，元素个数为size\n\tvoid WriteBoolArray(const wchar_t * AppName, const wchar_t * KeyName, const bool* values, int size);\n\tvoid GetBoolArray(const wchar_t * AppName, const wchar_t * KeyName, bool* values, int size, bool default_value = false) const;\n    void WriteStringList(const wchar_t* AppName, const wchar_t* KeyName, const vector<wstring>& values);      //写入一个字符串列表，由于保存到ini文件中时字符串前后会加上引号，所以字符串中不能包含引号\n    void GetStringList(const wchar_t* AppName, const wchar_t* KeyName, vector<wstring>& values, const vector<wstring>& default_value) const;\n\n    // 获取带有指定前缀的所有AppName（不含前缀）\n    vector<wstring> GetAllAppName(const wstring& prefix) const;\n    // 获取一个AppName下所有键值对\n    void GetAllKeyValues(const wstring& AppName, std::map<wstring, wstring>& map) const;\n\n\t//移除一个段\n\tbool RemoveSection(const wstring& AppName);\n\n\tbool Save();\t\t//将ini文件保存到文件，成功返回true\n\nprotected:\n\twstring m_file_path;\n\twstring m_ini_str;\n\tbool m_save_as_utf8{ true };\t\t//是否以及UTF8编码保存\n\n    static void UnEscapeString(wstring& str);\n    void _WriteString(const wchar_t* AppName, const wchar_t* KeyName, const wstring& str);\n\tbool _GetString(const wchar_t* AppName, const wchar_t* KeyName, wstring& str) const;\n\n    static wstring MergeStringList(const vector<wstring>& values);\n    static void SplitStringList(vector<wstring>& values, const wstring& str_value);\n};\n"
  },
  {
    "path": "TrafficMonitor/LinkStatic.cpp",
    "content": "﻿// CLinkStatic.cpp: 实现文件\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"LinkStatic.h\"\n\n\n// CLinkStatic\n\nIMPLEMENT_DYNAMIC(CLinkStatic, CStatic)\n\nCLinkStatic::CLinkStatic()\n{\n\n}\n\nCLinkStatic::~CLinkStatic()\n{\n}\n\n\nvoid CLinkStatic::SetBackgroundColor(COLORREF background_color)\n{\n    m_back_color = background_color;\n}\n\nvoid CLinkStatic::SetURL(CString strURL)\n{\n\tm_strURL = strURL;\n}\n\nCString CLinkStatic::GetURL() const\n{\n\treturn m_strURL;\n}\n\n\nBEGIN_MESSAGE_MAP(CLinkStatic, CStatic)\n\tON_WM_MOUSEMOVE()\n\tON_WM_LBUTTONUP()\n\tON_WM_MOUSEHOVER()\n\tON_WM_MOUSELEAVE()\n\tON_WM_SETCURSOR()\n\tON_WM_PAINT()\nEND_MESSAGE_MAP()\n\n\n\n// CLinkStatic 消息处理程序\n\nbool CLinkStatic::IsLinkValid() const\n{\n    return (!m_link_is_url || !m_strURL.IsEmpty());\n}\n\nvoid CLinkStatic::OnMouseMove(UINT nFlags, CPoint point)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tTRACKMOUSEEVENT tme;\n\ttme.cbSize = sizeof(tme);\n\ttme.hwndTrack = m_hWnd;\n\ttme.dwFlags = TME_LEAVE | TME_HOVER;\n\ttme.dwHoverTime = 1;\n\t_TrackMouseEvent(&tme);\n}\n\n\nvoid CLinkStatic::OnLButtonUp(UINT nFlags, CPoint point)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tif (m_link_is_url)\n\t{\n\t\tif (!m_strURL.IsEmpty())\n\t\t\tShellExecute(NULL, _T(\"open\"), m_strURL, NULL, NULL, SW_SHOW);\t//打开超链接\n\t}\n\telse\n\t{\n\t\tCWnd* pParent{ GetParent() };\n\t\tif (pParent != nullptr)\n\t\t\tpParent->SendMessage(WM_LINK_CLICKED, (WPARAM)this);\n\t}\n}\n\n\nvoid CLinkStatic::OnMouseHover(UINT nFlags, CPoint point)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tif (!m_bHot)\n\t{\n\t\tm_bHot = true;\n\t\tInvalidate();\n\t}\n\telse\n\t{\n\t\tCStatic::OnMouseHover(nFlags, point);\n\t}\n}\n\n\nvoid CLinkStatic::OnMouseLeave()\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tm_bHot = false;\n\tInvalidate();\n}\n\n\nBOOL CLinkStatic::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\tif (IsLinkValid() && m_bHot)\n\t{\n\t\t::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(32649)));\n\t\treturn TRUE;\n\t}\n\n\treturn CStatic::OnSetCursor(pWnd, nHitTest, message);\n}\n\n\n\nvoid CLinkStatic::OnPaint()\n{\n\tCPaintDC dc(this); // device context for painting\n\t\t\t\t\t   // TODO: 在此处添加消息处理程序代码\n\t\t\t\t\t   // 不为绘图消息调用 CStatic::OnPaint()\n\t//准备工作\n    if (m_hover_font.GetSafeHandle() == NULL)\n    {\n        LOGFONT lf;\n        GetFont()->GetLogFont(&lf);\n        lf.lfUnderline = true;\n        m_hover_font.CreateFontIndirect(&lf);\n    }\n\n    if (IsLinkValid())\n    {\n        if (m_bHot)\n            dc.SelectObject(&m_hover_font);\n        else\n            dc.SelectObject(GetFont());\n        dc.SetTextColor(GetSysColor(COLOR_HOTLIGHT));\n    }\n    else\n    {\n        dc.SelectObject(GetFont());\n    }\n\tdc.SetBkMode(TRANSPARENT);\n\tCRect rect;\n\tthis->GetClientRect(&rect);\n\t//画背景\n\tdc.FillSolidRect(rect, m_back_color);\n\t///输出文字\n    CString text;\n    GetWindowText(text);\n\tif (text.GetLength()>0)\n\t{\n\t\tdc.DrawText(text, rect, DT_VCENTER | DT_SINGLELINE);\n\t}\n}\n\n\nvoid CLinkStatic::PreSubclassWindow()\n{\n\t// TODO: 在此添加专用代码和/或调用基类\n\tDWORD dwStyle = GetStyle();\n\t::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);\n\n\tCStatic::PreSubclassWindow();\n}\n"
  },
  {
    "path": "TrafficMonitor/LinkStatic.h",
    "content": "﻿/*继承于CStatic类，用作超链接：\n调用SetURL函数设置超链接；\n调用SetLinkIsURL函数设置点击控件后是打开超链接还是响应命令\n如果调用SetLinkIsURL(false)，则点击控件后会向父窗口发送一个WM_LINK_CLICKED消息，\n并通过WPARAM传递控件的指针。\n否则，点击控件后打开超链接\n*/\n#pragma once\n\n#define WM_LINK_CLICKED (WM_USER + 1002)\n\n// CLinkStatic\n\nclass CLinkStatic : public CStatic\n{\n\tDECLARE_DYNAMIC(CLinkStatic)\n\npublic:\n\tCLinkStatic();\n\tvirtual ~CLinkStatic();\n    void SetBackgroundColor(COLORREF background_color);\n\npublic:\n\tvoid SetURL(CString strURL);\t\t//设置超链接\n\tCString GetURL() const;\t\t\t//获取超链接字符串\n\tvoid SetLinkIsURL(bool enable) { m_link_is_url = enable; }\nprotected:\n\tbool m_link_is_url{ true };\t\t//如果为true，点击后打开超链接，否则向父窗口发送一个点击消息\n\tbool m_bHot{ false };\t\t\t//当鼠标指向超链接时，则为true\n\tCString m_strURL;\t\t\t\t//超链接字符串\n    COLORREF m_back_color{ GetSysColor(COLOR_BTNFACE) };\n    CFont m_hover_font;\n    bool IsLinkValid() const;\n\nprotected:\n\tDECLARE_MESSAGE_MAP()\n\tafx_msg void OnMouseMove(UINT nFlags, CPoint point);\n\tafx_msg void OnLButtonUp(UINT nFlags, CPoint point);\n\tafx_msg void OnMouseHover(UINT nFlags, CPoint point);\n\tafx_msg void OnMouseLeave();\n\tafx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);\npublic:\n\tafx_msg void OnPaint();\n\tvirtual void PreSubclassWindow();\n};\n\n\n"
  },
  {
    "path": "TrafficMonitor/ListCtrlEx.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"ListCtrlEx.h\"\n\nIMPLEMENT_DYNAMIC(CListCtrlEx, CListCtrl)\n\nCListCtrlEx::CListCtrlEx()\n{\n}\n\n\nCListCtrlEx::~CListCtrlEx()\n{\n}\n\nvoid CListCtrlEx::Edit(int row, int col)\n{\n    EnsureVisible(row, FALSE);\t\t\t\t//编辑一行时确保该行可见\n    m_editing = true;\n\n    m_edit_row = row;\n    m_edit_col = col;\n    CRect item_rect;\n    GetSubItemRect(row, col, LVIR_LABEL, item_rect);\t//取得子项的矩形\n\n    CString text = GetItemText(row, col);\t\t//取得子项的内容\n\n    m_item_edit.SetWindowText(text);\t\t//将子项的内容显示到编辑框中\n    m_item_edit.ShowWindow(SW_SHOW);\t\t//显示编辑框\n    m_item_edit.MoveWindow(item_rect);\t\t//将编辑框移动到子项上面，覆盖在子项上\n    m_item_edit.SetFocus();\t\t\t\t\t//使编辑框取得焦点\n    m_item_edit.SetSel(0, -1);\n}\n\nvoid CListCtrlEx::SetEditColMethod(eEditColMethod method)\n{\n    m_edit_col_method = method;\n}\n\nvoid CListCtrlEx::SetEditableCol(const std::initializer_list<int>& paras)\n{\n    m_edit_cols = paras;\n}\n\nvoid CListCtrlEx::EndEdit()\n{\n    if (m_editing)\n    {\n        if (m_edit_row >= 0 && m_edit_row < GetItemCount())\n        {\n            CString str;\n            m_item_edit.GetWindowText(str);\t//取得编辑框的内容\n            SetItemText(m_edit_row, m_edit_col, str);\t//将该内容更新到CListCtrl中\n        }\n        m_item_edit.ShowWindow(SW_HIDE);//隐藏编辑框\n        m_editing = false;\n    }\n}\n\nBEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)\n    ON_EN_KILLFOCUS(IDC_ITEM_EDITBOX, &CListCtrlEx::OnEnKillfocusEdit1)\n    ON_NOTIFY_REFLECT_EX(NM_DBLCLK, &CListCtrlEx::OnNMDblclk)\n    ON_NOTIFY_REFLECT(LVN_BEGINSCROLL, &CListCtrlEx::OnLvnBeginScroll)\n    ON_MESSAGE(WM_TABLET_QUERYSYSTEMGESTURESTATUS, &CListCtrlEx::OnTabletQuerysystemgesturestatus)\nEND_MESSAGE_MAP()\n\n\nvoid CListCtrlEx::OnEnKillfocusEdit1()\n{\n    //当文本编辑控件控件失去焦点时响应\n    EndEdit();\n}\n\n\n\nvoid CListCtrlEx::PreSubclassWindow()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    m_item_edit.Create(WS_BORDER | ES_AUTOHSCROLL, CRect(), this, IDC_ITEM_EDITBOX);\n    m_item_edit.SetFont(GetFont());\n\n    CListCtrl::PreSubclassWindow();\n}\n\n\nBOOL CListCtrlEx::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n\n    //如果双击的列是要编辑的列\n    if (m_edit_col_method == EC_ALL\n        || (m_edit_col_method == EC_SPECIFIED && m_edit_cols.find(pNMItemActivate->iSubItem) != m_edit_cols.end()))\n    {\n        Edit(pNMItemActivate->iItem, pNMItemActivate->iSubItem);\n        *pResult = 0;\n        return TRUE;\n    }\n    else\n    {\n        return FALSE;\n    }\n}\n\n\nvoid CListCtrlEx::OnLvnBeginScroll(NMHDR *pNMHDR, LRESULT *pResult)\n{\n    // 此功能要求 Internet Explorer 5.5 或更高版本。\n    // 符号 _WIN32_IE 必须是 >= 0x0560。\n    LPNMLVSCROLL pStateChanged = reinterpret_cast<LPNMLVSCROLL>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n    EndEdit();\n\n    *pResult = 0;\n}\n\n\nafx_msg LRESULT CListCtrlEx::OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam)\n{\n    return 0;\n}\n\n\nBOOL CListCtrlEx::PreTranslateMessage(MSG* pMsg)\n{\n    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)\n    {\n        //编辑状态下按回车键结束编辑而不是关闭对话框\n        if (m_editing)\n        {\n            EndEdit();\n            return TRUE;\n        }\n    }\n\n    return CListCtrl::PreTranslateMessage(pMsg);\n}\n"
  },
  {
    "path": "TrafficMonitor/ListCtrlEx.h",
    "content": "﻿#pragma once\n#include \"afxcmn.h\"\n#include \"DrawCommon.h\"\n#include <set>\n\n#define IDC_ITEM_EDITBOX 1991\nclass CListCtrlEx :\n\tpublic CListCtrl\n{\nDECLARE_DYNAMIC(CListCtrlEx)\npublic:\n\tCListCtrlEx();\n\t~CListCtrlEx();\n\n    void Edit(int row, int col);\t\t\t//编辑指定单元格\n\n    enum eEditColMethod       //要编辑的列的方式\n    {\n        EC_NONE,        //无\n        EC_ALL,         //全部\n        EC_SPECIFIED    //指定的列\n    };\n    void SetEditColMethod(eEditColMethod method);\n    void SetEditableCol(const std::initializer_list<int>& paras);   //设置允许编辑的列\n\nprivate:\n    CEdit m_item_edit;\n    int m_edit_row{};\n    int m_edit_col{};\n    bool m_editing{};\n\n    eEditColMethod m_edit_col_method{ EC_NONE };\n    std::set<int> m_edit_cols;\n\nprotected:\n    void EndEdit();\n\n\tDECLARE_MESSAGE_MAP()\n    afx_msg void OnEnKillfocusEdit1();\n    virtual void PreSubclassWindow();\n    afx_msg BOOL OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);\n    afx_msg void OnLvnBeginScroll(NMHDR *pNMHDR, LRESULT *pResult);\n    afx_msg LRESULT OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam);\npublic:\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n};\n\n"
  },
  {
    "path": "TrafficMonitor/MainWndColorDlg.cpp",
    "content": "﻿// MainWndColorDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"MainWndColorDlg.h\"\n#include \"afxdialogex.h\"\n#include \"CMFCColorDialogEx.h\"\n#include \"TrafficMonitorDlg.h\"\n\n\n// CMainWndColorDlg 对话框\n\nIMPLEMENT_DYNAMIC(CMainWndColorDlg, CBaseDialog)\n\nCMainWndColorDlg::CMainWndColorDlg(const std::map<CommonDisplayItem, COLORREF>& colors, CWnd* pParent /*=NULL*/)\n\t: CBaseDialog(IDD_MAIN_COLOR_DIALOG, pParent), m_colors(colors)\n{\n}\n\nCMainWndColorDlg::~CMainWndColorDlg()\n{\n}\n\nCString CMainWndColorDlg::GetDialogName() const\n{\n    return _T(\"MainWndColorDlg\");\n}\n\nvoid CMainWndColorDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_LIST1, m_list_ctrl);\n}\n\n\nBEGIN_MESSAGE_MAP(CMainWndColorDlg, CBaseDialog)\n    ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CMainWndColorDlg::OnNMDblclkList1)\nEND_MESSAGE_MAP()\n\n\n// CMainWndColorDlg 消息处理程序\n\n\nBOOL CMainWndColorDlg::OnInitDialog()\n{\n\tCBaseDialog::OnInitDialog();\n\n\t// TODO:  在此添加额外的初始化\n\n    SetIcon(theApp.GetMenuIcon(IDI_MAIN_WINDOW), FALSE);\t\t// 设置小图标\n\n    //初始化列表控件\n    CRect rect;\n    m_list_ctrl.GetClientRect(rect);\n    m_list_ctrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);\n    int width0, width1;\n    width0 = rect.Width() * 2 / 3;\n    width1 = rect.Width() - width0 - theApp.DPI(20) - 1;\n    m_list_ctrl.InsertColumn(0, CCommon::LoadText(IDS_ITEM), LVCFMT_LEFT, width0);\t\t//插入第0列\n    m_list_ctrl.InsertColumn(1, CCommon::LoadText(IDS_COLOR), LVCFMT_LEFT, width1);\t\t//插入第1列\n    m_list_ctrl.SetDrawItemRangMargin(theApp.DPI(2));\n\n    static std::set<CommonDisplayItem> all_skin_items;\n    CTrafficMonitorDlg::Instance()->GetCurSkin().GetSkinDisplayItems(all_skin_items);\n\n    //向列表中插入行\n    for (auto iter = all_skin_items.begin(); iter != all_skin_items.end(); ++iter)\n    {\n        CString item_name = iter->GetItemName();\n        if (!item_name.IsEmpty())\n        {\n            int index = m_list_ctrl.GetItemCount();\n            m_list_ctrl.InsertItem(index, item_name);\n            m_list_ctrl.SetItemColor(index, 1, m_colors[*iter]);\n            m_list_ctrl.SetItemData(index, (DWORD_PTR)&(*iter));\n        }\n    }\n\n\n\treturn TRUE;  // return TRUE unless you set the focus to a control\n\t\t\t\t  // 异常: OCX 属性页应返回 FALSE\n}\n\n\n\nvoid CMainWndColorDlg::OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n    int index = pNMItemActivate->iItem;\n    COLORREF color = m_list_ctrl.GetItemColor(index, 1);\n    CMFCColorDialogEx colorDlg(color, 0, this);\n    if (colorDlg.DoModal() == IDOK)\n    {\n        color = colorDlg.GetColor();\n        m_list_ctrl.SetItemColor(index, 1, color);\n        CommonDisplayItem* item = (CommonDisplayItem*)(m_list_ctrl.GetItemData(index));\n        m_colors[*item] = color;\n    }\n\n    *pResult = 0;\n}\n"
  },
  {
    "path": "TrafficMonitor/MainWndColorDlg.h",
    "content": "﻿#pragma once\n#include \"ColorStatic.h\"\n#include \"afxwin.h\"\n#include \"ColorSettingListCtrl.h\"\n#include \"BaseDialog.h\"\n\n// CMainWndColorDlg 对话框\n\nclass CMainWndColorDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CMainWndColorDlg)\n\npublic:\n\tCMainWndColorDlg(const std::map<CommonDisplayItem, COLORREF>& colors, CWnd* pParent = NULL);   // 标准构造函数\n\tvirtual ~CMainWndColorDlg();\n\n    const std::map<CommonDisplayItem, COLORREF>& GetColors() const { return m_colors; }\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_MAIN_COLOR_DIALOG };\n#endif\nprotected:\n    std::map<CommonDisplayItem, COLORREF> m_colors;\n    CColorSettingListCtrl m_list_ctrl;\n\n    virtual CString GetDialogName() const override;\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n\tDECLARE_MESSAGE_MAP()\npublic:\n\tvirtual BOOL OnInitDialog();\n    afx_msg void OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult);\n};\n"
  },
  {
    "path": "TrafficMonitor/MainWndSettingsDlg.cpp",
    "content": "﻿// MainWndSettingsDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"MainWndSettingsDlg.h\"\n#include \"afxdialogex.h\"\n#include \"CMFCColorDialogEx.h\"\n#include \"DisplayTextSettingDlg.h\"\n#include \"FileDialogEx.h\"\n#include \"TrafficMonitorDlg.h\"\n#include \"SkinManager.h\"\n\n// CMainWndSettingsDlg 对话框\n\nIMPLEMENT_DYNAMIC(CMainWndSettingsDlg, CTabDlg)\n\nCMainWndSettingsDlg::CMainWndSettingsDlg(CWnd* pParent /*=NULL*/)\n    : CTabDlg(IDD_MAIN_WND_SETTINGS_DIALOG, pParent)\n{\n\n}\n\nCMainWndSettingsDlg::~CMainWndSettingsDlg()\n{\n}\n\nvoid CMainWndSettingsDlg::SetControlMouseWheelEnable(bool enable)\n{\n    m_unit_combo.SetMouseWheelEnable(enable);\n    m_double_click_combo.SetMouseWheelEnable(enable);\n    m_font_size_edit.SetMouseWheelEnable(enable);\n    m_memory_display_combo.SetMouseWheelEnable(enable);\n}\n\nbool CMainWndSettingsDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_FONT_STATIC },\n        { CtrlTextInfo::C0, IDC_FONT_NAME_EDIT },\n        { CtrlTextInfo::R1, IDC_FONT_SIZE_STATIC },\n        { CtrlTextInfo::R2, IDC_FONT_SIZE_EDIT },\n        { CtrlTextInfo::R3, IDC_SET_FONT_BUTTON, CtrlTextInfo::W16 }\n        });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L2, IDC_TXT_COLOR_LABEL_STATIC },\n        { CtrlTextInfo::L1, IDC_TEXT_COLOR_STATIC },\n        { CtrlTextInfo::C0, IDC_SPECIFY_EACH_ITEM_COLOR_CHECK, CtrlTextInfo::W16 },\n        { CtrlTextInfo::R1, IDC_RESOTRE_SKIN_DEFAULT_BUTTON, CtrlTextInfo::W16 }\n    });\n\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_DISPLAY_TEXT_SETTING_BUTTON, CtrlTextInfo::W16 }\n    });\n\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_MEMORY_DISPLAY_MODE_STATIC },\n        { CtrlTextInfo::C0, IDC_MEMORY_DISPLAY_COMBO }\n    });\n\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_DOUBLE_CLICK_ACTION_STATIC },\n        { CtrlTextInfo::C0, IDC_DOUBLE_CLICK_COMBO },\n        { CtrlTextInfo::L1, IDC_EXE_PATH_STATIC },\n        { CtrlTextInfo::C0, IDC_EXE_PATH_EDIT },\n        { CtrlTextInfo::R1, IDC_BROWSE_BUTTON }\n    });\n\n    return true;\n}\n\nvoid CMainWndSettingsDlg::DrawStaticColor()\n{\n    //CCommon::FillStaticColor(m_color_static, m_data.text_color);\n    if (m_data.text_colors.empty())\n        return;\n    if (m_data.specify_each_item_color)\n    {\n        int color_num{ static_cast<int>(m_data.text_colors.size()) };\n        if (color_num > 16)\n            color_num = 16;\n        m_color_static.SetColorNum(color_num);\n        int index{};\n        for (const auto& item : m_data.text_colors)\n        {\n            m_color_static.SetFillColor(index, item.second);\n            index++;\n        }\n        m_color_static.Invalidate();\n    }\n    else\n    {\n        m_color_static.SetFillColor(m_data.text_colors.begin()->second);\n    }\n}\n\nvoid CMainWndSettingsDlg::IniUnitCombo()\n{\n    m_unit_combo.ResetContent();\n    m_unit_combo.AddString(CCommon::LoadText(IDS_AUTO));\n    if (m_data.unit_byte)\n    {\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" KB/s\")));\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" MB/s\")));\n    }\n    else\n    {\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" Kb/s\")));\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" Mb/s\")));\n    }\n    m_unit_combo.SetCurSel(static_cast<int>(m_data.speed_unit));\n}\n\nvoid CMainWndSettingsDlg::EnableControl()\n{\n    bool exe_path_enable = (m_data.double_click_action == DoubleClickAction::SEPCIFIC_APP);\n    CWnd* pWnd{};\n    pWnd = GetDlgItem(IDC_EXE_PATH_STATIC);\n    if (pWnd != nullptr)\n        pWnd->ShowWindow(exe_path_enable ? SW_SHOW : SW_HIDE);\n    pWnd = GetDlgItem(IDC_EXE_PATH_EDIT);\n    if (pWnd != nullptr)\n        pWnd->ShowWindow(exe_path_enable ? SW_SHOW : SW_HIDE);\n    pWnd = GetDlgItem(IDC_BROWSE_BUTTON);\n    if (pWnd != nullptr)\n        pWnd->ShowWindow(exe_path_enable ? SW_SHOW : SW_HIDE);\n}\n\nvoid CMainWndSettingsDlg::DoDataExchange(CDataExchange* pDX)\n{\n    DDX_Control(pDX, IDC_TEXT_COLOR_STATIC, m_color_static);\n    CTabDlg::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_HIDE_UNIT_CHECK, m_hide_unit_chk);\n    DDX_Control(pDX, IDC_UNIT_COMBO, m_unit_combo);\n    DDX_Control(pDX, IDC_FONT_SIZE_EDIT, m_font_size_edit);\n    DDX_Control(pDX, IDC_DOUBLE_CLICK_COMBO, m_double_click_combo);\n    DDX_Control(pDX, IDC_MEMORY_DISPLAY_COMBO, m_memory_display_combo);\n}\n\n\nBEGIN_MESSAGE_MAP(CMainWndSettingsDlg, CTabDlg)\n    //ON_EN_CHANGE(IDC_UPLOAD_EDIT, &CMainWndSettingsDlg::OnEnChangeUploadEdit)\n    //ON_EN_CHANGE(IDC_DOWNLOAD_EDIT, &CMainWndSettingsDlg::OnEnChangeDownloadEdit)\n    //ON_EN_CHANGE(IDC_CPU_EDIT, &CMainWndSettingsDlg::OnEnChangeCpuEdit)\n    //ON_EN_CHANGE(IDC_MEMORY_EDIT, &CMainWndSettingsDlg::OnEnChangeMemoryEdit)\n    //ON_BN_CLICKED(IDC_SET_COLOR_BUTTON1, &CMainWndSettingsDlg::OnBnClickedSetColorButton1)\n    //ON_BN_CLICKED(IDC_SET_DEFAULT_BUTTON, &CMainWndSettingsDlg::OnBnClickedSetDefaultButton)\n    ON_BN_CLICKED(IDC_SET_FONT_BUTTON, &CMainWndSettingsDlg::OnBnClickedSetFontButton)\n    ON_BN_CLICKED(IDC_SWITCH_UP_DOWN_CHECK, &CMainWndSettingsDlg::OnBnClickedSwitchUpDownCheck)\n    ON_BN_CLICKED(IDC_FULLSCREEN_HIDE_CHECK, &CMainWndSettingsDlg::OnBnClickedFullscreenHideCheck)\n    ON_BN_CLICKED(IDC_SPEED_SHORT_MODE_CHECK2, &CMainWndSettingsDlg::OnBnClickedSpeedShortModeCheck2)\n    ON_CBN_SELCHANGE(IDC_UNIT_COMBO, &CMainWndSettingsDlg::OnCbnSelchangeUnitCombo)\n    ON_BN_CLICKED(IDC_HIDE_UNIT_CHECK, &CMainWndSettingsDlg::OnBnClickedHideUnitCheck)\n    ON_BN_CLICKED(IDC_HIDE_PERCENTAGE_CHECK, &CMainWndSettingsDlg::OnBnClickedHidePercentageCheck)\n    ON_MESSAGE(WM_STATIC_CLICKED, &CMainWndSettingsDlg::OnStaticClicked)\n    ON_BN_CLICKED(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK, &CMainWndSettingsDlg::OnBnClickedSpecifyEachItemColorCheck)\n    ON_CBN_SELCHANGE(IDC_DOUBLE_CLICK_COMBO, &CMainWndSettingsDlg::OnCbnSelchangeDoubleClickCombo)\n    ON_BN_CLICKED(IDC_SEPARATE_VALUE_UNIT_CHECK, &CMainWndSettingsDlg::OnBnClickedSeparateValueUnitCheck)\n    ON_BN_CLICKED(IDC_UNIT_BYTE_RADIO, &CMainWndSettingsDlg::OnBnClickedUnitByteRadio)\n    ON_BN_CLICKED(IDC_UNIT_BIT_RADIO, &CMainWndSettingsDlg::OnBnClickedUnitBitRadio)\n    ON_BN_CLICKED(IDC_SHOW_TOOL_TIP_CHK, &CMainWndSettingsDlg::OnBnClickedShowToolTipChk)\n    ON_BN_CLICKED(IDC_BROWSE_BUTTON, &CMainWndSettingsDlg::OnBnClickedBrowseButton)\n    ON_BN_CLICKED(IDC_DISPLAY_TEXT_SETTING_BUTTON, &CMainWndSettingsDlg::OnBnClickedDisplayTextSettingButton)\n    ON_CBN_SELCHANGE(IDC_MEMORY_DISPLAY_COMBO, &CMainWndSettingsDlg::OnCbnSelchangeMemoryDisplayCombo)\n    ON_BN_CLICKED(IDC_ALWAYS_ON_TOP_CHECK, &CMainWndSettingsDlg::OnBnClickedAlwaysOnTopCheck)\n    ON_BN_CLICKED(IDC_MOUSE_PENETRATE_CHECK, &CMainWndSettingsDlg::OnBnClickedMousePenetrateCheck)\n    ON_BN_CLICKED(IDC_LOCK_WINDOW_POS_CHECK, &CMainWndSettingsDlg::OnBnClickedLockWindowPosCheck)\n    ON_BN_CLICKED(IDC_ALOW_OUT_OF_BORDER_CHECK, &CMainWndSettingsDlg::OnBnClickedAlowOutOfBorderCheck)\n    ON_BN_CLICKED(IDC_RESOTRE_SKIN_DEFAULT_BUTTON, &CMainWndSettingsDlg::OnBnClickedResotreSkinDefaultButton)\n    ON_EN_CHANGE(IDC_FONT_SIZE_EDIT, &CMainWndSettingsDlg::OnEnChangeFontSizeEdit)\nEND_MESSAGE_MAP()\n\n\n// CMainWndSettingsDlg 消息处理程序\n\n\nBOOL CMainWndSettingsDlg::OnInitDialog()\n{\n    CTabDlg::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n\n    //初始化各控件状态\n    SetDlgItemText(IDC_FONT_NAME_EDIT, m_data.font.name);\n    //wchar_t buff[16];\n    //swprintf_s(buff, L\"%d\", m_data.font_size);\n    //SetDlgItemText(IDC_FONT_SIZE_EDIT, buff);\n    m_font_size_edit.SetRange(5, 72);\n    m_font_size_edit.SetValue(m_data.font.size);\n\n    //SetDlgItemText(IDC_UPLOAD_EDIT, m_data.disp_str.Get(TDI_UP).c_str());\n    //SetDlgItemText(IDC_DOWNLOAD_EDIT, m_data.disp_str.Get(TDI_DOWN).c_str());\n    //SetDlgItemText(IDC_CPU_EDIT, m_data.disp_str.Get(TDI_CPU).c_str());\n    //SetDlgItemText(IDC_MEMORY_EDIT, m_data.disp_str.Get(TDI_MEMORY).c_str());\n\n    ((CButton*)GetDlgItem(IDC_SWITCH_UP_DOWN_CHECK))->SetCheck(m_data.swap_up_down);\n    ((CButton*)GetDlgItem(IDC_FULLSCREEN_HIDE_CHECK))->SetCheck(m_data.hide_main_wnd_when_fullscreen);\n    ((CButton*)GetDlgItem(IDC_SPEED_SHORT_MODE_CHECK2))->SetCheck(m_data.speed_short_mode);\n    ((CButton*)GetDlgItem(IDC_SEPARATE_VALUE_UNIT_CHECK))->SetCheck(m_data.separate_value_unit_with_space);\n    ((CButton*)GetDlgItem(IDC_SHOW_TOOL_TIP_CHK))->SetCheck(m_data.show_tool_tip);\n\n    m_color_static.SetLinkCursor();\n    DrawStaticColor();\n\n    m_toolTip.Create(this);\n    m_toolTip.SetMaxTipWidth(theApp.DPI(300));\n    m_toolTip.AddTool(GetDlgItem(IDC_SPEED_SHORT_MODE_CHECK2), CCommon::LoadText(IDS_SPEED_SHORT_MODE_TIP));\n\n    if (m_data.unit_byte)\n        ((CButton*)GetDlgItem(IDC_UNIT_BYTE_RADIO))->SetCheck(TRUE);\n    else\n        ((CButton*)GetDlgItem(IDC_UNIT_BIT_RADIO))->SetCheck(TRUE);\n\n    IniUnitCombo();\n\n    m_hide_unit_chk.SetCheck(m_data.hide_unit);\n    if (m_data.speed_unit == SpeedUnit::AUTO)\n    {\n        m_hide_unit_chk.SetCheck(FALSE);\n        m_data.hide_unit = false;\n        m_hide_unit_chk.EnableWindow(FALSE);\n    }\n    ((CButton*)GetDlgItem(IDC_HIDE_PERCENTAGE_CHECK))->SetCheck(m_data.hide_percent);\n\n    if (m_text_disable)\n    {\n        //GetDlgItem(IDC_UPLOAD_EDIT)->EnableWindow(FALSE);\n        //GetDlgItem(IDC_DOWNLOAD_EDIT)->EnableWindow(FALSE);\n        //GetDlgItem(IDC_CPU_EDIT)->EnableWindow(FALSE);\n        //GetDlgItem(IDC_MEMORY_EDIT)->EnableWindow(FALSE);\n        EnableDlgCtrl(IDC_DISPLAY_TEXT_SETTING_BUTTON, false);\n        m_data.swap_up_down = false;\n        ((CButton*)GetDlgItem(IDC_SWITCH_UP_DOWN_CHECK))->SetCheck(FALSE);\n        GetDlgItem(IDC_SWITCH_UP_DOWN_CHECK)->EnableWindow(FALSE);\n        //GetDlgItem(IDC_SET_DEFAULT_BUTTON)->EnableWindow(FALSE);\n    }\n\n    CheckDlgButton(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK, m_data.specify_each_item_color);\n\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_CONNECTION_DETIAL));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_HISTORICAL_TRAFFIC));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_SHOW_HIDE_MORE_INFO));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_OPTION_SETTINGS));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_TASK_MANAGER));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_SPECIFIC_APP));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_CHANGE_SKIN));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_NONE));\n    m_double_click_combo.SetCurSel(static_cast<int>(m_data.double_click_action));\n\n    SetDlgItemText(IDC_EXE_PATH_EDIT, m_data.double_click_exe.c_str());\n    EnableControl();\n\n    //初始化内存显示方式下拉列表\n    m_memory_display_combo.AddString(CCommon::LoadText(IDS_USAGE_PERCENTAGE));\n    m_memory_display_combo.AddString(CCommon::LoadText(IDS_MEMORY_USED));\n    m_memory_display_combo.AddString(CCommon::LoadText(IDS_MEMORY_AVAILABLE));\n    m_memory_display_combo.SetCurSel(static_cast<int>(m_data.memory_display));\n\n    CheckDlgButton(IDC_ALWAYS_ON_TOP_CHECK, m_data.m_always_on_top);\n    CheckDlgButton(IDC_MOUSE_PENETRATE_CHECK, m_data.m_mouse_penetrate);\n    CheckDlgButton(IDC_LOCK_WINDOW_POS_CHECK, m_data.m_lock_window_pos);\n    CheckDlgButton(IDC_ALOW_OUT_OF_BORDER_CHECK, m_data.m_alow_out_of_border);\n\n    ////设置控件不响应鼠标滚轮消息\n    //m_unit_combo.SetMouseWheelEnable(false);\n    //m_double_click_combo.SetMouseWheelEnable(false);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\n//void CMainWndSettingsDlg::OnEnChangeUploadEdit()\n//{\n//  // TODO:  如果该控件是 RICHEDIT 控件，它将不\n//  // 发送此通知，除非重写 CTabDlg::OnInitDialog()\n//  // 函数并调用 CRichEditCtrl().SetEventMask()，\n//  // 同时将 ENM_CHANGE 标志“或”运算到掩码中。\n//\n//  // TODO:  在此添加控件通知处理程序代码\n//  CString tmp;\n//  GetDlgItemText(IDC_UPLOAD_EDIT, tmp);\n//  m_data.disp_str.Get(TDI_UP) = tmp;\n//}\n//\n//\n//void CMainWndSettingsDlg::OnEnChangeDownloadEdit()\n//{\n//  // TODO:  如果该控件是 RICHEDIT 控件，它将不\n//  // 发送此通知，除非重写 CTabDlg::OnInitDialog()\n//  // 函数并调用 CRichEditCtrl().SetEventMask()，\n//  // 同时将 ENM_CHANGE 标志“或”运算到掩码中。\n//\n//  // TODO:  在此添加控件通知处理程序代码\n//  CString tmp;\n//  GetDlgItemText(IDC_DOWNLOAD_EDIT, tmp);\n//  m_data.disp_str.Get(TDI_DOWN) = tmp;\n//}\n//\n//\n//void CMainWndSettingsDlg::OnEnChangeCpuEdit()\n//{\n//  // TODO:  如果该控件是 RICHEDIT 控件，它将不\n//  // 发送此通知，除非重写 CTabDlg::OnInitDialog()\n//  // 函数并调用 CRichEditCtrl().SetEventMask()，\n//  // 同时将 ENM_CHANGE 标志“或”运算到掩码中。\n//\n//  // TODO:  在此添加控件通知处理程序代码\n//  CString tmp;\n//  GetDlgItemText(IDC_CPU_EDIT, tmp);\n//  m_data.disp_str.Get(TDI_CPU) = tmp;\n//}\n//\n//\n//void CMainWndSettingsDlg::OnEnChangeMemoryEdit()\n//{\n//  // TODO:  如果该控件是 RICHEDIT 控件，它将不\n//  // 发送此通知，除非重写 CTabDlg::OnInitDialog()\n//  // 函数并调用 CRichEditCtrl().SetEventMask()，\n//  // 同时将 ENM_CHANGE 标志“或”运算到掩码中。\n//\n//  // TODO:  在此添加控件通知处理程序代码\n//  CString tmp;\n//  GetDlgItemText(IDC_MEMORY_EDIT, tmp);\n//  m_data.disp_str.Get(TDI_MEMORY) = tmp;\n//}\n\n\n//void CMainWndSettingsDlg::OnBnClickedSetDefaultButton()\n//{\n//  // TODO: 在此添加控件通知处理程序代码\n//  m_data.disp_str.Get(TDI_UP) = CCommon::LoadText(IDS_UPLOAD_DISP, _T(\": \"));\n//  m_data.disp_str.Get(TDI_DOWN) = CCommon::LoadText(IDS_DOWNLOAD_DISP, _T(\": \"));\n//  m_data.disp_str.Get(TDI_CPU) = L\"CPU: \";\n//  m_data.disp_str.Get(TDI_MEMORY) = CCommon::LoadText(IDS_MEMORY_DISP, _T(\": \"));\n//  SetDlgItemText(IDC_UPLOAD_EDIT, m_data.disp_str.Get(TDI_UP).c_str());\n//  SetDlgItemText(IDC_DOWNLOAD_EDIT, m_data.disp_str.Get(TDI_DOWN).c_str());\n//  SetDlgItemText(IDC_CPU_EDIT, m_data.disp_str.Get(TDI_CPU).c_str());\n//  SetDlgItemText(IDC_MEMORY_EDIT, m_data.disp_str.Get(TDI_MEMORY).c_str());\n//}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedSetFontButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    LOGFONT lf{};\n    lf.lfHeight = FontSizeToLfHeight(m_data.font.size);\n    lf.lfWeight = (m_data.font.bold ? FW_BOLD : FW_NORMAL);\n    lf.lfItalic = m_data.font.italic;\n    lf.lfUnderline = m_data.font.underline;\n    lf.lfStrikeOut = m_data.font.strike_out;\n    lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;\n    //wcsncpy_s(lf.lfFaceName, m_data.font.name.GetString(), 32);\n    CCommon::WStringCopy(lf.lfFaceName, 32, m_data.font.name.GetString());\n    CCommon::NormalizeFont(lf);\n    CFontDialog fontDlg(&lf);   //构造字体对话框，初始选择字体为之前字体\n    if (IDOK == fontDlg.DoModal())     // 显示字体对话框\n    {\n        //获取字体信息\n        m_data.font.name = fontDlg.GetFaceName();\n        m_data.font.size = fontDlg.GetSize() / 10;\n        m_data.font.bold = (fontDlg.IsBold() != FALSE);\n        m_data.font.italic = (fontDlg.IsItalic() != FALSE);\n        m_data.font.underline = (fontDlg.IsUnderline() != FALSE);\n        m_data.font.strike_out = (fontDlg.IsStrikeOut() != FALSE);\n        //将字体信息显示出来\n        SetDlgItemText(IDC_FONT_NAME_EDIT, m_data.font.name);\n        SetDlgItemText(IDC_FONT_SIZE_EDIT, std::to_wstring(m_data.font.size).c_str());\n    }\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedSwitchUpDownCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.swap_up_down = (((CButton*)GetDlgItem(IDC_SWITCH_UP_DOWN_CHECK))->GetCheck() != 0);\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedFullscreenHideCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.hide_main_wnd_when_fullscreen = (((CButton*)GetDlgItem(IDC_FULLSCREEN_HIDE_CHECK))->GetCheck() != 0);\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedSpeedShortModeCheck2()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.speed_short_mode = (((CButton*)GetDlgItem(IDC_SPEED_SHORT_MODE_CHECK2))->GetCheck() != 0);\n}\n\n\nvoid CMainWndSettingsDlg::OnCbnSelchangeUnitCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.speed_unit = static_cast<SpeedUnit>(m_unit_combo.GetCurSel());\n    if (m_data.speed_unit == SpeedUnit::AUTO)\n    {\n        m_hide_unit_chk.SetCheck(FALSE);\n        m_data.hide_unit = false;\n        m_hide_unit_chk.EnableWindow(FALSE);\n    }\n    else\n    {\n        m_hide_unit_chk.EnableWindow(TRUE);\n    }\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedHideUnitCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.hide_unit = (m_hide_unit_chk.GetCheck() != 0);\n}\n\n\nBOOL CMainWndSettingsDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    if (pMsg->message == WM_MOUSEMOVE)\n        m_toolTip.RelayEvent(pMsg);\n\n    return CTabDlg::PreTranslateMessage(pMsg);\n}\n\n\nvoid CMainWndSettingsDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //获取字体设置\n    int font_size;\n    font_size = m_font_size_edit.GetValue();\n    if (font_size > MAX_FONT_SIZE || font_size < MIN_FONT_SIZE)\n    {\n        CString info;\n        info.Format(CCommon::LoadText(IDS_FONT_SIZE_WARNING), MIN_FONT_SIZE, MAX_FONT_SIZE);\n        MessageBox(info, NULL, MB_OK | MB_ICONWARNING);\n    }\n    else\n    {\n        m_data.font.size = font_size;\n    }\n    GetDlgItemText(IDC_FONT_NAME_EDIT, m_data.font.name);\n\n    CTabDlg::OnOK();\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedHidePercentageCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.hide_percent = (((CButton*)GetDlgItem(IDC_HIDE_PERCENTAGE_CHECK))->GetCheck() != 0);\n}\n\n\nafx_msg LRESULT CMainWndSettingsDlg::OnStaticClicked(WPARAM wParam, LPARAM lParam)\n{\n    switch (::GetDlgCtrlID(((CWnd*)wParam)->m_hWnd))\n    {\n    case IDC_TEXT_COLOR_STATIC:\n    {\n        //设置文本颜色\n        if (m_data.specify_each_item_color)\n        {\n            CMainWndColorDlg colorDlg(m_data.text_colors);\n            if (colorDlg.DoModal() == IDOK)\n            {\n                m_data.text_colors = colorDlg.GetColors();\n                DrawStaticColor();\n            }\n        }\n        else if (!m_data.text_colors.empty())\n        {\n            CMFCColorDialogEx colorDlg(m_data.text_colors.begin()->second, 0, this);\n            if (colorDlg.DoModal() == IDOK)\n            {\n                m_data.text_colors.begin()->second = colorDlg.GetColor();\n                DrawStaticColor();\n            }\n        }\n        break;\n    }\n    default:\n        break;\n    }\n    return 0;\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedSpecifyEachItemColorCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.specify_each_item_color = (((CButton*)GetDlgItem(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK))->GetCheck() != 0);\n    DrawStaticColor();\n}\n\n\nvoid CMainWndSettingsDlg::OnCbnSelchangeDoubleClickCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.double_click_action = static_cast<DoubleClickAction>(m_double_click_combo.GetCurSel());\n    EnableControl();\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedSeparateValueUnitCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.separate_value_unit_with_space = (((CButton*)GetDlgItem(IDC_SEPARATE_VALUE_UNIT_CHECK))->GetCheck() != 0);\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedUnitByteRadio()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.unit_byte = true;\n    IniUnitCombo();\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedUnitBitRadio()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.unit_byte = false;\n    IniUnitCombo();\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedShowToolTipChk()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.show_tool_tip = (((CButton*)GetDlgItem(IDC_SHOW_TOOL_TIP_CHK))->GetCheck() != 0);\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedBrowseButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CString szFilter = CCommon::LoadText(IDS_EXE_FILTER);\n    CFileDialogEx fileDlg(TRUE, NULL, szFilter);\n    if (IDOK == fileDlg.DoModal())\n    {\n        m_data.double_click_exe = fileDlg.GetPathName();\n        SetDlgItemText(IDC_EXE_PATH_EDIT, m_data.double_click_exe.c_str());\n    }\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedDisplayTextSettingButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CDisplayTextSettingDlg dlg(m_data.disp_str, true);\n    dlg.DoModal();\n}\n\n\nvoid CMainWndSettingsDlg::OnCbnSelchangeMemoryDisplayCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.memory_display = static_cast<MemoryDisplay>(m_memory_display_combo.GetCurSel());\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedAlwaysOnTopCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.m_always_on_top = IsDlgButtonChecked(IDC_ALWAYS_ON_TOP_CHECK) != 0;\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedMousePenetrateCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.m_mouse_penetrate = IsDlgButtonChecked(IDC_MOUSE_PENETRATE_CHECK) != 0;\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedLockWindowPosCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.m_lock_window_pos = IsDlgButtonChecked(IDC_LOCK_WINDOW_POS_CHECK) != 0;\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedAlowOutOfBorderCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.m_alow_out_of_border = IsDlgButtonChecked(IDC_ALOW_OUT_OF_BORDER_CHECK) != 0;\n}\n\n\nvoid CMainWndSettingsDlg::OnBnClickedResotreSkinDefaultButton()\n{\n    SkinSettingData skin_setting_data;\n    CTrafficMonitorDlg* pMainWnd = CTrafficMonitorDlg::Instance();\n    if (pMainWnd != nullptr)\n    {\n        CSkinManager::SkinSettingDataFronSkin(skin_setting_data, pMainWnd->GetCurSkin());\n        m_data.text_colors = skin_setting_data.text_colors;\n        m_data.specify_each_item_color = skin_setting_data.specify_each_item_color;\n        m_data.font = skin_setting_data.font;\n\n        SetDlgItemText(IDC_FONT_NAME_EDIT, m_data.font.name);\n        SetDlgItemText(IDC_FONT_SIZE_EDIT, std::to_wstring(m_data.font.size).c_str());\n        CheckDlgButton(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK, m_data.specify_each_item_color);\n        DrawStaticColor();\n    }\n}\n\n\nvoid CMainWndSettingsDlg::OnEnChangeFontSizeEdit()\n{\n    m_data.font.size = m_font_size_edit.GetValue();\n}\n"
  },
  {
    "path": "TrafficMonitor/MainWndSettingsDlg.h",
    "content": "﻿#pragma once\n#include \"ColorStatic.h\"\n#include \"afxwin.h\"\n#include \"SpinEdit.h\"\n#include \"TabDlg.h\"\n#include \"MainWndColorDlg.h\"\n#include \"ComboBox2.h\"\n\n// CMainWndSettingsDlg 对话框\n\nclass CMainWndSettingsDlg : public CTabDlg\n{\n    DECLARE_DYNAMIC(CMainWndSettingsDlg)\n\npublic:\n    CMainWndSettingsDlg(CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~CMainWndSettingsDlg();\n\n    //选项设置数据\n    MainWndSettingData m_data;\n\n    bool m_text_disable{ false };   //如果为true，则不允许设置“显示文本”，并不允许交换上传和下载的位置\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_MAIN_WND_SETTINGS_DIALOG };\n#endif\n\n\nprotected:\n    //控件变量\n    CColorStatic m_color_static;\n    CToolTipCtrl m_toolTip;\n    CComboBox2 m_unit_combo;\n    CButton m_hide_unit_chk;\n    CSpinEdit m_font_size_edit;\n    CComboBox2 m_double_click_combo;\n    CComboBox2 m_memory_display_combo;\n\nprotected:\n    void DrawStaticColor();\n    void IniUnitCombo();\n    void EnableControl();\n\n    virtual void SetControlMouseWheelEnable(bool enable) override;\n    virtual bool InitializeControls() override;\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    //afx_msg void OnEnChangeUploadEdit();\n    //afx_msg void OnEnChangeDownloadEdit();\n    //afx_msg void OnEnChangeCpuEdit();\n    //afx_msg void OnEnChangeMemoryEdit();\n    //afx_msg void OnBnClickedSetDefaultButton();\n    afx_msg void OnBnClickedSetFontButton();\n    afx_msg void OnBnClickedSwitchUpDownCheck();\n    afx_msg void OnBnClickedFullscreenHideCheck();\n    afx_msg void OnBnClickedSpeedShortModeCheck2();\n    afx_msg void OnCbnSelchangeUnitCombo();\n    afx_msg void OnBnClickedHideUnitCheck();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    virtual void OnOK();\n    afx_msg void OnBnClickedHidePercentageCheck();\nprotected:\n    afx_msg LRESULT OnStaticClicked(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnBnClickedSpecifyEachItemColorCheck();\n    afx_msg void OnCbnSelchangeDoubleClickCombo();\n    afx_msg void OnBnClickedSeparateValueUnitCheck();\n    afx_msg void OnBnClickedUnitByteRadio();\n    afx_msg void OnBnClickedUnitBitRadio();\n    afx_msg void OnBnClickedShowToolTipChk();\n    afx_msg void OnBnClickedBrowseButton();\n    afx_msg void OnBnClickedDisplayTextSettingButton();\n    afx_msg void OnCbnSelchangeMemoryDisplayCombo();\n    afx_msg void OnBnClickedAlwaysOnTopCheck();\n    afx_msg void OnBnClickedMousePenetrateCheck();\n    afx_msg void OnBnClickedLockWindowPosCheck();\n    afx_msg void OnBnClickedAlowOutOfBorderCheck();\n    afx_msg void OnBnClickedResotreSkinDefaultButton();\n    afx_msg void OnEnChangeFontSizeEdit();\n};\n"
  },
  {
    "path": "TrafficMonitor/MessageDlg.cpp",
    "content": "﻿// HelpDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"MessageDlg.h\"\n#include \"DrawCommon.h\"\n\n\n// CMessageDlg 对话框\n\n#define MESSAGE_DLG_ICON_SIZE (theApp.DPI(32))\n#define MESSAGE_DLG_ICON_VERTIAL_MARGIN (theApp.DPI(12))\n\nIMPLEMENT_DYNAMIC(CMessageDlg, CBaseDialog)\n\nCMessageDlg::CMessageDlg(CWnd* pParent /*=NULL*/)\n\t: CBaseDialog(IDD_MESSAGE_DIALOG, pParent)\n{\n\n}\n\nCMessageDlg::~CMessageDlg()\n{\n}\n\nvoid CMessageDlg::SetWindowTitle(LPCTSTR str)\n{\n\tm_title = str;\n}\n\nvoid CMessageDlg::SetInfoText(LPCTSTR str)\n{\n\tm_info = str;\n}\n\nvoid CMessageDlg::SetMessageText(LPCTSTR str)\n{\n\tm_message = str;\n}\n\n//void CMessageDlg::SetLinkInfo(LPCTSTR text, LPCTSTR url)\n//{\n//\tm_link_text = text;\n//\tm_link_url = url;\n//}\n\nvoid CMessageDlg::SetMessageIcon(HICON hIcon)\n{\n    m_icon = hIcon;\n}\n\nvoid CMessageDlg::SetStandarnMessageIcon(StandardIcon standard_icon)\n{\n\tHICON hIcon;\n\tPCWSTR icon{};\n\tswitch (standard_icon)\n\t{\n\tcase SI_INFORMATION:\n\t\ticon = IDI_INFORMATION;\n\t\tbreak;\n\tcase SI_WARNING:\n\t\ticon = IDI_WARNING;\n\t\tbreak;\n\tcase SI_ERROR:\n\t\ticon = IDI_ERROR;\n\t\tbreak;\n\t}\n\tHRESULT hr = LoadIconWithScaleDown(NULL, icon, theApp.DPI(32), theApp.DPI(32), &hIcon);\n\tif (SUCCEEDED(hr))\n\t\tSetMessageIcon(hIcon);\n}\n\nvoid CMessageDlg::DoDataExchange(CDataExchange* pDX)\n{\n\tCBaseDialog::DoDataExchange(pDX);\n\tDDX_Control(pDX, IDC_HELP_EDIT, m_message_edit);\n\tDDX_Control(pDX, IDC_INFO_STATIC, m_info_static);\n}\n\n\nBEGIN_MESSAGE_MAP(CMessageDlg, CBaseDialog)\n\tON_WM_GETMINMAXINFO()\n\t//ON_NOTIFY(NM_CLICK, IDC_SYSLINK1, &CMessageDlg::OnNMClickSyslink1)\n    ON_WM_PAINT()\n    ON_WM_SIZE()\nEND_MESSAGE_MAP()\n\n\n// CMessageDlg 消息处理程序\n\n\nBOOL CMessageDlg::OnInitDialog()\n{\n\tCBaseDialog::OnInitDialog();\n\n\t// TODO:  在此添加额外的初始化\n\n\tSetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), FALSE);\t\t// 设置小图标\n\n\t//获取初始时窗口的大小\n\tCRect rect;\n\tGetWindowRect(rect);\n\tm_min_size.cx = rect.Width();\n\tm_min_size.cy = rect.Height();\n\n\tSetWindowText(m_title);\n\tm_info_static.SetWindowText(m_info);\n\tm_message_edit.SetWindowText(m_message);\n\n\t//CWnd* pLinkCtrl = GetDlgItem(IDC_SYSLINK1);\n\t//if (pLinkCtrl != nullptr)\n\t//{\n\t//\tpLinkCtrl->ShowWindow(m_show_link_ctrl);\n\t//\tpLinkCtrl->SetWindowText(_T(\"<a>\") + m_link_text + _T(\"</a>\"));\n\t//}\n\n    //设置图标的位置\n    if (m_icon != NULL)\n    {\n\t\tCRect rc_info = GetControlRect(&m_info_static);\n\t\t//设置Static控件水平位置，为图标腾出空间\n\t\trc_info.left = rc_info.left + MESSAGE_DLG_ICON_SIZE + theApp.DPI(8);\n\t\t//设置Static控件的垂直位置\n\t\trc_info.MoveToY(rc_info.top + MESSAGE_DLG_ICON_VERTIAL_MARGIN);\n\t\tm_info_static.MoveWindow(rc_info);\n\n\t\tCRect rc_edit = GetControlRect(&m_message_edit);\n\t\trc_edit.top += (MESSAGE_DLG_ICON_VERTIAL_MARGIN * 2);\n\t\tm_icon_pos.x = rc_edit.left;\n\t\tm_icon_pos.y = (rc_edit.top - MESSAGE_DLG_ICON_SIZE) / 2;\n\t\tm_message_edit.MoveWindow(rc_edit);\n    }\n\n\t//没有图标，且消息标题为空时，隐藏Static控件\n\tif (m_icon == NULL && m_info.IsEmpty())\n\t{\n\t\tCRect rc_info = GetControlRect(&m_info_static);\n\t\tCRect rc_edit = GetControlRect(&m_message_edit);\n\t\trc_edit.top = rc_info.top;\n\t\tm_message_edit.MoveWindow(rc_edit);\n\t\tm_info_static.ShowWindow(SW_HIDE);\n\t}\n\n\treturn TRUE;  // return TRUE unless you set the focus to a control\n\t\t\t\t  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CMessageDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)\n{\n\t// TODO: 在此添加消息处理程序代码和/或调用默认值\n\t//限制窗口最小大小\n\tlpMMI->ptMinTrackSize.x = m_min_size.cx;\t\t//设置最小宽度\n\tlpMMI->ptMinTrackSize.y = m_min_size.cy;\t\t//设置最小高度\n\n\tCBaseDialog::OnGetMinMaxInfo(lpMMI);\n}\n\n\n//void CMessageDlg::OnNMClickSyslink1(NMHDR *pNMHDR, LRESULT *pResult)\n//{\n//\t// TODO: 在此添加控件通知处理程序代码\n//\tif(!m_link_url.IsEmpty())\n//\t\tShellExecute(NULL, _T(\"open\"), m_link_url, NULL, NULL, SW_SHOW);\t//打开超链接\n//\n//\t*pResult = 0;\n//}\n\n\nvoid CMessageDlg::OnPaint()\n{\n    CPaintDC dc(this); // device context for painting\n                       // TODO: 在此处添加消息处理程序代码\n                       // 不为绘图消息调用 CBaseDialog::OnPaint()\n\n    CDrawCommon draw;\n    draw.Create(&dc, this);\n    draw.DrawIcon(m_icon, m_icon_pos, CSize(MESSAGE_DLG_ICON_SIZE, MESSAGE_DLG_ICON_SIZE));\n}\n\n\nvoid CMessageDlg::OnSize(UINT nType, int cx, int cy)\n{\n    CBaseDialog::OnSize(nType, cx, cy);\n\n\tif (m_info_static.GetSafeHwnd() != NULL && m_icon != NULL)\n\t{\n\t\tCRect rc_info = GetControlRect(&m_info_static);\n\t\trc_info.right = cx;\n\t\tm_info_static.MoveWindow(rc_info);\n\t}\n\tif (m_message_edit.GetSafeHwnd() != NULL)\n\t{\n\t\tCRect rc_edit = GetControlRect(&m_message_edit);\n\t\t//设置Edit控件的垂直位置\n\t\tCRect rc_ok = GetControlRect(IDOK);\n\t\tif (!rc_ok.IsRectEmpty())\n\t\t{\n\t\t\trc_edit.bottom = rc_ok.top - theApp.DPI(6);\n\t\t\tm_message_edit.MoveWindow(rc_edit);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "TrafficMonitor/MessageDlg.h",
    "content": "﻿#pragma once\n#include \"afxwin.h\"\n#include \"BaseDialog.h\"\n\n// CMessageDlg 对话框\n\nclass CMessageDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CMessageDlg)\n\npublic:\n\tCMessageDlg(CWnd* pParent = NULL);   // 标准构造函数\n\tvirtual ~CMessageDlg();\n\n\tvoid SetWindowTitle(LPCTSTR str);\t//设置窗口标题\n\tvoid SetInfoText(LPCTSTR str);\t\t//设置消息标题\n\tvoid SetMessageText(LPCTSTR str);\t//设置消息文本\n\t//void ShowLinkStatic(bool show = true) { m_show_link_ctrl = show; }\n\t//void SetLinkInfo(LPCTSTR text, LPCTSTR url);\n    void SetMessageIcon(HICON hIcon);\n\n\t//消息对话框的系统标准图标\n\tenum StandardIcon\n\t{\n\t\tSI_INFORMATION,\n\t\tSI_WARNING,\n\t\tSI_ERROR\n\t};\n\n\t//为消息对话框框设置系统标准图标\n\tvoid SetStandarnMessageIcon(StandardIcon standard_icon);\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_MESSAGE_DIALOG };\n#endif\n\nprotected:\n\tCEdit m_message_edit;\n\tCSize m_min_size;\t\t//窗口的最小大小\n\tCStatic m_info_static;\n\n\tCString m_title;\n\tCString m_info;\n\tCString m_message;\n\n\t//CString m_link_text;\n\t//CString m_link_url;\n\n    HICON m_icon{};\n    CPoint m_icon_pos{};        //图标的位置\n\n\t//bool m_show_link_ctrl{ false };\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n\tDECLARE_MESSAGE_MAP()\n\npublic:\n\tvirtual BOOL OnInitDialog();\n\tafx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);\n\t//afx_msg void OnNMClickSyslink1(NMHDR *pNMHDR, LRESULT *pResult);\n    afx_msg void OnPaint();\n    afx_msg void OnSize(UINT nType, int cx, int cy);\n};\n"
  },
  {
    "path": "TrafficMonitor/NetworkInfoDlg.cpp",
    "content": "﻿// CNetworkInfoDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"NetworkInfoDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// CNetworkInfoDlg 对话框\n\nIMPLEMENT_DYNAMIC(CNetworkInfoDlg, CBaseDialog)\n\nCNetworkInfoDlg::CNetworkInfoDlg(vector<NetWorkConection>& adapters, MIB_IFROW* pIfRow, int connection_selected, CWnd* pParent /*=NULL*/)\n    : CBaseDialog(IDD_NETWORK_INFO_DIALOG, pParent), m_connections(adapters), m_pIfRow(pIfRow), m_connection_selected(connection_selected)\n{\n    m_current_connection = connection_selected;\n}\n\nCNetworkInfoDlg::~CNetworkInfoDlg()\n{\n}\n\n\nvoid CNetworkInfoDlg::ShowInfo()\n{\n    CString temp;\n    MIB_IFROW& network_info = GetConnectIfTable(m_connection_selected);\n    //接口名\n    m_info_list.SetItemText(0, 1, network_info.wszName);\n    //接口描述\n    m_info_list.SetItemText(1, 1, CCommon::StrToUnicode((const char*)network_info.bDescr).c_str());\n    //连接类型\n    switch (network_info.dwType)\n    {\n    case IF_TYPE_OTHER: temp = CCommon::LoadText(IDS_IF_TYPE_OTHER); break;\n    case IF_TYPE_ETHERNET_CSMACD: temp = CCommon::LoadText(IDS_IF_TYPE_ETHERNET_CSMACD); break;\n    case IF_TYPE_ISO88025_TOKENRING: temp = CCommon::LoadText(IDS_IF_TYPE_ISO88025_TOKENRING); break;\n    case IF_TYPE_FDDI: temp = CCommon::LoadText(IDS_IF_TYPE_FDDI); break;\n    case IF_TYPE_PPP: temp = CCommon::LoadText(IDS_IF_TYPE_PPP); break;\n    case IF_TYPE_SOFTWARE_LOOPBACK: temp = CCommon::LoadText(IDS_IF_TYPE_SOFTWARE_LOOPBACK); break;\n    case IF_TYPE_ATM: temp = CCommon::LoadText(IDS_IF_TYPE_ATM); break;\n    case IF_TYPE_IEEE80211: temp = CCommon::LoadText(IDS_IF_TYPE_IEEE80211); break;\n    case IF_TYPE_TUNNEL: temp = CCommon::LoadText(IDS_IF_TYPE_TUNNEL); break;\n    case IF_TYPE_IEEE1394: temp = CCommon::LoadText(IDS_IF_TYPE_IEEE1394); break;\n    case IF_TYPE_IEEE80216_WMAN: temp = CCommon::LoadText(IDS_IF_TYPE_IEEE80216_WMAN); break;\n    case IF_TYPE_WWANPP: temp = CCommon::LoadText(IDS_IF_TYPE_WWANPP); break;\n    case IF_TYPE_WWANPP2: temp = CCommon::LoadText(IDS_IF_TYPE_WWANPP2); break;\n    default: temp = CCommon::LoadText(IDS_UNKNOW_CONNECTION); break;\n    }\n    m_info_list.SetItemText(2, 1, temp);\n    //速度\n    temp.Format(_T(\"%dMbps\"), network_info.dwSpeed / 1000000);\n    m_info_list.SetItemText(3, 1, temp);\n    //适配器物理地址\n    temp = _T(\"\");\n    char buff[3];\n    for (size_t i{}; i < network_info.dwPhysAddrLen; i++)\n    {\n        sprintf_s(buff, \"%.2x\", network_info.bPhysAddr[i]);\n        temp += buff;\n        if (i != network_info.dwPhysAddrLen - 1)\n            temp += _T('-');\n    }\n    m_info_list.SetItemText(4, 1, temp);\n    //IP地址\n    m_info_list.SetItemText(5, 1, GetConnection(m_connection_selected).ip_address.c_str());\n    //子网掩码\n    m_info_list.SetItemText(6, 1, GetConnection(m_connection_selected).subnet_mask.c_str());\n    //默认网关\n    m_info_list.SetItemText(7, 1, GetConnection(m_connection_selected).default_gateway.c_str());\n    //连接状态\n    switch (network_info.dwOperStatus)\n    {\n    case IF_OPER_STATUS_NON_OPERATIONAL: temp = CCommon::LoadText(IDS_IF_OPER_STATUS_NON_OPERATIONAL); break;\n    case IF_OPER_STATUS_UNREACHABLE: temp = CCommon::LoadText(IDS_IF_OPER_STATUS_UNREACHABLE); break;\n    case IF_OPER_STATUS_DISCONNECTED: temp = CCommon::LoadText(IDS_IF_OPER_STATUS_DISCONNECTED); break;\n    case IF_OPER_STATUS_CONNECTING: temp = CCommon::LoadText(IDS_IF_OPER_STATUS_CONNECTING); break;\n    case IF_OPER_STATUS_CONNECTED: temp = CCommon::LoadText(IDS_IF_OPER_STATUS_CONNECTED); break;\n    case IF_OPER_STATUS_OPERATIONAL: temp = CCommon::LoadText(IDS_IF_OPER_STATUS_OPERATIONAL); break;\n        //case IfOperStatusUp:\n        //    temp = CCommon::LoadText(IDS_IF_OPER_STATUS_UP);\n        //    break;\n        //case IfOperStatusDown:\n        //case IfOperStatusNotPresent:\n        //case IfOperStatusLowerLayerDown:\n        //    temp = CCommon::LoadText(IDS_IF_OPER_STATUS_DOWN);\n        //    break;\n        //case IfOperStatusTesting:\n        //case IfOperStatusUnknown:\n        //    temp = CCommon::LoadText(IDS_UNKNOW_STATUS);\n        //    break;\n        //case IfOperStatusDormant:\n        //    temp = CCommon::LoadText(IDS_IF_OPER_STATUS_DORMANT);\n            //break;\n    default: temp = CCommon::LoadText(IDS_UNKNOW_STATUS); break;\n    }\n    m_info_list.SetItemText(8, 1, temp);\n    //已接收字节数\n    temp.Format(_T(\"%s (%s)\"), CCommon::IntToString(network_info.dwInOctets, true, true), CCommon::DataSizeToString(network_info.dwInOctets));\n    m_info_list.SetItemText(9, 1, temp);\n    //已发送字节数\n    temp.Format(_T(\"%s (%s)\"), CCommon::IntToString(network_info.dwOutOctets, true, true), CCommon::DataSizeToString(network_info.dwOutOctets));\n    m_info_list.SetItemText(10, 1, temp);\n    //自程序启动以来已接收字节数\n    unsigned __int64 in_bytes_since_start;\n    in_bytes_since_start = network_info.dwInOctets - GetConnection(m_connection_selected).in_bytes;\n    temp.Format(_T(\"%s (%s)\"), CCommon::IntToString(in_bytes_since_start, true, true), CCommon::DataSizeToString(in_bytes_since_start));\n    m_info_list.SetItemText(11, 1, temp);\n    //自程序启动以来已发送字节数\n    unsigned __int64 out_bytes_since_start;\n    out_bytes_since_start = network_info.dwOutOctets - GetConnection(m_connection_selected).out_bytes;\n    temp.Format(_T(\"%s (%s)\"), CCommon::IntToString(out_bytes_since_start, true, true), CCommon::DataSizeToString(out_bytes_since_start));\n    m_info_list.SetItemText(12, 1, temp);\n\n    //显示当前选择指示\n    CString str;\n    str.Format(_T(\"%d/%d\"), m_connection_selected + 1, m_connections.size());\n    SetDlgItemText(IDC_INDEX_STATIC, str);\n    CFont* font = GetFont();\n    CWnd* index_static = GetDlgItem(IDC_INDEX_STATIC);\n    if (m_current_connection == m_connection_selected && !theApp.m_cfg_data.m_select_all)\n        index_static->SetFont(&m_font_bold);\n    else\n        index_static->SetFont(font);\n}\n\nvoid CNetworkInfoDlg::GetProgramElapsedTime()\n{\n    //程序已运行时间\n    SYSTEMTIME current_time, time;\n    GetLocalTime(&current_time);\n    time = CCommon::CompareSystemTime(current_time, m_start_time);\n    CString temp;\n    temp.Format(CCommon::LoadText(IDS_HOUR_MINUTE_SECOND), time.wHour, time.wMinute, time.wSecond);\n    m_info_list.SetItemText(13, 1, temp);\n}\n\nMIB_IFROW& CNetworkInfoDlg::GetConnectIfTable(int connection_index)\n{\n    static MIB_IFROW nouse{};\n    if (connection_index >= 0 && connection_index < static_cast<int>(m_connections.size()))\n    {\n        int index = m_connections[connection_index].index;\n        if (m_pIfRow != nullptr)\n            return m_pIfRow[index];\n    }\n    return nouse;\n}\n\nNetWorkConection CNetworkInfoDlg::GetConnection(int connection_index)\n{\n    if (connection_index >= 0 && connection_index < static_cast<int>(m_connections.size()))\n        return m_connections[connection_index];\n    else\n        return NetWorkConection();\n}\n\nUINT CNetworkInfoDlg::GetInternetIPThreadFunc(LPVOID lpParam)\n{\n    CCommon::SetThreadLanguage(theApp.m_general_data.language);\t\t//设置线程语言\n    CNetworkInfoDlg* p_instance = (CNetworkInfoDlg*)lpParam;\n    wstring ip_address, ip_location;\n\n    //IPV4\n    CCommon::GetInternetIp2(ip_address, ip_location, false);\t\t\t//获取外网IP地址，\n    if (!IsWindow(p_instance->GetSafeHwnd()))\t\t//如果当前对话框已经销毁，则退出线程\n        return 0;\n    if (!ip_address.empty())\n    {\n        CString info;\n        if (ip_location.empty())\n            info = ip_address.c_str();\n        else\n            info.Format(_T(\"%s (%s)\"), ip_address.c_str(), ip_location.c_str());\n        p_instance->m_info_list.SetItemText(14, 1, info);\n    }\n    else\n    {\n        p_instance->m_info_list.SetItemText(14, 1, CCommon::LoadText(IDS_GET_FAILED));\n    }\n\n    //IPV6\n    wstring ipv6_address, ipv6_location;\n    CCommon::GetInternetIp2(ip_address, ip_location, true);\t\t\t//获取外网IP地址，\n    if (!IsWindow(p_instance->GetSafeHwnd()))\t\t//如果当前对话框已经销毁，则退出线程\n        return 0;\n    if (!ip_address.empty())\n    {\n        CString info;\n        if (ip_location.empty())\n            info = ip_address.c_str();\n        else\n            info.Format(_T(\"%s (%s)\"), ip_address.c_str(), ip_location.c_str());\n        p_instance->m_info_list.SetItemText(15, 1, info);\n    }\n    else\n    {\n        p_instance->m_info_list.SetItemText(15, 1, CCommon::LoadText(IDS_GET_FAILED));\n    }\n\n    p_instance->m_ip_acquired = true;\n    return 0;\n}\n\nCString CNetworkInfoDlg::GetDialogName() const\n{\n    return _T(\"NetworkInfoDlg\");\n}\n\nvoid CNetworkInfoDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_INFO_LIST1, m_info_list);\n}\n\n\nBEGIN_MESSAGE_MAP(CNetworkInfoDlg, CBaseDialog)\n    ON_COMMAND(ID_COPY_TEXT, &CNetworkInfoDlg::OnCopyText)\n    ON_NOTIFY(NM_RCLICK, IDC_INFO_LIST1, &CNetworkInfoDlg::OnNMRClickInfoList1)\n    ON_WM_CLOSE()\n    ON_BN_CLICKED(IDC_PREVIOUS_BUTTON, &CNetworkInfoDlg::OnBnClickedPreviousButton)\n    ON_BN_CLICKED(IDC_NEXT_BUTTON, &CNetworkInfoDlg::OnBnClickedNextButton)\n    ON_WM_TIMER()\n    ON_WM_MOUSEWHEEL()\n    ON_NOTIFY(NM_DBLCLK, IDC_INFO_LIST1, &CNetworkInfoDlg::OnNMDblclkInfoList1)\nEND_MESSAGE_MAP()\n\n\n// CNetworkInfoDlg 消息处理程序\n\n\nBOOL CNetworkInfoDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_INFO), FALSE);\t\t// 设置小图标\n\n    //重新获取IP地址\n    CAdapterCommon::RefreshIpAddress(m_connections);\n\n    //初始化列表控件\n    CRect rect;\n    m_info_list.GetClientRect(rect);\n    m_info_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);\n    int width0, width1;\n    width0 = rect.Width() / 4;\n    width1 = rect.Width() - width0 - theApp.DPI(20) - 1;\n    m_info_list.InsertColumn(0, CCommon::LoadText(IDS_ITEM), LVCFMT_LEFT, width0);\t\t//插入第0列\n    m_info_list.InsertColumn(1, CCommon::LoadText(IDS_VALUE), LVCFMT_LEFT, width1);\t\t//插入第1列\n\n    //向列表中插入行\n    m_info_list.InsertItem(0, CCommon::LoadText(IDS_INTERFACE_NAME));\n    m_info_list.InsertItem(1, CCommon::LoadText(IDS_INTERFACE_DESCRIPTION));\n    m_info_list.InsertItem(2, CCommon::LoadText(IDS_CONNECTION_TYPE));\n    m_info_list.InsertItem(3, CCommon::LoadText(IDS_SPEED));\n    m_info_list.InsertItem(4, CCommon::LoadText(IDS_ADAPTER_PHYSICAL_ADDRESS));\n    m_info_list.InsertItem(5, CCommon::LoadText(IDS_IP_ADDRESS));\n    m_info_list.InsertItem(6, CCommon::LoadText(IDS_SUBNET_MASK));\n    m_info_list.InsertItem(7, CCommon::LoadText(IDS_DEFAULT_GATEWAY));\n    m_info_list.InsertItem(8, CCommon::LoadText(IDS_OPERATIONAL_STATUS));\n    m_info_list.InsertItem(9, CCommon::LoadText(IDS_BYTES_RECEIVED));\n    m_info_list.InsertItem(10, CCommon::LoadText(IDS_BYTES_SENT));\n    m_info_list.InsertItem(11, CCommon::LoadText(IDS_BYTES_RECEIVED_SINCE_START));\n    m_info_list.InsertItem(12, CCommon::LoadText(IDS_BYTES_SENT_SINCE_START));\n    m_info_list.InsertItem(13, CCommon::LoadText(IDS_PROGRAM_ELAPSED_TIME));\n    m_info_list.InsertItem(14, CCommon::LoadText(IDS_INTERNET_IP_ADDRESS, _T(\" (ipv4)\")));\n    m_info_list.InsertItem(15, CCommon::LoadText(IDS_INTERNET_IP_ADDRESS, _T(\" (ipv6)\")));\n    //if (theApp.m_cfg_data.m_show_internet_ip)\n    //{\n    //\tm_info_list.SetItemText(14, 1, CCommon::LoadText(IDS_ACQUIRING, _T(\"...\")));\n    //\tm_info_list.SetItemText(15, 1, CCommon::LoadText(IDS_ACQUIRING, _T(\"...\")));\n    //}\n    //else\n    //{\n    m_info_list.SetItemText(14, 1, CCommon::LoadText(IDS_DOUBLE_CLICK_TO_ACQUIRE));\n    m_info_list.SetItemText(15, 1, CCommon::LoadText(IDS_DOUBLE_CLICK_TO_ACQUIRE));\n    //}\n\n    //显示列表中的信息\n    LOGFONT lf{};\n    GetFont()->GetLogFont(&lf);\n    lf.lfWeight = FW_BOLD;\n    m_font_bold.CreateFontIndirect(&lf);\n    ShowInfo();\n    GetProgramElapsedTime();\n\n    //CCommon::GetInternetIp();\n    //if (theApp.m_cfg_data.m_show_internet_ip)\n //       m_pGetIPThread = AfxBeginThread(GetInternetIPThreadFunc, this);\t\t//启动获取外网IP的线程\n\n    //SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);\t\t//取消置顶\n    m_info_list.GetToolTips()->SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);\n\n    CCommon::LoadMenuResource(m_menu, IDR_INFO_MENU); //装载右键菜单\n\n    SetTimer(CONNECTION_DETAIL_TIMER, 1000, NULL);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CNetworkInfoDlg::OnCopyText()\n{\n    // TODO: 在此添加命令处理程序代码\n    if (!CCommon::CopyStringToClipboard(wstring(m_selected_string)))\n        MessageBox(CCommon::LoadText(IDS_COPY_TO_CLIPBOARD_FAILED), NULL, MB_ICONWARNING);\n}\n\n\nvoid CNetworkInfoDlg::OnNMRClickInfoList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n\n    //获取鼠标点击处的文本\n    int item, sub_item;\n    item = pNMItemActivate->iItem;\n    sub_item = pNMItemActivate->iSubItem;\n    m_selected_string = m_info_list.GetItemText(item, sub_item);\n\n    //弹出右键菜单\n    CMenu* pContextMenu = m_menu.GetSubMenu(0);\t//获取第一个弹出菜单\n    CPoint point1;\t//定义一个用于确定光标位置的位置\n    GetCursorPos(&point1);\t//获取当前光标的位置，以便使得菜单可以跟随光标\n    pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this); //在指定位置显示弹出菜单\n\n    *pResult = 0;\n}\n\n\nvoid CNetworkInfoDlg::OnClose()\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    //对话框关闭时强制结束获取IP地址的线程\n    //if(theApp.m_cfg_data.m_show_internet_ip)\n //       TerminateThread(m_pGetIPThread->m_hThread, 0);\n    CBaseDialog::OnClose();\n}\n\n\nvoid CNetworkInfoDlg::OnBnClickedPreviousButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    if (m_connections.size() > 1 && m_connection_selected > 0)\n    {\n        m_connection_selected--;\n        ShowInfo();\n    }\n}\n\n\nvoid CNetworkInfoDlg::OnBnClickedNextButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    if (m_connections.size() > 1 && m_connection_selected < m_connections.size() - 1)\n    {\n        m_connection_selected++;\n        ShowInfo();\n    }\n}\n\n\nBOOL CNetworkInfoDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    if (pMsg->message == WM_KEYDOWN)\n    {\n        if (pMsg->wParam == VK_LEFT)\n        {\n            OnBnClickedPreviousButton();\n            return TRUE;\n        }\n        if (pMsg->wParam == VK_RIGHT)\n        {\n            OnBnClickedNextButton();\n            return TRUE;\n        }\n    }\n\n    return CBaseDialog::PreTranslateMessage(pMsg);\n}\n\n\n\nvoid CNetworkInfoDlg::OnTimer(UINT_PTR nIDEvent)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    if (nIDEvent == CONNECTION_DETAIL_TIMER)\n    {\n        GetProgramElapsedTime();\n    }\n\n    CBaseDialog::OnTimer(nIDEvent);\n}\n\nBOOL CNetworkInfoDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    //通过鼠标滚轮翻页\n    if (zDelta > 0)\n    {\n        OnBnClickedPreviousButton();\n    }\n    if (zDelta < 0)\n    {\n        OnBnClickedNextButton();\n    }\n\n    return CBaseDialog::OnMouseWheel(nFlags, zDelta, pt);\n}\n\n\nvoid CNetworkInfoDlg::OnNMDblclkInfoList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n    if (/*!theApp.m_cfg_data.m_show_internet_ip && */!m_ip_acquired && (pNMItemActivate->iItem == 14 || pNMItemActivate->iItem == 15))\t\t//双击了IP地址一行时\n    {\n        m_info_list.SetItemText(14, 1, CCommon::LoadText(IDS_ACQUIRING, _T(\"...\")));\n        m_info_list.SetItemText(15, 1, CCommon::LoadText(IDS_ACQUIRING, _T(\"...\")));\n        m_pGetIPThread = AfxBeginThread(GetInternetIPThreadFunc, this);\n    }\n    *pResult = 0;\n}\n"
  },
  {
    "path": "TrafficMonitor/NetworkInfoDlg.h",
    "content": "﻿#pragma once\n#include\"Common.h\"\n#include \"afxcmn.h\"\n#include \"AdapterCommon.h\"\n#include \"BaseDialog.h\"\n#include \"ListCtrlEx.h\"\n\n// CNetworkInfoDlg 对话框\n\nclass CNetworkInfoDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CNetworkInfoDlg)\n\npublic:\n    CNetworkInfoDlg(vector<NetWorkConection>& adapters, MIB_IFROW* pIfRow, int connection_selected, CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~CNetworkInfoDlg();\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_NETWORK_INFO_DIALOG };\n#endif\n\n    SYSTEMTIME m_start_time;\t\t//程序启动的时间\n\nprotected:\n\n    vector<NetWorkConection>& m_connections;\n    MIB_IFROW* m_pIfRow;\n    int m_connection_selected;\t\t//当前对话框显示的连接\n    int m_current_connection;\t\t//初始选择的连接\n\n    CListCtrlEx m_info_list;\n    CMenu m_menu;\n    CString m_selected_string;\n    CFont m_font_bold;\t\t//默认字体的粗体\n\n    CWinThread* m_pGetIPThread;\t\t\t//获取外网IP的线程\n    bool m_ip_acquired{ false };        //如果已获取外网ip地址，则为true\n\n    //void GetIPAddress();\t//获取IP地址\n    void ShowInfo();\n    void GetProgramElapsedTime();\n    MIB_IFROW& GetConnectIfTable(int connection_index);    //获取当前选择的网络连接的MIB_IFROW对象。connection_index为m_connections中的索引\n    NetWorkConection GetConnection(int connection_index); //获取当前选择的网络连接的NetWorkConection对象。connection_index为m_connections中的索引\n\n    //获取外网IP的线程函数\n    static UINT GetInternetIPThreadFunc(LPVOID lpParam);\n\n    virtual CString GetDialogName() const override;\n\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n    DECLARE_MESSAGE_MAP()\n\n    virtual BOOL OnInitDialog();\npublic:\n    afx_msg void OnCopyText();\n    afx_msg void OnNMRClickInfoList1(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnClose();\n    afx_msg void OnBnClickedPreviousButton();\n    afx_msg void OnBnClickedNextButton();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    afx_msg void OnTimer(UINT_PTR nIDEvent);\n    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);\n    afx_msg void OnNMDblclkInfoList1(NMHDR* pNMHDR, LRESULT* pResult);\n};\n"
  },
  {
    "path": "TrafficMonitor/Nullable.hpp",
    "content": "﻿#pragma once\n#include <cstddef>\n#include <functional>\n#include <type_traits>\n#include <stdexcept>\n#include <tuple>\n\ntemplate <class T>\nclass AlignedStorage\n{\nprivate:\n    alignas(T) std::byte m_buffer[sizeof(T)]{};\n\npublic:\n    AlignedStorage() = default;\n    ~AlignedStorage() = default;\n    T& Get() noexcept\n    {\n        return *reinterpret_cast<T*>(m_buffer);\n    };\n    const T& Get() const noexcept\n    {\n        return *reinterpret_cast<T*>(m_buffer);\n    };\n    std::byte* operator&() noexcept\n    {\n        return m_buffer;\n    };\n};\n\n// 皆不保证多线程操作安全\n/**\n * @brief CNullable<T>的默认删除器，注意重载operator()的参数为T*\n *\n * @tparam T 要删除的类型\n */\ntemplate <class T>\nstruct NullableDefaultDeleter\n{\n    void operator()(T* p_this)\n    {\n        p_this->~T();\n    }\n};\n/**\n * @brief 可空对象，允许对象在无默认构造函数的情况下仍然可以执行默认构造，代价是必须在使用对象之前执行Construct方法\n *\n * @tparam T 实际存储的对象\n * @tparam Deleter T的删除器\n */\ntemplate <class T, class Deleter = NullableDefaultDeleter<T>>\nclass CNullable\n{\n    using StorageType = AlignedStorage<T>;\n    using RawType = std::decay_t<T>;\n    template <class... Args>\n    static void EmplaceAt(RawType* p_object, Args&&... args)\n    {\n        ::new (p_object) RawType(std::forward<Args>(args)...);\n    }\n\npublic:\n    CNullable(Deleter deleter = {})\n        : m_storage{deleter} {}\n    ~CNullable()\n    {\n        if (m_has_value)\n        {\n            DestroySelf();\n        }\n    }\n    CNullable(const CNullable& other)\n        : m_has_value{other.m_has_value}, m_storage{static_cast<Deleter>(other.m_storage)}\n    {\n        if (other)\n        {\n            EmplaceAt(m_storage.GetPointerUnsafe(), other.m_storage.GetUnsafe());\n        }\n    }\n    CNullable& operator=(const CNullable& other)\n    {\n        this->m_has_value = other.m_has_value;\n        Deleter& ref_deleter = m_storage;\n        ref_deleter = static_cast<Deleter>(other.m_storage);\n        if (other)\n        {\n            EmplaceAt(m_storage.GetPointerUnsafe(), other.m_storage.GetUnsafe());\n        }\n    }\n    CNullable(CNullable&& other) noexcept\n        : m_has_value{other.m_has_value}, m_storage{std::move(static_cast<Deleter>(other.m_storage))}\n    {\n        if (other)\n        {\n            EmplaceAt(m_storage.GetPointerUnsafe(), std::move(other.m_storage.GetUnsafe()));\n        }\n    }\n    CNullable& operator=(CNullable&& other) noexcept\n    {\n        this->m_has_value = other.m_has_value;\n        Deleter& ref_deleter = m_storage;\n        ref_deleter = std::move(static_cast<Deleter>(other.m_storage));\n        if (other)\n        {\n            EmplaceAt(m_storage.GetPointerUnsafe(), std::move(other.m_storage.GetUnsafe()));\n        }\n    }\n\n    template <class... Args>\n    void Construct(Args&&... args)\n    {\n        if (m_has_value)\n        {\n            DestroySelf();\n            m_has_value = false;\n        }\n\n        EmplaceAt(m_storage.GetPointerUnsafe(), std::forward<Args>(args)...);\n\n        m_has_value = true;\n    }\n    const T& GetUnsafe() const noexcept\n    {\n        return m_storage.GetUnsafe();\n    }\n    T& GetUnsafe() noexcept\n    {\n        return m_storage.GetUnsafe();\n    }\n    const T& Get() const noexcept\n    {\n        Check();\n        return GetUnsafe();\n    }\n    T& Get() noexcept\n    {\n        Check();\n        return GetUnsafe();\n    }\n    bool HasValue() const noexcept\n    {\n        return m_has_value;\n    }\n    operator bool() const noexcept\n    {\n        return HasValue();\n    }\n\nprivate:\n    void DestroySelf()\n    {\n        auto&& ref_deleter = static_cast<Deleter&>(m_storage);\n        ref_deleter(m_storage.GetPointerUnsafe());\n    }\n    void Check() const\n    {\n        if (!m_has_value)\n        {\n            throw CallNullObjectError{};\n        }\n    }\n\n    class CallNullObjectError : public std::runtime_error\n    {\n    public:\n        CallNullObjectError()\n            : std::runtime_error{\"Value is uninitialized!\"} {}\n        ~CallNullObjectError() override = default;\n    };\n\n    class StorageAndEboDeleter : public Deleter\n    {\n    private:\n        StorageType m_storage;\n\n    public:\n        explicit StorageAndEboDeleter(Deleter deleter)\n            : Deleter{deleter} {}\n        ~StorageAndEboDeleter() = default;\n        StorageAndEboDeleter(const StorageAndEboDeleter&) = delete;\n        StorageAndEboDeleter& operator=(const StorageAndEboDeleter&) = delete;\n\n        const T& GetUnsafe() const noexcept\n        {\n            return *static_cast<const T*>(static_cast<const void*>(&m_storage));\n        }\n        T& GetUnsafe() noexcept\n        {\n            return *static_cast<T*>(static_cast<void*>(&m_storage));\n        }\n        const T* GetPointerUnsafe() const noexcept\n        {\n            return static_cast<const T*>(static_cast<const void*>(&m_storage));\n        }\n        T* GetPointerUnsafe() noexcept\n        {\n            return static_cast<T*>(static_cast<void*>(&m_storage));\n        }\n    };\n    bool m_has_value{false};\n    StorageAndEboDeleter m_storage;\n};\ntemplate <class T, class Deleter = NullableDefaultDeleter<T>>\nauto MakeNullableObject(Deleter deleter)\n    -> CNullable<T, Deleter>\n{\n    return {deleter};\n}\n\n/**\n * @brief 可延迟构造的对象，用于预先分配内存，在有使用该对象的请求时立即构造此对象，对象必须可默认构造\n *\n * @tparam T 要被应用这一特性的类型\n * @tparam Deleter T的删除器，默认为NullableDefaultDeleter<T>\n */\ntemplate <class T, class Deleter = NullableDefaultDeleter<T>>\nclass CLazyConstructable\n{\npublic:\n    CLazyConstructable() = default;\n    ~CLazyConstructable() = default;\n    T& Get()\n    {\n        if (m_content)\n        {\n            return m_content.GetUnsafe();\n        }\n        else\n        {\n            m_content.Construct();\n            return m_content.GetUnsafe();\n        }\n    }\n\nprivate:\n    CNullable<T, Deleter> m_content{};\n};\n\ntemplate <class T, class Deleter, class Tuple>\nclass CLazyConstructableWithInitializer;\n\ntemplate <class T, class Deleter, template <class...> class Container, class... InitArgs>\nclass CLazyConstructableWithInitializer<T, Deleter, Container<InitArgs...>>\n{\nprivate:\n    using ArgsContainer = Container<InitArgs...>;\n    using ArgsInitFunction = std::function<ArgsContainer()>;\n    constexpr static std::size_t init_args_size = sizeof...(InitArgs);\n    template <class Tuple, std::size_t... Indexs>\n    void ConstructHelper(Tuple&& args, std::index_sequence<Indexs...>)\n    {\n        m_content.Construct(std::get<Indexs>(args)...);\n    }\n\npublic:\n    CLazyConstructableWithInitializer(ArgsInitFunction init_function)\n        : m_init_function{init_function}\n    {\n    }\n    ~CLazyConstructableWithInitializer() = default;\n    T& Get()\n    {\n        if (m_content)\n        {\n            return m_content.GetUnsafe();\n        }\n        else\n        {\n            auto init_args{std::move(m_init_function())};\n            ConstructHelper(\n                init_args,\n                std::make_index_sequence<std::tuple_size<decltype(init_args)>{}>{});\n            return m_content.GetUnsafe();\n        }\n    }\n    bool HasValue() const noexcept\n    {\n        return m_content.HasValue();\n    }\n    operator bool() const noexcept\n    {\n        return HasValue();\n    }\n\nprivate:\n    CNullable<T, Deleter> m_content{};\n    ArgsInitFunction m_init_function{};\n};\n\ntemplate <class T, class... Args>\nusing DefaultCLazyConstructableWithInitializer =\n    CLazyConstructableWithInitializer<T, NullableDefaultDeleter<T>, std::tuple<Args...>>;\n"
  },
  {
    "path": "TrafficMonitor/OptionsDlg.cpp",
    "content": "﻿// OptionsDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"OptionsDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// COptionsDlg 对话框\n\nIMPLEMENT_DYNAMIC(COptionsDlg, CBaseDialog)\n\nCOptionsDlg::COptionsDlg(int tab, CWnd* pParent /*=NULL*/)\n    : CBaseDialog(IDD_OPTIONS_DIALOG, pParent), m_tab_selected{ tab }\n{\n\n}\n\nCOptionsDlg::~COptionsDlg()\n{\n}\n\nCString COptionsDlg::GetDialogName() const\n{\n    return OPTION_DLG_NAME;\n}\n\nvoid COptionsDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_TAB1, m_tab);\n}\n\n\nBEGIN_MESSAGE_MAP(COptionsDlg, CBaseDialog)\n    ON_WM_SIZE()\n    ON_BN_CLICKED(IDC_APPLY_BUTTON, &COptionsDlg::OnBnClickedApplyButton)\nEND_MESSAGE_MAP()\n\n\n// COptionsDlg 消息处理程序\n\n\nBOOL COptionsDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_SETTINGS), FALSE);       // 设置小图标\n\n    //创建子对话框\n    m_tab1_dlg.Create(IDD_MAIN_WND_SETTINGS_DIALOG, &m_tab);\n    m_tab2_dlg.Create(IDD_TASKBAR_SETTINGS_DIALOG, &m_tab);\n    m_tab3_dlg.Create(IDD_GENERAL_SETTINGS_DIALOG, &m_tab);\n\n    //保存子对话框\n    m_tab_vect.push_back(&m_tab1_dlg);\n    m_tab_vect.push_back(&m_tab2_dlg);\n    m_tab_vect.push_back(&m_tab3_dlg);\n\n    //获取子对话框的初始高度\n    for (const auto* pDlg : m_tab_vect)\n    {\n        CRect rect;\n        pDlg->GetWindowRect(rect);\n        m_tab_height.push_back(rect.Height());\n    }\n\n    //添加对话框\n    m_tab.AddWindow(&m_tab1_dlg, CCommon::LoadText(IDS_MAIN_WINDOW_SETTINGS));\n    m_tab.AddWindow(&m_tab2_dlg, CCommon::LoadText(IDS_TASKBAR_WINDOW_SETTINGS));\n    m_tab.AddWindow(&m_tab3_dlg, CCommon::LoadText(IDS_GENERAL_SETTINGS));\n\n    //为每个标签添加图标\n    CImageList ImageList;\n    ImageList.Create(theApp.DPI(16), theApp.DPI(16), ILC_COLOR32 | ILC_MASK, 2, 2);\n    ImageList.Add(theApp.GetMenuIcon(IDI_MAIN_WINDOW));\n    ImageList.Add(theApp.GetMenuIcon(IDI_TASKBAR_WINDOW));\n    ImageList.Add(theApp.GetMenuIcon(IDI_SETTINGS));\n    m_tab.SetImageList(&ImageList);\n    ImageList.Detach();\n\n    m_tab.SetItemSize(CSize(theApp.DPI(60), theApp.DPI(24)));\n    m_tab.AdjustTabWindowSize();\n\n    //为每个子窗口设置滚动信息\n    for (size_t i = 0; i < m_tab_vect.size(); i++)\n    {\n        m_tab_vect[i]->SetScrollbarInfo(m_tab.m_tab_rect.Height(), m_tab_height[i]);\n    }\n\n    //设置默认选中的标签\n    if (m_tab_selected < 0 || m_tab_selected >= m_tab.GetItemCount())\n        m_tab_selected = 0;\n    m_tab.SetCurTab(m_tab_selected);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid COptionsDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    m_tab1_dlg.OnOK();\n    m_tab2_dlg.OnOK();\n    m_tab3_dlg.OnOK();\n\n    CBaseDialog::OnOK();\n}\n\n\nvoid COptionsDlg::OnSize(UINT nType, int cx, int cy)\n{\n    CBaseDialog::OnSize(nType, cx, cy);\n\n    // TODO: 在此处添加消息处理程序代码\n    if (nType != SIZE_MINIMIZED)\n    {\n        //为每个子窗口设置滚动信息\n        for (size_t i = 0; i < m_tab_vect.size(); i++)\n        {\n            m_tab_vect[i]->SetScrollbarInfo(m_tab.m_tab_rect.Height(), m_tab_height[i]);\n        }\n    }\n}\n\n\nvoid COptionsDlg::OnCancel()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    m_tab3_dlg.OnCancel();\n\n    CBaseDialog::OnCancel();\n}\n\n\nvoid COptionsDlg::OnBnClickedApplyButton()\n{\n    m_tab2_dlg.SaveColorSettingToDefaultStyle();\n    ::SendMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_SETTINGS_APPLIED, (WPARAM)this, 0);\n    for (size_t i = 0; i < m_tab_vect.size(); i++)\n    {\n        m_tab_vect[i]->OnSettingsApplied();\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/OptionsDlg.h",
    "content": "﻿#pragma once\n#include \"MainWndSettingsDlg.h\"\n#include \"TaskBarSettingsDlg.h\"\n#include \"GeneralSettingsDlg.h\"\n#include \"afxcmn.h\"\n#include \"CTabCtrlEx.h\"\n#include \"BaseDialog.h\"\n\n// COptionsDlg 对话框\n\n#define OPTION_DLG_NAME _T(\"OptionsDlg\")\n\nclass COptionsDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(COptionsDlg)\n\npublic:\n    COptionsDlg(int tab = 0, CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~COptionsDlg();\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_OPTIONS_DIALOG };\n#endif\n\n    CMainWndSettingsDlg m_tab1_dlg{ this };\n    CTaskBarSettingsDlg m_tab2_dlg{ this };\n    CGeneralSettingsDlg m_tab3_dlg{ this };\n\nprotected:\n    CTabCtrlEx m_tab;\n    int m_tab_selected;\n    std::vector<CTabDlg*> m_tab_vect;\n    std::vector<int> m_tab_height;\n\n    virtual CString GetDialogName() const override;\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    virtual void OnOK();\n    afx_msg void OnSize(UINT nType, int cx, int cy);\n    virtual void OnCancel();\n    afx_msg void OnBnClickedApplyButton();\n};\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/CPUUsage.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"CPUUsage.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n#include <powerbase.h>\n#include <sysinfoapi.h>\n\n\n///////////////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////////////\nCPdhCPUUsage::CPdhCPUUsage()\n    : CPdhQuery(theApp.m_win_version.GetMajorVersion() >= 10 ? _T(\"\\\\Processor Information(_Total)\\\\% Processor Utility\") : _T(\"\\\\Processor Information(_Total)\\\\% Processor Time\"))\n{\n}\n\nbool CPdhCPUUsage::GetCPUUsage(int& cpu_usage)\n{\n    double value{};\n    if (QueryValue(value))\n    {\n        cpu_usage = static_cast<int>(value);\n        if (cpu_usage > 100)\n            cpu_usage = 100;\n        return true;\n    }\n    return false;\n}\n\n///////////////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////////////\nCCPUUsage::CCPUUsage()\n{\n}\n\nvoid CCPUUsage::SetUseCPUTimes(bool use_get_system_times)\n{\n    if (m_use_get_system_times != use_get_system_times)\n    {\n        m_use_get_system_times = use_get_system_times;\n    }\n}\n\nint CCPUUsage::GetCpuUsage()\n{\n    int cpu_usage{};\n    if (m_use_get_system_times)\n    {\n        cpu_usage = GetCpuUsageByGetSystemTimes();\n    }\n    else\n    {\n        //如果通过pdh获取CPU利用率失败，采用GetSystemTimes获取\n        if (!m_pdh_cup_usage_query.GetCPUUsage(cpu_usage))\n        {\n            cpu_usage = GetCpuUsageByGetSystemTimes();\n            //写入日志\n            //static bool write_log = false;\n            //if (!write_log)\n            //{\n            //    CString str_log = CCommon::LoadTextFormat(IDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG, { fullCounterPath });\n            //    CCommon::WriteLog(str_log, theApp.m_log_path.c_str());\n            //    write_log = true;\n            //}\n        }\n    }\n    return cpu_usage;\n}\n\nint CCPUUsage::GetCpuUsageByGetSystemTimes()\n{\n    int cpu_usage{};\n    FILETIME idleTime;\n    FILETIME kernelTime;\n    FILETIME userTime;\n    GetSystemTimes(&idleTime, &kernelTime, &userTime);\n\n    __int64 idle = CCommon::CompareFileTime2(m_preidleTime, idleTime);\n    __int64 kernel = CCommon::CompareFileTime2(m_prekernelTime, kernelTime);\n    __int64 user = CCommon::CompareFileTime2(m_preuserTime, userTime);\n\n    if (kernel + user == 0)\n    {\n        cpu_usage = 0;\n    }\n    else\n    {\n        //（总的时间-空闲时间）/总的时间=占用cpu的时间就是使用率\n        cpu_usage = static_cast<int>(abs((kernel + user - idle) * 100 / (kernel + user)));\n    }\n    m_preidleTime = idleTime;\n    m_prekernelTime = kernelTime;\n    m_preuserTime = userTime;\n\n    return cpu_usage;\n}\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/CPUUsage.h",
    "content": "﻿#pragma once\n#include <Pdh.h>\n#include <PdhMsg.h>\n#include \"PdhQuery.h\"\n\nclass CPdhCPUUsage : public CPdhQuery\n{\npublic:\n    CPdhCPUUsage();\n\n    ~CPdhCPUUsage()\n    {\n    }\n\n    bool GetCPUUsage(int& cpu_usage);\n\n};\n\n//////////////////////////////////////////////////////////////////////////////////\nclass CCPUUsage\n{\npublic:\n    CCPUUsage();\n\n    ~CCPUUsage()\n    {}\n\n    void SetUseCPUTimes(bool use_get_system_times);\t\t//设置获取CPU利用率的方式，是通过GetSystemTimes还是Pdh\n    int GetCpuUsage();\n\nprivate:\n    int GetCpuUsageByGetSystemTimes();\n\nprivate:\n    bool m_use_get_system_times{ true };\t\t//是否使用GetSysTime这个API来获取CPU利用率\n\n    FILETIME m_preidleTime{};\n    FILETIME m_prekernelTime{};\n    FILETIME m_preuserTime{};\n\n    CPdhCPUUsage m_pdh_cup_usage_query;\n};\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/CpuFreq.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"CpuFreq.h\"\n#include <powerbase.h>\n#include <sysinfoapi.h>\n\n\n///////////////////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////////////////\n\ntypedef struct _PROCESSOR_POWER_INFORMATION {\n    ULONG Number;\n    ULONG MaxMhz;\n    ULONG CurrentMhz;\n    ULONG MhzLimit;\n    ULONG MaxIdleState;\n    ULONG CurrentIdleState;\n} PROCESSOR_POWER_INFORMATION, * PPROCESSOR_POWER_INFORMATION;\n\nCPdhCpuFreq::CPdhCpuFreq()\n    : CPdhQuery(_T(\"\\\\Processor Information(_Total)\\\\% Processor Performance\"))\n{\n    //获取max_cpu_freq\n    SYSTEM_INFO si;\n    GetSystemInfo(&si);\n    auto ppInfo = std::vector<PROCESSOR_POWER_INFORMATION>(si.dwNumberOfProcessors);\n    auto status = CallNtPowerInformation(POWER_INFORMATION_LEVEL::ProcessorInformation,\n        NULL, 0, &ppInfo[0], sizeof(PROCESSOR_POWER_INFORMATION) * ppInfo.size());\n    for (size_t i = 0; i < ppInfo.size(); i++)\n    {\n        max_cpu_freq = max(max_cpu_freq, ppInfo[i].MaxMhz / 1000.f);\n    }\n}\n\nbool CPdhCpuFreq::GetCpuFreq(float& freq)\n{\n    double value{};\n    if (QueryValue(value))\n    {\n        freq = value / 100 * max_cpu_freq;\n        return true;\n    }\n    return false;\n}\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/CpuFreq.h",
    "content": "﻿#pragma once\n#include <Pdh.h>\n#include <PdhMsg.h>\n#include \"PdhQuery.h\"\n\nclass CPdhCpuFreq : public CPdhQuery\n{\npublic:\n    CPdhCpuFreq();\n\n    // 调用此函数获取CPU频率。\n    // 注意：第二次调用此函数开始才能获取到值，两次调用的时间不应过短，最好大于200毫秒\n    bool GetCpuFreq(float& freq);\n\nprivate:\n    float max_cpu_freq = 0;\n};\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/DiskUsage.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"DiskUsage.h\"\n#include <algorithm>\n#include <cmath>\n\nCPdhDiskUsage::CPdhDiskUsage()\n    : CPdhQuery(_T(\"\\\\PhysicalDisk(*)\\\\% Idle Time\"))\n{\n    m_isAvailable = Initialize();\n    if (m_isAvailable)\n    {\n        // 预热：触发PDH内部初始化（首次QueryValues会填充实例列表）\n        std::vector<CounterValueItem> dummy;\n        QueryValues(dummy);\n        ExtractDiskNames();\n    }\n}\n\nCPdhDiskUsage::~CPdhDiskUsage()\n{\n}\n\nvoid CPdhDiskUsage::ExtractDiskNames()\n{\n    m_diskNames.clear();\n    std::vector<CounterValueItem> values;\n\n    if (!QueryValues(values))\n        return;\n\n    for (const auto& item : values)\n    {\n        CString name(item.name.c_str());\n        m_diskNames.push_back(name);\n    }\n}\n\nint CPdhDiskUsage::CalculateUtilization(double idleTime) const\n{\n    // 关键处理：NVMe/RAID等多队列磁盘的空闲时间可能 >100%\n    // 例如: 4队列磁盘空闲时间=400% → 实际空闲=100% → 利用率=0%\n    if (idleTime > 100.0)\n        idleTime = 100.0;\n\n    // 确保范围在0-100\n    idleTime = (std::max)(0.0, (std::min)(100.0, idleTime));\n\n    // 利用率 = 100% - 空闲时间\n    double utilization = 100.0 - idleTime;\n    return static_cast<int>(utilization + 0.5); // 四舍五入\n}\n\nbool CPdhDiskUsage::GetDiskUsage(int diskIndex, int& usage)\n{\n    usage = 0;\n    if (!m_isAvailable)\n        return false;\n\n    std::vector<CounterValueItem> values;\n    if (!QueryValues(values) || values.empty())\n        return false;\n\n    if (diskIndex >= 0 && diskIndex < static_cast<int>(values.size()))\n    {\n        usage = CalculateUtilization(values[diskIndex].value);\n        return true;\n    }\n    return false;\n\n}\n\nint CPdhDiskUsage::FindDiskIndex(const std::wstring diskName)\n{\n    int disk_index = -1;\n    for (int i = 0; i < static_cast<int>(m_diskNames.size()); i++)\n    {\n        if (diskName == m_diskNames[i].GetString())\n        {\n            disk_index = i;\n            break;\n        }\n    }\n    return disk_index;\n}\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/DiskUsage.h",
    "content": "﻿#pragma once\n#include \"PdhQuery.h\"\n\nclass CPdhDiskUsage : public CPdhQuery\n{\npublic:\n    CPdhDiskUsage();\n    ~CPdhDiskUsage();\n\n    // 获取指定物理磁盘的利用率（0-100）\n    // diskIndex: 0=第一个物理磁盘, 1=第二个...\n    // 返回值: true=成功, false=失败（首次调用通常失败，需间隔200ms+重试）\n    bool GetDiskUsage(int diskIndex, /*out*/ int& usage);\n\n    // 获取物理磁盘名称列表\n    const std::vector<CString>& GetDiskNames() const { return m_diskNames; }\n\n    //根据名称查找一个硬盘的序号\n    int FindDiskIndex(const std::wstring diskName);\n\n    // 检查磁盘监控是否可用\n    bool IsAvailable() const { return m_isAvailable; }\n\nprivate:\n    // 从计数器实例提取磁盘名称\n    void ExtractDiskNames();\n\n    // 处理空闲时间\n    int CalculateUtilization(double idleTime) const;\n\nprivate:\n    bool m_isAvailable{ false };\n    std::vector<CString> m_diskNames;  // 磁盘名称列表，按PDH返回顺序\n};"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/GpuUsage.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"GpuUsage.h\"\n\n///////////////////////////////////////////////////////////////////////////////////////////\n// CPdhGPUUsage 实现\n///////////////////////////////////////////////////////////////////////////////////////////\nCPdhGPUUsage::CPdhGPUUsage()\n: CPdhQuery(_T(\"\\\\GPU Engine(*)\\\\Utilization Percentage\"))\n{\n}\n\nCPdhGPUUsage::~CPdhGPUUsage()\n{\n}\n\nbool CPdhGPUUsage::GetGpuUsage(int& usage)\n{\n    if (isInitialized)\n    {\n        std::vector<CounterValueItem> valueItems;\n        if (QueryValues(valueItems))\n        {\n            if (!valueItems.empty())\n            {\n                //获取所有类型的利用率\n                std::map<std::wstring, double> gpu_usage_map;\n                for (const auto& item : valueItems)\n                {\n                    std::wstring item_name = item.name;\n                    size_t index = item.name.rfind(L'_');\n                    if (index != std::wstring::npos)\n                        item_name = item.name.substr(index + 1);\n                    gpu_usage_map[item_name] += item.value;\n                }\n                //查找所有类型中最大的值作为总利用率（同Windows任务管理器的处理）\n                double max_value = 0;\n                for (const auto& item : gpu_usage_map)\n                {\n                    if (item.second > max_value)\n                        max_value = item.second;\n                }\n\n                usage = static_cast<int>(max_value + 0.5);  // 四舍五入\n                usage = min(max(usage, 0), 100);        // 限制在0-100范围\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/GpuUsage.h",
    "content": "﻿#pragma once\n#include \"PdhQuery.h\"\n\n// GPU利用率监控类\nclass CPdhGPUUsage : public CPdhQuery\n{\npublic:\n    CPdhGPUUsage();\n    ~CPdhGPUUsage();\n\n    // 获取GPU利用率（0-100）\n    // 返回值: true=成功, false=失败\n    // 注意：首次调用通常返回false（PDH需要预热），建议间隔200ms以上再次调用\n    bool GetGpuUsage(/*out*/ int& usage);\n\n};\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/PdhQuery.cpp",
    "content": "#include \"stdafx.h\"\n#include \"PdhQuery.h\"\n\nCPdhQuery::CPdhQuery(LPCTSTR _fullCounterPath)\n    : fullCounterPath(_fullCounterPath)\n{\n    Initialize();\n}\n\nCPdhQuery::~CPdhQuery()\n{\n    //رղѯ\n    PdhCloseQuery(query);\n}\n\nbool CPdhQuery::Initialize()\n{\n    if (isInitialized)\n        return true;\n\n    PDH_STATUS status;\n    //򿪲ѯ\n    status = PdhOpenQuery(NULL, NULL, &query);\n    if (status != ERROR_SUCCESS)\n        return false;\n\n    //Ӽ\n    status = PdhAddCounter(query, fullCounterPath.GetString(), NULL, &counter);\n    //ȵPdhAddCounterʧʹPdhAddEnglishCounterһ\n    if (status != ERROR_SUCCESS)\n    {\n        status = PdhAddEnglishCounter(query, fullCounterPath.GetString(), NULL, &counter);\n        if (status != ERROR_SUCCESS)\n        {\n            PdhCloseQuery(query);\n            query = nullptr;\n            return false;\n        }\n    }\n\n    //ʼ\n    PdhCollectQueryData(query);\n    isInitialized = true;\n    return true;\n}\n\nbool CPdhQuery::QueryValue(double& value)\n{\n    if (!isInitialized)\n        return false;\n\n    //\n    PdhCollectQueryData(query);\n    PDH_FMT_COUNTERVALUE pdhValue;\n    DWORD dwValue;\n    PDH_STATUS status = PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, &dwValue, &pdhValue);\n    if (status != ERROR_SUCCESS)\n    {\n        return false;\n    }\n    value = pdhValue.doubleValue;\n    return true;\n}\n\nbool CPdhQuery::QueryValues(std::vector<CounterValueItem>& values)\n{\n    values.clear();\n    if (!isInitialized)\n        return false;\n\n    //\n    PdhCollectQueryData(query);\n    DWORD dwBufferSize = 0;         // Size of the pItems buffer\n    DWORD dwItemCount = 0;          // Number of items in the pItems buffer\n    PDH_FMT_COUNTERVALUE_ITEM* pItems = NULL;\n    PDH_STATUS status = PdhGetFormattedCounterArray(counter, PDH_FMT_DOUBLE, &dwBufferSize, &dwItemCount, pItems);\n    if (PDH_MORE_DATA == status)\n    {\n        pItems = (PDH_FMT_COUNTERVALUE_ITEM*)malloc(dwBufferSize);\n        if (pItems)\n        {\n            status = PdhGetFormattedCounterArray(counter, PDH_FMT_DOUBLE, &dwBufferSize, &dwItemCount, pItems);\n            if (ERROR_SUCCESS == status)\n            {\n                // Loop through the array and print the instance name and counter value.\n                for (DWORD i = 0; i < dwItemCount; i++)\n                {\n                    CounterValueItem value_item;\n                    value_item.name = pItems[i].szName;\n                    value_item.value = pItems[i].FmtValue.doubleValue;\n                    values.push_back(value_item);\n                }\n            }\n            else\n            {\n                return false;\n            }\n\n            free(pItems);\n            pItems = NULL;\n            dwBufferSize = dwItemCount = 0;\n        }\n        else\n        {\n            return false;\n        }\n    }\n    else\n    {\n        return false;\n    }\n\n    return true;\n}\n"
  },
  {
    "path": "TrafficMonitor/PdhHardwareQuery/PdhQuery.h",
    "content": "﻿#pragma once\n#include <Pdh.h>\n#include <PdhMsg.h>\n\nclass CPdhQuery\n{\npublic:\n    CPdhQuery(LPCTSTR _fullCounterPath);\n    virtual ~CPdhQuery();\n\nprotected:\n    bool Initialize();\n    bool QueryValue(double& value);\n    struct CounterValueItem\n    {\n        std::wstring name;\n        double value{};\n    };\n    bool QueryValues(std::vector<CounterValueItem>& values);\n\nprotected:\n    HQUERY query = nullptr;\n    HCOUNTER counter = nullptr;\n    bool isInitialized = false;\n    CString fullCounterPath;\n};\n"
  },
  {
    "path": "TrafficMonitor/PictureStatic.cpp",
    "content": "#include \"stdafx.h\"\n#include \"PictureStatic.h\"\n\n\nCPictureStatic::CPictureStatic()\n{\n}\n\n\nCPictureStatic::~CPictureStatic()\n{\n\tm_memDC.DeleteDC();\n\tm_bitmap.Detach();\n}\n\nvoid CPictureStatic::SetPicture(UINT pic_id)\n{\n\tm_memDC.DeleteDC();\n\tif (!m_bitmap.LoadBitmap(pic_id))\t\t//λͼ\n\t\treturn;\n\t//ȡͼʵʴС\n\tGetObject(m_bitmap, sizeof(BITMAP), &m_bm);\n\tCDC* pDC = GetDC();\n\tm_memDC.CreateCompatibleDC(pDC);\n\tm_memDC.SelectObject(&m_bitmap);\n\t//ȡؼС\n\tGetClientRect(m_rect);\n\t//ֶػ\n\tInvalidate();\n}\n\nvoid CPictureStatic::SetPicture(HBITMAP hBitmap)\n{\n\tm_memDC.DeleteDC();\n\tm_bitmap.Detach();\n\tif (!m_bitmap.Attach(hBitmap))\n\t\treturn;\n\t//ȡͼʵʴС\n\tGetObject(m_bitmap, sizeof(BITMAP), &m_bm);\n\tCDC* pDC = GetDC();\n\tm_memDC.CreateCompatibleDC(pDC);\n\tm_memDC.SelectObject(&m_bitmap);\n\t//ȡؼС\n\tGetClientRect(m_rect);\n\t//ֶػ\n\tInvalidate();\n}\n\nBEGIN_MESSAGE_MAP(CPictureStatic, CStatic)\n\tON_WM_PAINT()\nEND_MESSAGE_MAP()\n\n\nvoid CPictureStatic::OnPaint()\n{\n\tCPaintDC dc(this); // device context for painting\n\t\t\t\t\t   // TODO: ڴ˴Ϣ\n\t\t\t\t\t   // ΪͼϢ CStatic::OnPaint()\n\tif (m_bitmap.m_hObject != NULL)\n\t{\n\t\t// бͼƬʧ\n\t\tdc.SetStretchBltMode(HALFTONE);\n\t\tdc.SetBrushOrg(0, 0);\n\t\t//ƽڴDCеͼ\n\t\tdc.StretchBlt(0, 0, m_rect.Width(), m_rect.Height(), &m_memDC, 0, 0, m_bm.bmWidth, m_bm.bmHeight, SRCCOPY);\n\n\t\t//򸸴ڷػϢ\n\t\tCWnd* pParent{ GetParent() };\n\t\tif (pParent != nullptr)\n\t\t\tpParent->SendMessage(WM_CONTROL_REPAINT, (WPARAM)this, LPARAM(&dc));\n\t}\n}\n"
  },
  {
    "path": "TrafficMonitor/PictureStatic.h",
    "content": "/*һʾͼƬľ̬ؼ\nҪʱSetPicture()þ̬ͼƬ\nؼػʱ򸸴ڷWM_CONTROL_REPAINTϢ\nͨwParamݵǰؼCWndָ룬ͨlParamCDCָ\n*/\n#pragma once\n#define WM_CONTROL_REPAINT (WM_USER + 1003)\t\t//ؼػϢ\n\nclass CPictureStatic : public CStatic\n{\npublic:\n\tCPictureStatic();\n\t~CPictureStatic();\n\n\tvoid SetPicture(UINT pic_id);\n\tvoid SetPicture(HBITMAP hBitmap);\n\nprotected:\n\tCDC m_memDC;\n\tCBitmap m_bitmap;\n\tCRect m_rect;\n\tBITMAP m_bm;\n\npublic:\n\tDECLARE_MESSAGE_MAP()\n\tafx_msg void OnPaint();\n};\n\n"
  },
  {
    "path": "TrafficMonitor/PluginInfoDlg.cpp",
    "content": "﻿// PluginInfoDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"PluginInfoDlg.h\"\n#include \"FilePathHelper.h\"\n\n\n// CPluginInfoDlg 对话框\n\nIMPLEMENT_DYNAMIC(CPluginInfoDlg, CBaseDialog)\n\nCPluginInfoDlg::CPluginInfoDlg(int plugin_index, CWnd* pParent /*=nullptr*/)\n\t: CBaseDialog(IDD_NETWORK_INFO_DIALOG, pParent), m_cur_index(plugin_index)\n{\n    if (m_cur_index < 0 || m_cur_index >= static_cast<int>(theApp.m_plugins.GetPlugins().size()))\n        m_cur_index = 0;\n}\n\nCPluginInfoDlg::~CPluginInfoDlg()\n{\n}\n\nvoid CPluginInfoDlg::DoDataExchange(CDataExchange* pDX)\n{\n\tCBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_INFO_LIST1, m_info_list);\n}\n\nvoid CPluginInfoDlg::ShowInfo()\n{\n    if (m_cur_index >= 0 && m_cur_index < static_cast<int>(theApp.m_plugins.GetPlugins().size()))\n    {\n        auto& plugin_info = theApp.m_plugins.GetPlugins()[m_cur_index];\n        m_info_list.SetItemText(RI_NAME, 1, plugin_info.Property(ITMPlugin::TMI_NAME).c_str());\n        m_info_list.SetItemText(RI_DESCRIPTION, 1, plugin_info.Property(ITMPlugin::TMI_DESCRIPTION).c_str());\n        m_info_list.SetItemText(RI_FILE_NAME, 1, CFilePathHelper(plugin_info.file_path).GetFileName().c_str());\n        m_info_list.SetItemText(RI_FILE_PATH, 1, plugin_info.file_path.c_str());\n        m_info_list.SetItemText(RI_ITEM_NUM, 1, std::to_wstring(plugin_info.plugin_items.size()).c_str());\n        wstring item_names;\n        wstring item_id;\n        for (const auto& item : plugin_info.plugin_items)\n        {\n            item_names += item->GetItemName();\n            item_names += L\";\";\n            item_id += item->GetItemId();\n            item_id += L\";\";\n        }\n        if (!plugin_info.plugin_items.empty())\n        {\n            item_names.pop_back();\n            item_id.pop_back();\n        }\n        m_info_list.SetItemText(RI_ITEM_NAMES, 1, item_names.c_str());\n        m_info_list.SetItemText(RI_ITEM_ID, 1, item_id.c_str());\n        m_info_list.SetItemText(RI_AUTHOR, 1, plugin_info.Property(ITMPlugin::TMI_AUTHOR).c_str());\n        m_info_list.SetItemText(RI_COPYRIGHT, 1, plugin_info.Property(ITMPlugin::TMI_COPYRIGHT).c_str());\n        m_info_list.SetItemText(RI_URL, 1, plugin_info.Property(ITMPlugin::TMI_URL).c_str());\n        m_info_list.SetItemText(RI_VERSION, 1, plugin_info.Property(ITMPlugin::TMI_VERSION).c_str());\n        std::wstring api_version;\n        if (plugin_info.plugin != nullptr)\n            api_version = std::to_wstring(plugin_info.plugin->GetAPIVersion());\n        m_info_list.SetItemText(RI_API_VERSION, 1, api_version.c_str());\n    }\n\n    //显示当前选择指示\n    CString str;\n    str.Format(_T(\"%d/%d\"), m_cur_index + 1, theApp.m_plugins.GetPlugins().size());\n    SetDlgItemText(IDC_INDEX_STATIC, str);\n}\n\n\nBEGIN_MESSAGE_MAP(CPluginInfoDlg, CBaseDialog)\n    ON_COMMAND(ID_COPY_TEXT, &CPluginInfoDlg::OnCopyText)\n    ON_NOTIFY(NM_RCLICK, IDC_INFO_LIST1, &CPluginInfoDlg::OnNMRClickInfoList1)\n    ON_BN_CLICKED(IDC_PREVIOUS_BUTTON, &CPluginInfoDlg::OnBnClickedPreviousButton)\n    ON_BN_CLICKED(IDC_NEXT_BUTTON, &CPluginInfoDlg::OnBnClickedNextButton)\n    ON_WM_MOUSEWHEEL()\nEND_MESSAGE_MAP()\n\n\n// CPluginInfoDlg 消息处理程序\n\n\nBOOL CPluginInfoDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetWindowText(CCommon::LoadText(IDS_PLUGIN_INFO));\n    SetIcon(theApp.GetMenuIcon(IDI_PLUGINS), FALSE);\t\t// 设置小图标\n\n    //初始化列表控件\n    CRect rect;\n    m_info_list.GetClientRect(rect);\n    m_info_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);\n    int width0, width1;\n    width0 = rect.Width() / 4;\n    width1 = rect.Width() - width0 - theApp.DPI(20) - 1;\n    m_info_list.InsertColumn(0, CCommon::LoadText(IDS_ITEM), LVCFMT_LEFT, width0);\n    m_info_list.InsertColumn(1, CCommon::LoadText(IDS_VALUE), LVCFMT_LEFT, width1);\n\n    //向列表中插入行\n    for (int i = 0; i < RI_MAX; i++)\n    {\n        m_info_list.InsertItem(i, GetRowName(i));\n    }\n\n    //显示列表中的信息\n    ShowInfo();\n\n    m_info_list.GetToolTips()->SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);\n\n    CCommon::LoadMenuResource(m_menu, IDR_INFO_MENU); //装载右键菜单\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\nCString CPluginInfoDlg::GetDialogName() const\n{\n    return _T(\"PluginInfoDlg\");\n}\n\nvoid CPluginInfoDlg::OnCopyText()\n{\n    if (!CCommon::CopyStringToClipboard(wstring(m_selected_string)))\n        MessageBox(CCommon::LoadText(IDS_COPY_TO_CLIPBOARD_FAILED), NULL, MB_ICONWARNING);\n}\n\nvoid CPluginInfoDlg::OnNMRClickInfoList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n\n    //获取鼠标点击处的文本\n    int item, sub_item;\n    item = pNMItemActivate->iItem;\n    sub_item = pNMItemActivate->iSubItem;\n    m_selected_string = m_info_list.GetItemText(item, sub_item);\n\n    //弹出右键菜单\n    CMenu* pContextMenu = m_menu.GetSubMenu(0);\t//获取第一个弹出菜单\n    CPoint point1;\t//定义一个用于确定光标位置的位置\n    GetCursorPos(&point1);\t//获取当前光标的位置，以便使得菜单可以跟随光标\n    pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this); //在指定位置显示弹出菜单\n\n    *pResult = 0;\n}\n\nvoid CPluginInfoDlg::OnBnClickedPreviousButton()\n{\n    if (m_cur_index > 0)\n    {\n        m_cur_index--;\n        ShowInfo();\n    }\n}\n\nvoid CPluginInfoDlg::OnBnClickedNextButton()\n{\n    if (m_cur_index < static_cast<int>(theApp.m_plugins.GetPlugins().size() - 1))\n    {\n        m_cur_index++;\n        ShowInfo();\n    }\n}\n\nBOOL CPluginInfoDlg::PreTranslateMessage(MSG* pMsg)\n{\n    if (pMsg->message == WM_KEYDOWN)\n    {\n        if (pMsg->wParam == VK_LEFT)\n        {\n            OnBnClickedPreviousButton();\n            return TRUE;\n        }\n        if (pMsg->wParam == VK_RIGHT)\n        {\n            OnBnClickedNextButton();\n            return TRUE;\n        }\n    }\n\n    return CBaseDialog::PreTranslateMessage(pMsg);\n}\n\n\nBOOL CPluginInfoDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)\n{\n    //通过鼠标滚轮翻页\n    if (zDelta > 0)\n    {\n        OnBnClickedPreviousButton();\n    }\n    if (zDelta < 0)\n    {\n        OnBnClickedNextButton();\n    }\n\n    return CBaseDialog::OnMouseWheel(nFlags, zDelta, pt);\n}\n\nCString CPluginInfoDlg::GetRowName(int row_index)\n{\n    switch (row_index)\n    {\n    case CPluginInfoDlg::RI_NAME:\n        return CCommon::LoadText(IDS_NAME);\n    case CPluginInfoDlg::RI_DESCRIPTION:\n        return CCommon::LoadText(IDS_DESCRIPTION);\n    case CPluginInfoDlg::RI_FILE_NAME:\n        return CCommon::LoadText(IDS_FILE_NAME);\n    case CPluginInfoDlg::RI_FILE_PATH:\n        return CCommon::LoadText(IDS_FILE_PATH);\n    case CPluginInfoDlg::RI_ITEM_NUM:\n        return CCommon::LoadText(IDS_ITEM_NUM);\n    case CPluginInfoDlg::RI_ITEM_NAMES:\n        return CCommon::LoadText(IDS_ITEM_NAMES);\n    case CPluginInfoDlg::RI_ITEM_ID:\n        return CCommon::LoadText(IDS_DISP_ITEM_ID);\n    case CPluginInfoDlg::RI_AUTHOR:\n        return CCommon::LoadText(IDS_AUTHOR);\n    case CPluginInfoDlg::RI_COPYRIGHT:\n        return CCommon::LoadText(IDS_COPYRIGHT);\n    case CPluginInfoDlg::RI_URL:\n        return CCommon::LoadText(IDS_URL);\n    case CPluginInfoDlg::RI_VERSION:\n        return CCommon::LoadText(IDS_VERSION);\n    case CPluginInfoDlg::RI_API_VERSION:\n        return CCommon::LoadText(IDS_PLUGIN_API_VERSION);\n    default:\n        break;\n    }\n    return CString();\n}\n"
  },
  {
    "path": "TrafficMonitor/PluginInfoDlg.h",
    "content": "﻿#pragma once\n#include \"BaseDialog.h\"\n#include \"ListCtrlEx.h\"\n\n// CPluginInfoDlg 对话框\n\nclass CPluginInfoDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CPluginInfoDlg)\n\npublic:\n\tCPluginInfoDlg(int plugin_index, CWnd* pParent = nullptr);   // 标准构造函数\n\tvirtual ~CPluginInfoDlg();\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_NETWORK_INFO_DIALOG };\n#endif\n\nprivate:\n    int m_cur_index;        //初始显示的插件索引\n    CListCtrlEx m_info_list;\n    CMenu m_menu;\n    CString m_selected_string;\n\n    //列表中的列\n    enum RowIndex\n    {\n        RI_FILE_NAME,\n        RI_FILE_PATH,\n        RI_NAME,\n        RI_DESCRIPTION,\n        RI_ITEM_NUM,\n        RI_ITEM_NAMES,\n        RI_ITEM_ID,\n        RI_AUTHOR,\n        RI_COPYRIGHT,\n        RI_URL,\n        RI_VERSION,\n        RI_API_VERSION,\n        RI_MAX\n    };\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    void ShowInfo();\n    static CString GetRowName(int row_index);   //获取行的名称\n\n    // 通过 CBaseDialog 继承\n    virtual CString GetDialogName() const override;\n\n\tDECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n\n    afx_msg void OnCopyText();\n    afx_msg void OnNMRClickInfoList1(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnBnClickedPreviousButton();\n    afx_msg void OnBnClickedNextButton();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);\n\n};\n"
  },
  {
    "path": "TrafficMonitor/PluginManager.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include <Windows.h>\n#include <cstddef>\n#include <functional>\n#include <unordered_map>\n#include <locale>\n#include <initializer_list>\n#include <string.h>\n#include \"DrawTextManager.h\"\n#include \"PluginManager.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n\n#define PLUGIN_UNSUPPORT_VERSION 0      //不被支持的插件版本\n\nCPluginManager::CPluginManager()\n{\n}\n\nCPluginManager::~CPluginManager()\n{\n    //卸载插件\n    for (const auto& m : m_modules)\n        FreeLibrary(m.plugin_module);\n}\n\nstatic wstring WcharArrayToWString(const wchar_t* str)\n{\n    if (str == nullptr)\n        return wstring();\n    else\n        return wstring(str);\n}\n\nvoid CPluginManager::LoadPlugins()\n{\n    //从plugins目录下加载插件\n    wstring plugin_dir;\n    plugin_dir = CCommon::GetModuleDir() + L\"plugins\";\n    vector<wstring> plugin_files;\n    CCommon::GetFiles((plugin_dir + L\"\\\\*.dll\").c_str(), plugin_files);\t\t//获取Plugins目录下所有的dll文件的文件名\n    for (const auto& file : plugin_files)\n    {\n        //插件信息\n        m_modules.push_back(PluginInfo());\n        PluginInfo& plugin_info{ m_modules.back() };\n        //插件dll的路径\n        plugin_info.file_path = plugin_dir + file;\n        //插件文件名\n        std::wstring file_name{ file };\n        if (!file_name.empty() && (file_name[0] == L'\\\\' || file_name[0] == L'/'))\n            file_name = file_name.substr(1);\n        //如果插件被禁用，则不加载插件\n        if (theApp.m_cfg_data.plugin_disabled.Contains(file_name))\n        {\n            plugin_info.state = PluginState::PS_DISABLE;\n            continue;\n        }\n        //载入dll\n        plugin_info.plugin_module = LoadLibrary(plugin_info.file_path.c_str());\n        if (plugin_info.plugin_module == NULL)\n        {\n            plugin_info.state = PluginState::PS_MUDULE_LOAD_FAILED;\n            plugin_info.error_code = GetLastError();\n            continue;\n        }\n        // hook插件导入的User32.dll下的DrawText系列函数\n        ReplacePluginDrawTextFunction(plugin_info.plugin_module);\n        //获取函数的入口地址\n        pfTMPluginGetInstance TMPluginGetInstance = (pfTMPluginGetInstance)::GetProcAddress(plugin_info.plugin_module, \"TMPluginGetInstance\");\n        if (TMPluginGetInstance == NULL)\n        {\n            plugin_info.state = PluginState::PS_FUNCTION_GET_FAILED;\n            plugin_info.error_code = GetLastError();\n            continue;\n        }\n        //创建插件对象\n        plugin_info.plugin = TMPluginGetInstance();\n        if (plugin_info.plugin == nullptr)\n            continue;\n        //检查插件版本\n        int version = plugin_info.plugin->GetAPIVersion();\n        if (version <= PLUGIN_UNSUPPORT_VERSION)\n        {\n            plugin_info.state = PluginState::PS_VERSION_NOT_SUPPORT;\n            continue;\n        }\n        //向插件传递配置文件的路径\n        std::wstring config_dir = theApp.m_config_dir;\n        config_dir += L\"plugins\\\\\";\n        if (version >= 2)\n        {\n            CreateDirectory(config_dir.c_str(), NULL);       //如果plugins不存在，则创建它\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_CONFIG_DIR, config_dir.c_str());\n        }\n\n        //调用初始化函数\n        if (version >= 7)\n        {\n            plugin_info.plugin->OnInitialize(&theApp);\n        }\n\n        //获取插件信息\n        for (int i{}; i < ITMPlugin::TMI_MAX; i++)\n        {\n            ITMPlugin::PluginInfoIndex index{ static_cast<ITMPlugin::PluginInfoIndex>(i) };\n            plugin_info.properties[index] = WcharArrayToWString(plugin_info.plugin->GetInfo(index));\n        }\n\n        //获取插件显示项目\n        int index = 0;\n        while (true)\n        {\n            IPluginItem* item = plugin_info.plugin->GetItem(index);\n            if (item == nullptr)\n                break;\n            plugin_info.plugin_items.push_back(item);\n            m_plugins.push_back(item);\n            m_plguin_item_map[item] = plugin_info.plugin;\n            index++;\n        }\n    }\n    // hook MFC导入的User32.dll下的DrawText系列函数\n    ReplaceMfcDrawTextFunction();\n\n    //初始化所有任务栏显示项目\n    for (const auto& display_item : AllDisplayItems)\n    {\n        m_all_display_items_with_plugins.insert(display_item);\n    }\n    for (const auto& display_item : m_plugins)\n    {\n        m_all_display_items_with_plugins.insert(display_item);\n    }\n}\n\nconst std::vector<IPluginItem*>& CPluginManager::GetPluginItems() const\n{\n    return m_plugins;\n}\n\nconst std::vector<CPluginManager::PluginInfo>& CPluginManager::GetPlugins() const\n{\n    return m_modules;\n}\n\nIPluginItem* CPluginManager::GetItemById(const std::wstring& item_id)\n{\n    for (const auto& item : m_plugins)\n    {\n        if (item->GetItemId() == item_id)\n            return item;\n    }\n    return nullptr;\n}\n\nIPluginItem* CPluginManager::GetItemByIndex(int index)\n{\n    if (index >= 0 && index < static_cast<int>(m_plugins.size()))\n        return m_plugins[index];\n    return nullptr;\n}\n\nint CPluginManager::GetItemIndex(IPluginItem* item) const\n{\n    for (auto iter = m_plugins.begin(); iter != m_plugins.end(); ++iter)\n    {\n        if (*iter == item)\n            return iter - m_plugins.begin();\n    }\n    return -1;\n}\n\nITMPlugin* CPluginManager::GetPluginByItem(IPluginItem* pItem)\n{\n    if (pItem == nullptr)\n        return nullptr;\n    return m_plguin_item_map[pItem];\n}\n\nint CPluginManager::GetPluginIndex(ITMPlugin* plugin) const\n{\n    for (auto iter = m_modules.begin(); iter != m_modules.end(); ++iter)\n    {\n        if (iter->plugin == plugin)\n            return iter - m_modules.begin();\n    }\n    return -1;\n}\n\nvoid CPluginManager::EnumPlugin(std::function<void(ITMPlugin*)> func) const\n{\n    for (const auto& item : m_modules)\n    {\n        if (item.plugin != nullptr)\n        {\n            func(item.plugin);\n        }\n    }\n}\n\nvoid CPluginManager::EnumPluginItem(std::function<void(IPluginItem*)> func) const\n{\n    for (const auto& item : m_plugins)\n    {\n        if (item != nullptr)\n        {\n            func(item);\n        }\n    }\n}\n\nconst std::set<CommonDisplayItem>& CPluginManager::AllDisplayItemsWithPlugins()\n{\n    return m_all_display_items_with_plugins;\n}\n\n\nint CPluginManager::GetItemWidth(IPluginItem* pItem, CDC* pDC)\n{\n    int width = 0;\n    ITMPlugin* plugin = GetPluginByItem(pItem);\n    if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n    {\n        width = pItem->GetItemWidthEx(pDC->GetSafeHdc());       //优先使用GetItemWidthEx接口获取宽度\n    }\n    if (width == 0)\n    {\n        width = theApp.DPI(pItem->GetItemWidth());\n    }\n    return width;\n}\n\nstd::wstring CPluginManager::PluginInfo::Property(ITMPlugin::PluginInfoIndex index) const\n{\n    auto iter = properties.find(index);\n    if (iter != properties.end())\n        return iter->second;\n    return wstring();\n}\n\ntemplate <class T>\nvoid inline CopyData(void* from, T* to)\n{\n    ::memcpy(to, from, sizeof(T));\n}\n\nauto inline GetCLocale() noexcept\n    -> const std::locale&\n{\n    const static std::locale restlt{\"C\"};\n    return restlt;\n};\n\n/**\n * @brief 将输入的dll名称转大写\n *\n * @param dll_name 输入的dll名称\n * @param expected_length 期望的dll名称长度，不匹配则无操作\n * @return std::string 大写的dll名称\n */\nstd::string UpperDllName(const char* dll_name, std::size_t expected_length)\n{\n    std::string result{};\n    result.resize(expected_length);\n    const char* dll_name_last = &dll_name[expected_length];\n    std::transform(dll_name, dll_name_last, result.begin(),\n                   [](char c) -> char\n                   { return std::toupper(c, GetCLocale()); });\n    return result;\n}\n\nstd::string UpperDllName(const char* dll_name)\n{\n    std::string result{};\n    for (std::size_t i = 0; i < 256; ++i)\n    {\n        auto current_char = dll_name[i];\n        if (current_char == '\\0')\n        {\n            result += '\\0';\n            break;\n        }\n        result += std::toupper(current_char, GetCLocale());\n    }\n    return result;\n}\n\nclass DllName\n{\npublic:\n    class FunctionNameImpl\n    {\n        using Handler = std::function<void(void**, void*)>;\n        friend DllName;\n\n    public:\n        /**\n         * @brief Construct a new Function Name Impl object\n         *\n         * @param function_name 函数名称\n         * @param on_function_find_handler 当查找到函数时执行的方法，\n         类型为std::function<void(void** pp_found_function_address, void* p_args)>\n         */\n        FunctionNameImpl(const std::string& function_name, Handler on_function_find_handler)\n            : m_function_name{function_name}, m_on_function_find_handler{on_function_find_handler}, m_p_function{}\n        {\n        }\n        ~FunctionNameImpl() = default;\n\n        void OnFunctionFind(void** pp_found_fuction, void* p_args) const\n        {\n            m_on_function_find_handler(pp_found_fuction, p_args);\n        }\n\n        auto NameString() const noexcept\n            -> const std::string&\n        {\n            return m_function_name;\n        }\n\n    private:\n        void* m_p_function;\n        Handler m_on_function_find_handler;\n        std::string m_function_name;\n    };\n    using FunctionName = FunctionNameImpl;\n\nprivate:\n    std::unordered_map<void*, FunctionName> m_function_name_map{};\n    std::string m_dll_name;\n\npublic:\n    DllName(const char* dll_name, std::size_t expected_length, std::initializer_list<FunctionName> function_names_in_dll)\n        : m_dll_name{UpperDllName(dll_name, expected_length)}\n    {\n        auto h_dll = ::LoadLibraryA(dll_name);\n        if (h_dll)\n        {\n            for (auto function_name : function_names_in_dll)\n            {\n                auto* function_pointer =\n                    reinterpret_cast<void*>(::GetProcAddress(h_dll, function_name.NameString().c_str()));\n\n                auto exist_it = m_function_name_map.find(function_pointer);\n                if (exist_it == m_function_name_map.end())\n                {\n                    m_function_name_map.emplace(std::move(std::make_pair(function_pointer, function_name)));\n                }\n            }\n            ::FreeLibrary(h_dll);\n        }\n    }\n    ~DllName() = default;\n\n    auto NameString() const noexcept\n        -> const std::string&\n    {\n        return m_dll_name;\n    }\n\n    auto MatchFunctionPointer(void* found_pointer) const noexcept\n        -> const FunctionName*\n    {\n        auto it = m_function_name_map.find(found_pointer);\n        if (it != m_function_name_map.end())\n        {\n            return &it->second;\n        }\n        return nullptr;\n    }\n};\n\nusing FunctionName = DllName::FunctionNameImpl;\n\nclass DllMap\n{\nprivate:\n    std::unordered_map<std::string, DllName> m_dll_name_map;\n\npublic:\n    DllMap(std::initializer_list<DllName> dll_names)\n    {\n        for (auto&& dll_name : dll_names)\n        {\n            auto exist_dll_name = m_dll_name_map.find(dll_name.NameString());\n            if (exist_dll_name == m_dll_name_map.end())\n            {\n                m_dll_name_map.emplace(std::make_pair(dll_name.NameString(), dll_name));\n            }\n        }\n    }\n    ~DllMap() = default;\n\n    auto MatchDllName(const char* any_case_string) const\n        -> const DllName*\n    {\n        std::string capital_dll_name = UpperDllName(any_case_string);\n        auto it = m_dll_name_map.find(capital_dll_name);\n        if (it != m_dll_name_map.end())\n        {\n            return &it->second;\n        }\n        return nullptr;\n    }\n};\n\n#define ARR_ARRLENGTH(c_array) c_array, GetArrayLength(c_array)\n\nvoid CPluginManager::ReplacePluginDrawTextFunction(HMODULE plgin_dll_module) noexcept\n{\n    auto* p_plugin_dll_module = reinterpret_cast<BYTE*>(plgin_dll_module);\n\n    auto p_dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(plgin_dll_module);\n\n    auto p_image_nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(\n        p_plugin_dll_module + p_dos_header->e_lfanew);\n\n    auto p_optional_header = reinterpret_cast<PIMAGE_OPTIONAL_HEADER>(\n        &p_image_nt_headers->OptionalHeader);\n\n    auto import_table_offset =\n        p_optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;\n    auto p_current_import_desc = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(\n        p_plugin_dll_module + import_table_offset);\n\n    //不区分大小写，需要输入的dll中导入表里User32.dll的4个函数\n    static const char user32_dll_name[] = \"User32.dll\";\n    static const DllName dll_names{ARR_ARRLENGTH(user32_dll_name),\n                                   {{\"DrawTextA\", User32DrawTextManager::A::GetReplaceOperation()},\n                                    {\"DrawTextW\", User32DrawTextManager::W::GetReplaceOperation()},\n                                    {\"DrawTextExA\", User32DrawTextManager::ExA::GetReplaceOperation()},\n                                    {\"DrawTextExW\", User32DrawTextManager::ExW::GetReplaceOperation()}}};\n    static const DllMap dll_map{{dll_names}};\n\n    while (p_current_import_desc->FirstThunk != NULL)\n    {\n        const auto* p_import_dll_name = reinterpret_cast<char*>(\n            p_plugin_dll_module + p_current_import_desc->Name);\n\n        auto* p_matched_dll_name = dll_map.MatchDllName(p_import_dll_name);\n        if (p_matched_dll_name != nullptr)\n        {\n            //搜索IAT表\n            auto p_current_chunk = reinterpret_cast<PIMAGE_THUNK_DATA>(\n                p_plugin_dll_module + p_current_import_desc->FirstThunk);\n\n            while (p_current_chunk->u1.AddressOfData != NULL)\n            {\n                static_assert(sizeof(p_current_chunk->u1.Function) == sizeof(void*), \"Length not match!\");\n                auto p_target_pointer = reinterpret_cast<void**>(&p_current_chunk->u1.Function);\n\n                auto p_matched_function =\n                    p_matched_dll_name->MatchFunctionPointer(*p_target_pointer);\n                if (p_matched_function != nullptr)\n                {\n                    p_matched_function->OnFunctionFind(p_target_pointer, nullptr);\n                }\n                ++p_current_chunk;\n            }\n        }\n        ++p_current_import_desc;\n    }\n}\n\nvoid CPluginManager::ReplaceMfcDrawTextFunction() noexcept\n{\n    HMODULE mfc_module = ::LoadLibraryA(\"mfc140u.dll\");\n    if (mfc_module != NULL)\n    {\n        ReplacePluginDrawTextFunction(mfc_module);\n        ::FreeLibrary(mfc_module);\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/PluginManager.h",
    "content": "﻿#pragma once\n#include \"PluginInterface.h\"\n#include <map>\n#include \"TaskbarItemOrderHelper.h\"\n#include <functional>\n\ntypedef ITMPlugin* (*pfTMPluginGetInstance)();\n\n//用于加载和管理插件\nclass CPluginManager\n{\npublic:\n    //插件的状态\n    enum class PluginState\n    {\n        PS_SUCCEED,             //载入成功\n        PS_MUDULE_LOAD_FAILED,  //dll加载失败\n        PS_FUNCTION_GET_FAILED, //插件函数获取失败\n        PS_VERSION_NOT_SUPPORT, //插件版本不被支持\n        PS_DISABLE              //已禁用\n    };\n\n    //插件信息\n    struct PluginInfo\n    {\n        wstring file_path;      //文件路径\n        HMODULE plugin_module{};  //dll module\n        ITMPlugin* plugin{};      //插件对象\n        std::vector<IPluginItem*> plugin_items; //插件提供的所有显示项目\n        PluginState state{};    //插件的状态\n        DWORD error_code{};     //错误代码（GetLastError的返回值）\n        std::map<ITMPlugin::PluginInfoIndex, std::wstring> properties;    //插件属性\n        std::wstring Property(ITMPlugin::PluginInfoIndex) const;\n    };\n\n    CPluginManager();\n    ~CPluginManager();\n    void LoadPlugins();\n\n    const std::vector<IPluginItem*>& GetPluginItems() const;\n    const std::vector<PluginInfo>& GetPlugins() const;\n    IPluginItem* GetItemById(const std::wstring& item_id);\n    IPluginItem* GetItemByIndex(int index);\n    int GetItemIndex(IPluginItem* item) const;\n    ITMPlugin* GetPluginByItem(IPluginItem* pItem);\n    int GetPluginIndex(ITMPlugin* plugin) const;\n\n    //遍历所有插件\n    //func: 参数为遍历到的ITMPlugin对象\n    void EnumPlugin(std::function<void(ITMPlugin*)> func) const;\n\n    //遍历所有插件项目\n    //func: 参数为遍历到的IPluginItem对象\n    void EnumPluginItem(std::function<void(IPluginItem*)> func) const;\n\n    const std::set<CommonDisplayItem>& AllDisplayItemsWithPlugins();\n\n    int GetItemWidth(IPluginItem* pItem, CDC* pDC);\n\nprivate:\n    static void ReplacePluginDrawTextFunction(HMODULE plgin_dll_module) noexcept;\n    static void ReplaceMfcDrawTextFunction() noexcept;\n\nprivate:\n    std::vector<IPluginItem*> m_plugins;\n    std::vector<PluginInfo> m_modules;\n    std::set<CommonDisplayItem> m_all_display_items_with_plugins;   //包含插件在内的所有任务栏显示项目\n    std::map<IPluginItem*, ITMPlugin*> m_plguin_item_map;          //用于根据插件项目查找对应插件的map\n};\n"
  },
  {
    "path": "TrafficMonitor/PluginManagerDlg.cpp",
    "content": "﻿// PluginManagerDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"PluginManagerDlg.h\"\n#include \"FilePathHelper.h\"\n#include \"PluginInfoDlg.h\"\n#include \"WIC.h\"\n\n\n// CPluginManagerDlg 对话框\n\nIMPLEMENT_DYNAMIC(CPluginManagerDlg, CBaseDialog)\n\nCPluginManagerDlg::CPluginManagerDlg(CWnd* pParent /*=nullptr*/)\n    : CBaseDialog(IDD_PLUGIN_MANAGER_DIALOG, pParent)\n{\n\n}\n\nCPluginManagerDlg::~CPluginManagerDlg()\n{\n}\n\nvoid CPluginManagerDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_LIST1, m_list_ctrl);\n    DDX_Control(pDX, IDC_PLUGIN_DOWNLOAD_STATIC, m_plugin_download_lnk);\n    DDX_Control(pDX, IDC_PLUGIN_DEV_GUID_STATIC, m_plugin_dev_guide_lnk);\n    DDX_Control(pDX, IDC_OPEN_PLUGIN_DIR_STATIC, m_open_plugin_dir_lnk);\n}\n\nvoid CPluginManagerDlg::EnableControl()\n{\n    bool enable{ IsSelectedPluginEnable() };\n    EnableDlgCtrl(IDC_OPTINS_BUTTON, enable);\n    EnableDlgCtrl(IDC_PLUGIN_INFO_BUTTON, enable);\n}\n\nbool CPluginManagerDlg::IsSelectedValid()\n{\n    return m_item_selected >= 0 && m_item_selected < static_cast<int>(theApp.m_plugins.GetPlugins().size());\n}\n\nbool CPluginManagerDlg::IsSelectedPluginEnable()\n{\n    CPluginManager::PluginInfo plugin_info{};\n    bool plugin_loaded{ false };\n    if (IsSelectedValid())\n    {\n        plugin_info = theApp.m_plugins.GetPlugins()[m_item_selected];\n        plugin_loaded = (plugin_info.state == CPluginManager::PluginState::PS_SUCCEED);\n    }\n\n    return plugin_loaded;\n}\n\nCString CPluginManagerDlg::GetDialogName() const\n{\n    return _T(\"PluginManagerDlg\");\n}\n\nbool CPluginManagerDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_PLUGIN_INFO_BUTTON, CtrlTextInfo::W32 },\n        { CtrlTextInfo::L3, IDC_OPTINS_BUTTON, CtrlTextInfo::W32 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_PLUGIN_DOWNLOAD_STATIC },\n        { CtrlTextInfo::L3, IDC_PLUGIN_DEV_GUID_STATIC },\n        { CtrlTextInfo::L2, IDC_OPEN_PLUGIN_DIR_STATIC }\n    });\n    return true;\n}\n\n\nBEGIN_MESSAGE_MAP(CPluginManagerDlg, CBaseDialog)\n    ON_NOTIFY(NM_RCLICK, IDC_LIST1, &CPluginManagerDlg::OnNMRClickList1)\n    ON_NOTIFY(NM_CLICK, IDC_LIST1, &CPluginManagerDlg::OnNMClickList1)\n    ON_BN_CLICKED(IDC_OPTINS_BUTTON, &CPluginManagerDlg::OnBnClickedOptinsButton)\n    ON_BN_CLICKED(IDC_PLUGIN_INFO_BUTTON, &CPluginManagerDlg::OnBnClickedPluginInfoButton)\n    ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CPluginManagerDlg::OnNMDblclkList1)\n    ON_WM_INITMENU()\n    ON_COMMAND(ID_PLUGIN_DETAIL, &CPluginManagerDlg::OnPluginDetail)\n    ON_COMMAND(ID_PLUGIN_OPTIONS, &CPluginManagerDlg::OnPluginOptions)\n    ON_COMMAND(ID_PLUGIN_DISABLE, &CPluginManagerDlg::OnPluginDisable)\n    ON_MESSAGE(WM_LINK_CLICKED, &CPluginManagerDlg::OnLinkClicked)\nEND_MESSAGE_MAP()\n\n\n// CPluginManagerDlg 消息处理程序\n\n\nBOOL CPluginManagerDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_PLUGINS), FALSE);\n\n    //初始化列表控件\n    CRect rect;\n    m_list_ctrl.GetClientRect(rect);\n    m_list_ctrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);\n    int width0, width1, width2, width3;\n    width0 = width1 = rect.Width() * 3 / 10;\n    width3 = rect.Width() * 2 / 10;\n    width2 = rect.Width() - width0 - width1 - width3 - theApp.DPI(20) - 1;\n    m_list_ctrl.InsertColumn(COL_FILE_NAME, CCommon::LoadText(IDS_FILE_NAME), LVCFMT_LEFT, width0);\n    m_list_ctrl.InsertColumn(COL_NAME, CCommon::LoadText(IDS_PLUGIN_NAME), LVCFMT_LEFT, width1);\n    m_list_ctrl.InsertColumn(COL_VERSION, CCommon::LoadText(IDS_VERSION), LVCFMT_LEFT, width2);\n    m_list_ctrl.InsertColumn(COL_STATUS, CCommon::LoadText(IDS_STATUS), LVCFMT_LEFT, width3);\n\n    //添加图标\n    int item_num = theApp.m_plugins.GetPlugins().size();\n    m_plugin_icon_list.Create(theApp.DPI(16), theApp.DPI(16), ILC_COLOR32, item_num, item_num);\n    for (const auto& plugin : theApp.m_plugins.GetPlugins())\n    {\n        HICON hIcon{};\n        if (plugin.plugin != nullptr && plugin.plugin->GetAPIVersion() >= 5)\n        {\n            hIcon = (HICON)plugin.plugin->GetPluginIcon();\n        }\n        if (hIcon == nullptr)\n        {\n            if (plugin.state == CPluginManager::PluginState::PS_DISABLE)\n                hIcon = theApp.GetMenuIcon(IDI_PLUGIN_DISABLED);\n            else\n                hIcon = theApp.GetMenuIcon(IDI_PLUGINS);\n        }\n        m_plugin_icon_list.Add(hIcon);\n    }\n    m_list_ctrl.SetImageList(&m_plugin_icon_list, LVSIL_SMALL);\n\n    //向列表中插入行\n    for (const auto& plugin : theApp.m_plugins.GetPlugins())\n    {\n        std::wstring file_name = CFilePathHelper(plugin.file_path).GetFileName();\n        CString error_info;\n        error_info.Format(_T(\"%u %s\"), plugin.error_code, CCommon::GetErrorMessage(plugin.error_code).GetString());\n        CString status;\n        switch (plugin.state)\n        {\n        case CPluginManager::PluginState::PS_SUCCEED:\n            status = CCommon::LoadText(IDS_PLUGIN_LOAD_SUCCEED);\n            break;\n        case CPluginManager::PluginState::PS_MUDULE_LOAD_FAILED:\n            status = CCommon::LoadTextFormat(IDS_PLUGIN_MODULE_LOAD_FAILED, { error_info });\n            break;\n        case CPluginManager::PluginState::PS_FUNCTION_GET_FAILED:\n            status = CCommon::LoadTextFormat(IDS_PLUGIN_FUNCTION_GET_FAILED, { error_info });\n            break;\n        case CPluginManager::PluginState::PS_DISABLE:\n            status = CCommon::LoadText(IDS_DISABLED);\n            break;\n        case CPluginManager::PluginState::PS_VERSION_NOT_SUPPORT:\n            status = CCommon::LoadText(IDS_PLUGIN_VERSION_NOT_SUPPORT);\n            break;\n        default:\n            break;\n        }\n        int index = m_list_ctrl.GetItemCount();\n        m_list_ctrl.InsertItem(index, file_name.c_str(), m_list_ctrl.GetItemCount());\n        m_list_ctrl.SetItemText(index, COL_NAME, plugin.Property(ITMPlugin::TMI_NAME).c_str());\n        if (plugin.state == CPluginManager::PluginState::PS_SUCCEED)\n        {\n            //如果插件有更新，在版本号后添加更新信息\n            PluginVersion cur_version(plugin.Property(ITMPlugin::TMI_VERSION));\n            PluginVersion latest_version(theApp.m_plugin_update.GetPluginLatestVersions(file_name));\n            if (cur_version < latest_version)\n            {\n                std::wstring update_info = theApp.m_str_table.LoadTextFormat(IDS_PLUGIN_NEW_VERSION_INFO, { latest_version.GetVersionWString() });\n                std::wstring version_text = plugin.Property(ITMPlugin::TMI_VERSION);\n                version_text += L\" (\";\n                version_text += update_info;\n                version_text += L')';\n                m_list_ctrl.SetItemText(index, COL_VERSION, version_text.c_str());\n            }\n            else\n            {\n                m_list_ctrl.SetItemText(index, COL_VERSION, plugin.Property(ITMPlugin::TMI_VERSION).c_str());\n            }\n        }\n        m_list_ctrl.SetItemText(index, COL_STATUS, status);\n    }\n\n    if (theApp.m_general_data.update_source == 1)   //更新源为Gitee，跳转到Gitee的链接\n        m_plugin_download_lnk.SetURL(L\"https://gitee.com/zhongyang219/TrafficMonitorPlugins/blob/main/download/plugin_download.md\");\n    else //更新源为Github\n        m_plugin_download_lnk.SetURL(L\"https://github.com/zhongyang219/TrafficMonitorPlugins/blob/main/download/plugin_download.md\");\n    m_plugin_dev_guide_lnk.SetURL(L\"https://github.com/zhongyang219/TrafficMonitor/wiki/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97\");\n    m_open_plugin_dir_lnk.SetLinkIsURL(false);\n\n    EnableControl();\n\n    CCommon::LoadMenuResource(m_menu, IDR_PLUGIN_MANAGER_MENU); //装载右键菜单\n\n    //设置菜单图标\n    CMenuIcon::AddIconToMenuItem(m_menu.GetSubMenu(0)->GetSafeHmenu(), ID_PLUGIN_DETAIL, FALSE, theApp.GetMenuIcon(IDI_INFO));\n    CMenuIcon::AddIconToMenuItem(m_menu.GetSubMenu(0)->GetSafeHmenu(), ID_PLUGIN_OPTIONS, FALSE, theApp.GetMenuIcon(IDI_SETTINGS));\n\n    //设置按钮图标\n    SetButtonIcon(IDC_PLUGIN_INFO_BUTTON, theApp.GetMenuIcon(IDI_INFO));\n    SetButtonIcon(IDC_OPTINS_BUTTON, theApp.GetMenuIcon(IDI_SETTINGS));\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CPluginManagerDlg::OnNMRClickList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n    m_item_selected = pNMItemActivate->iItem;\n    EnableControl();\n\n    //弹出右键菜单\n    CMenu* pContextMenu = m_menu.GetSubMenu(0);\t//获取第一个弹出菜单\n    pContextMenu->SetDefaultItem(ID_PLUGIN_DETAIL);\n    //更新插件子菜单\n    if (m_item_selected >= 0 && m_item_selected < static_cast<int>(theApp.m_plugins.GetPlugins().size()))\n    {\n        auto plugin_info = theApp.m_plugins.GetPlugins()[m_item_selected];\n        theApp.UpdatePluginMenu(pContextMenu, plugin_info.plugin, 3);\n    }\n\n    CPoint point1;\t//定义一个用于确定光标位置的位置\n    GetCursorPos(&point1);\t//获取当前光标的位置，以便使得菜单可以跟随光标\n    pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this); //在指定位置显示弹出菜单\n\n    *pResult = 0;\n}\n\n\nvoid CPluginManagerDlg::OnNMClickList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n    m_item_selected = pNMItemActivate->iItem;\n    EnableControl();\n    *pResult = 0;\n}\n\n\nvoid CPluginManagerDlg::OnBnClickedOptinsButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    if (m_item_selected >= 0 && m_item_selected < static_cast<int>(theApp.m_plugins.GetPlugins().size()))\n    {\n        auto plugin_info = theApp.m_plugins.GetPlugins()[m_item_selected];\n        if (plugin_info.plugin != nullptr)\n        {\n            ITMPlugin::OptionReturn rtn = plugin_info.plugin->ShowOptionsDialog(m_hWnd);\n            if (rtn == ITMPlugin::OR_OPTION_NOT_PROVIDED)\n                MessageBox(CCommon::LoadText(IDS_PLUGIN_NO_OPTIONS_INFO), nullptr, MB_ICONINFORMATION | MB_OK);\n            //else if (rtn == ITMPlugin::OR_OPTION_CHANGED)\n            //    theApp.m_pMainWnd->SendMessage(WM_REOPEN_TASKBAR_WND);\n        }\n    }\n}\n\n\nvoid CPluginManagerDlg::OnBnClickedPluginInfoButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    if (IsSelectedPluginEnable())\n    {\n        CPluginInfoDlg dlg(m_item_selected);\n        dlg.DoModal();\n    }\n}\n\n\nvoid CPluginManagerDlg::OnNMDblclkList1(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n    m_item_selected = pNMItemActivate->iItem;\n    OnBnClickedPluginInfoButton();\n    *pResult = 0;\n}\n\n\nvoid CPluginManagerDlg::OnInitMenu(CMenu* pMenu)\n{\n    CBaseDialog::OnInitMenu(pMenu);\n\n    // TODO: 在此处添加消息处理程序代码\n    bool enable{ IsSelectedPluginEnable() };\n    pMenu->EnableMenuItem(ID_PLUGIN_DETAIL, MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED));\n    pMenu->EnableMenuItem(ID_PLUGIN_OPTIONS, MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED));\n    pMenu->EnableMenuItem(ID_PLUGIN_DISABLE, MF_BYCOMMAND | (IsSelectedValid() ? MF_ENABLED : MF_GRAYED));\n\n    bool disabled{};\n    CPluginManager::PluginInfo plugin_info;\n    if (m_item_selected >= 0 && m_item_selected < static_cast<int>(theApp.m_plugins.GetPlugins().size()))\n    {\n        plugin_info = theApp.m_plugins.GetPlugins()[m_item_selected];\n        std::wstring file_name = CFilePathHelper(plugin_info.file_path).GetFileName();\n        disabled = theApp.m_cfg_data.plugin_disabled.Contains(file_name);\n    }\n    pMenu->CheckMenuItem(ID_PLUGIN_DISABLE, MF_BYCOMMAND | (disabled ? MF_CHECKED : MF_UNCHECKED));\n}\n\n\nvoid CPluginManagerDlg::OnPluginDetail()\n{\n    OnBnClickedPluginInfoButton();\n}\n\n\nvoid CPluginManagerDlg::OnPluginOptions()\n{\n    OnBnClickedOptinsButton();\n}\n\n\nvoid CPluginManagerDlg::OnPluginDisable()\n{\n    if (m_item_selected >= 0 && m_item_selected < static_cast<int>(theApp.m_plugins.GetPlugins().size()))\n    {\n        CPluginManager::PluginInfo plugin_info = theApp.m_plugins.GetPlugins()[m_item_selected];\n        std::wstring file_name = CFilePathHelper(plugin_info.file_path).GetFileName();\n        bool disabled = theApp.m_cfg_data.plugin_disabled.Contains(file_name);\n        theApp.m_cfg_data.plugin_disabled.SetStrContained(file_name, !disabled);\n        MessageBox(CCommon::LoadText(IDS_RESTART_TO_APPLY_CHANGE_INFO), nullptr, MB_OK | MB_ICONINFORMATION);\n    }\n}\n\n\nafx_msg LRESULT CPluginManagerDlg::OnLinkClicked(WPARAM wParam, LPARAM lParam)\n{\n    CWnd* pCtrl = (CWnd*)wParam;\n    //点击了“打开插件目录”\n    if (pCtrl == &m_open_plugin_dir_lnk)\n    {\n        wstring plugin_dir = CCommon::GetModuleDir() + L\"plugins\";\n        CreateDirectory(plugin_dir.c_str(), NULL);       //如果plugins不存在，则创建它\n        ShellExecute(NULL, _T(\"open\"), _T(\"explorer\"), plugin_dir.c_str(), NULL, SW_SHOWNORMAL);\n    }\n\n    return 0;\n}\n\n\nBOOL CPluginManagerDlg::OnCommand(WPARAM wParam, LPARAM lParam)\n{\n    UINT uMsg = LOWORD(wParam);\n    //选择了插件命令\n    if (uMsg >= ID_PLUGIN_COMMAND_START && uMsg <= ID_PLUGIN_COMMAND_MAX)\n    {\n        int index = uMsg - ID_PLUGIN_COMMAND_START;\n        if (m_item_selected >= 0 && m_item_selected < static_cast<int>(theApp.m_plugins.GetPlugins().size()))\n        {\n            ITMPlugin* plugin = theApp.m_plugins.GetPlugins()[m_item_selected].plugin;\n            if (plugin != nullptr && plugin->GetAPIVersion() >= 5)\n            {\n                plugin->OnPluginCommand(index, (void*)GetSafeHwnd(), nullptr);\n            }\n        }\n    }\n\n    return CBaseDialog::OnCommand(wParam, lParam);\n}\n"
  },
  {
    "path": "TrafficMonitor/PluginManagerDlg.h",
    "content": "﻿#pragma once\n#include \"BaseDialog.h\"\n#include \"LinkStatic.h\"\n#include \"ListCtrlEx.h\"\n\n// CPluginManagerDlg 对话框\n\nclass CPluginManagerDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CPluginManagerDlg)\n\npublic:\n    CPluginManagerDlg(CWnd* pParent = nullptr);   // 标准构造函数\n    virtual ~CPluginManagerDlg();\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_PLUGIN_MANAGER_DIALOG };\n#endif\n\nprivate:\n    CListCtrlEx m_list_ctrl;\n    int m_item_selected{ -1 };\n    CMenu m_menu;\n    CLinkStatic m_plugin_download_lnk;\n    CLinkStatic m_plugin_dev_guide_lnk;\n    CLinkStatic m_open_plugin_dir_lnk;\n    CImageList m_plugin_icon_list;\n\nprotected:\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    void EnableControl();\n    bool IsSelectedValid();\n    bool IsSelectedPluginEnable();     //选中插件是否可用\n\n    enum Column\n    {\n        COL_FILE_NAME,\n        COL_NAME,\n        COL_VERSION,\n        COL_STATUS,\n        COL_MAX\n    };\n\n    DECLARE_MESSAGE_MAP()\n\n    // 通过 CBaseDialog 继承\n    virtual CString GetDialogName() const override;\n    virtual bool InitializeControls() override;\n\npublic:\n    virtual BOOL OnInitDialog();\n    afx_msg void OnNMRClickList1(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnNMClickList1(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnBnClickedOptinsButton();\n    afx_msg void OnBnClickedPluginInfoButton();\n    afx_msg void OnNMDblclkList1(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnInitMenu(CMenu* pMenu);\n    afx_msg void OnPluginDetail();\n    afx_msg void OnPluginOptions();\n    afx_msg void OnPluginDisable();\nprotected:\n    afx_msg LRESULT OnLinkClicked(WPARAM wParam, LPARAM lParam);\n    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);\n};\n"
  },
  {
    "path": "TrafficMonitor/PluginUpdateHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"PluginUpdateHelper.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n#include \"TinyXml2Helper.h\"\n\nstatic void VersionFromString(const std::string& version_str, std::vector<int>& versions)\n{\n    versions.clear();\n    //拆分字符串\n    std::vector<std::string> vec_version;\n    CCommon::StringSplit(version_str, '.', vec_version);\n    //转换为整数保存\n    for (const auto& str : vec_version)\n    {\n        //去掉除数字以外的字符\n        std::string str_ver;\n        for (auto ch : str)\n        {\n            if (ch >= '0' && ch <= '9')\n                str_ver.push_back(ch);\n        }\n\n        versions.push_back(atoi(str_ver.c_str()));\n    }\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////\nPluginVersion::PluginVersion()\n{\n}\n\nPluginVersion::PluginVersion(const std::wstring& version)\n{\n    m_version_str = CCommon::AsciiToStr(version);\n    VersionFromString(m_version_str, m_version);\n}\n\nPluginVersion::PluginVersion(const std::string& version)\n{\n    m_version_str = version;\n    VersionFromString(m_version_str, m_version);\n}\n\nbool PluginVersion::operator<(const PluginVersion& another) const\n{\n    for (size_t i{}; i < m_version.size() || i < another.m_version.size(); i++)\n    {\n        if (GetSubVersion(i) < another.GetSubVersion(i))\n            return true;\n    }\n    return false;\n}\n\nbool PluginVersion::operator==(const PluginVersion& another) const\n{\n    for (size_t i{}; i < m_version.size() || i < another.m_version.size(); i++)\n    {\n        if (GetSubVersion(i) != another.GetSubVersion(i))\n            return false;\n    }\n    return true;\n}\n\nstd::string PluginVersion::GetVersionString() const\n{\n    return m_version_str;\n}\n\nstd::wstring PluginVersion::GetVersionWString() const\n{\n    return CCommon::AsciiToUnicode(m_version_str);\n}\n\nint PluginVersion::GetSubVersion(size_t index) const\n{\n    if (index < m_version.size())\n        return m_version[index];\n    return 0;\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////\nbool CPluginUpdateHelper::CheckForUpdate()\n{\n    m_latest_versions.clear();\n    std::wstring url;\n    //更新源为Gitee\n    if (theApp.m_general_data.update_source == 1)\n        url = L\"https://gitee.com/zhongyang219/TrafficMonitorPlugins/raw/main/plugins_version.xml\";\n    //更新源为Github\n    else\n        url = L\"https://raw.githubusercontent.com/zhongyang219/TrafficMonitorPlugins/main/plugins_version.xml\";\n\n    //获取url内容\n    std::string version_info;\n    if (CCommon::GetURL(url, version_info))\n    {\n        //解析xml，获取版本信息\n        tinyxml2::XMLDocument doc;\n        doc.Parse(version_info.c_str(), version_info.size());\n        //遍历插件版本\n        CTinyXml2Helper::IterateChildNode(doc.RootElement(), [&](tinyxml2::XMLElement* ele) {\n            std::wstring file_name = CCommon::StrToUnicode(CTinyXml2Helper::ElementAttribute(ele, \"file_name\"));\n            std::string plugin_version(CTinyXml2Helper::ElementAttribute(ele, \"version\"));\n            PluginVersion version(plugin_version);\n            m_latest_versions.emplace(file_name, version);\n        });\n        return true;\n    }\n    return false;\n}\n\nconst PluginVersion& CPluginUpdateHelper::GetPluginLatestVersions(const std::wstring& file_name) const\n{\n    auto iter = m_latest_versions.find(file_name);\n    if (iter != m_latest_versions.end())\n    {\n        return iter->second;\n    }\n    static PluginVersion empty_version;\n    return empty_version;\n}\n"
  },
  {
    "path": "TrafficMonitor/PluginUpdateHelper.h",
    "content": "﻿#pragma once\n\nclass PluginVersion\n{\npublic:\n    PluginVersion();\n    PluginVersion(const std::wstring& version);\n    PluginVersion(const std::string& version);\n\n    bool operator<(const PluginVersion& another) const;\n    bool operator==(const PluginVersion& another) const;\n\n    std::string GetVersionString() const;\n    std::wstring GetVersionWString() const;\n\nprotected:\n    int GetSubVersion(size_t index) const;\n\nprivate:\n    std::vector<int> m_version;\n    std::string m_version_str;\n};\n\nclass CPluginUpdateHelper\n{\npublic:\n    bool CheckForUpdate();\n\n    //获取一个插件的最新版本\n    const PluginVersion& GetPluginLatestVersions(const std::wstring& file_name) const;\n\nprivate:\n    std::map<std::wstring, PluginVersion> m_latest_versions;    //在线获取到的每个插件的最新版本信息\n};\n\n"
  },
  {
    "path": "TrafficMonitor/ReadMe.txt",
    "content": "﻿================================================================================\n    MICROSOFT 基础类库 : TrafficMonitor 项目概述\n===============================================================================\n\n应用程序向导已为您创建了此 TrafficMonitor 应用程序。此应用程序不仅演示 Microsoft 基础类的基本使用方法，还可作为您编写应用程序的起点。\n\n本文件概要介绍组成 TrafficMonitor 应用程序的每个文件的内容。\n\nTrafficMonitor.vcxproj\n    这是使用应用程序向导生成的 VC++ 项目的主项目文件，其中包含生成该文件的 Visual C++ 的版本信息，以及有关使用应用程序向导选择的平台、配置和项目功能的信息。\n\nTrafficMonitor.vcxproj.filters\n    这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中，通过这种关联，在特定节点下以分组形式显示具有相似扩展名的文件。例如，“.cpp”文件与“源文件”筛选器关联。\n\nTrafficMonitor.h\n    这是应用程序的主头文件。\n    其中包括其他项目特定的标头（包括 Resource.h），并声明 CTrafficMonitorApp 应用程序类。\n\nTrafficMonitor.cpp\n    这是包含应用程序类 CTrafficMonitorApp 的主应用程序源文件。\n\nTrafficMonitor.rc\n    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源包含在 2052 中。\n\nres\\TrafficMonitor.ico\n    这是用作应用程序图标的图标文件。此图标包括在主资源文件 TrafficMonitor.rc 中。\n\nres\\TrafficMonitor.rc2\n    此文件包含不在 Microsoft Visual C++ 中进行编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。\n\n\n/////////////////////////////////////////////////////////////////////////////\n\n应用程序向导创建一个对话框类：\n\nTrafficMonitorDlg.h、TrafficMonitorDlg.cpp - 对话框\n    这些文件包含 CTrafficMonitorDlg 类。此类定义应用程序的主对话框的行为。对话框模板包含在 TrafficMonitor.rc 中，该文件可以在 Microsoft Visual C++ 中编辑。\n\n/////////////////////////////////////////////////////////////////////////////\n\n其他功能：\n\nActiveX 控件\n    该应用程序包含对使用 ActiveX 控件的支持。\n\n/////////////////////////////////////////////////////////////////////////////\n\n其他标准文件:\n\nStdAfx.h, StdAfx.cpp\n    这些文件用于生成名为 TrafficMonitor.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。\n\nResource.h\n    这是标准头文件，可用于定义新的资源 ID。Microsoft Visual C++ 将读取并更新此文件。\n\nTrafficMonitor.manifest\n\tWindows XP 使用应用程序清单文件来描述特定版本的并行程序集的应用程序依赖项。加载程序使用这些信息来从程序集缓存中加载相应的程序集，并保护其不被应用程序访问。应用程序清单可能会包含在内，以作为与应用程序可执行文件安装在同一文件夹中的外部 .manifest 文件进行重新分发，它还可能以资源的形式包含在可执行文件中。\n/////////////////////////////////////////////////////////////////////////////\n\n其他注释:\n\n应用程序向导使用“TODO:”来指示应添加或自定义的源代码部分。\n\n如果应用程序使用共享 DLL 中的 MFC，您将需要重新分发 MFC DLL。如果应用程序所使用的语言与操作系统的区域设置不同，则还需要重新分发相应的本地化资源 mfc110XXX.DLL。\n有关上述话题的更多信息，请参见 MSDN 文档中有关重新分发 Visual C++ 应用程序的部分。\n\n/////////////////////////////////////////////////////////////////////////////\n"
  },
  {
    "path": "TrafficMonitor/RenderAPISupport.h",
    "content": "﻿#pragma once\n#include <utility>\n#include <type_traits>\n#include <memory>\n#include <unordered_set>\n\n#define TRAFFICMONITOR_HAS_FUNCTION_CALL(function_name, class_name) \\\n    ::is_function_##function_name##_exist<class_name>::value\n#define TRAFFICMONITOR_DEFINE_HAS_FUNCTION_CALL(function_name)                 \\\n    template <typename T>                                                      \\\n    class is_function_##function_name##_exist                                  \\\n    {                                                                          \\\n        using Existence = char;                                                \\\n        struct Inexistence                                                     \\\n        {                                                                      \\\n            char unused[2];                                                    \\\n        };                                                                     \\\n                                                                               \\\n        template <typename C>                                                  \\\n        static Existence test(decltype(&C::function_name));                    \\\n        template <typename C>                                                  \\\n        static Inexistence test(...);                                          \\\n                                                                               \\\n    public:                                                                    \\\n        constexpr static bool value = sizeof(test<T>(0)) == sizeof(Existence); \\\n    }\n\nTRAFFICMONITOR_DEFINE_HAS_FUNCTION_CALL(AddResource);\nTRAFFICMONITOR_DEFINE_HAS_FUNCTION_CALL(RemoveResource);\nTRAFFICMONITOR_DEFINE_HAS_FUNCTION_CALL(Recreate);\n\ntemplate <class... Ts>\nstruct MutipleStorage : public Ts...\n{\n};\n\ntemplate <class T>\nusing storage_t = typename T::Storage;\n\ntemplate <class T>\nusing resource_t = typename T::Resource;\n\ntemplate <class T>\nstruct get_first_template_argument;\ntemplate <template <class> class T1, class T2>\nstruct get_first_template_argument<T1<T2>>\n{\n    using type = T2;\n};\ntemplate <class T>\nusing get_first_template_argument_t = typename get_first_template_argument<T>::type;\n\ntemplate <class T>\nstruct resolve_member_function;\ntemplate <class R, class C>\nstruct resolve_member_function<R C::*>\n{\n    using member_type = R;\n    using class_type = C;\n};\ntemplate<class T>\nusing get_member_class_t = typename resolve_member_function<T>::class_type;\ntemplate <class T>\nusing get_member_t = typename resolve_member_function<T>::member_type;\n\n/**\n * @brief CRTP 基类\n *\n * @tparam Device 是子类\n */\ntemplate <class Device>\nclass CTrackableDevice\n{\n    static_assert(!std::is_pointer<Device>{}, \"Type Device should not be a pointer type.\");\n    using DevicePointer = std::add_pointer_t<Device>;\n\npublic:\n    struct Storage\n    {\n        DevicePointer m_p_device;\n        auto GetDevicePointer()\n            -> DevicePointer&\n        {\n            return m_p_device;\n        }\n    };\n\nprivate:\n    std::shared_ptr<Storage> m_sp_storage;\n\npublic:\n    CTrackableDevice()\n        : m_sp_storage{}\n    {\n        auto p_device = static_cast<DevicePointer>(this);\n        m_sp_storage = std::make_shared<Storage>(p_device);\n    }\n    CTrackableDevice(std::shared_ptr<Storage> sp_storage)\n        : m_sp_storage{sp_storage}\n    {\n    }\n    ~CTrackableDevice() = default;\n    CTrackableDevice(const CTrackableDevice&)\n        : m_sp_storage{}\n    {\n        auto p_device = static_cast<DevicePointer>(this);\n        m_sp_storage = std::make_shared<Storage>(p_device);\n    }\n    CTrackableDevice& operator=(const CTrackableDevice&)\n    {\n        auto p_device = static_cast<DevicePointer>(this);\n        this->m_sp_storage = std::make_shared<Storage>(p_device);\n        return *this;\n    }\n    CTrackableDevice(CTrackableDevice&& other) noexcept\n        : m_sp_storage{std::exchange(other.m_sp_storage, nullptr)}\n    {\n        m_sp_storage.GetDevicePointer() = static_cast<DevicePointer>(this);\n    }\n    CTrackableDevice& operator=(CTrackableDevice&& other) noexcept\n    {\n        m_sp_storage = std::exchange(other.m_sp_storage, nullptr);\n        m_sp_storage.GetDevicePointer() = static_cast<DevicePointer>(this);\n        return *this;\n    }\n\n    auto GetSharedDevicePointerStorage() const\n        -> std::shared_ptr<Storage>\n    {\n        return m_sp_storage;\n    }\n};\n\ntemplate <class Device>\nclass CDeviceResourceBase;\n\ntemplate <class Resource>\nclass CResourceTracker\n{\n    /**\n     * @brief 将CDeviceResource<Device>变换为CDeviceResourceBase<Device>*\n     *\n     */\n    using ResourcePointer =\n        std::add_pointer_t<\n            CDeviceResourceBase<\n                get_first_template_argument_t<Resource>>>;\n\npublic:\n    struct Storage\n    {\n        std::unordered_set<ResourcePointer> m_resource_pointer_set{};\n\n        auto GetResourcePointerSet()\n            -> std::unordered_set<ResourcePointer>&\n        {\n            return m_resource_pointer_set;\n        }\n        void AddResource(ResourcePointer p_resource)\n        {\n            auto count = m_resource_pointer_set.count(p_resource);\n            if (count == 0)\n            {\n                m_resource_pointer_set.insert(p_resource);\n            }\n        }\n        void RemoveResource(ResourcePointer p_resource)\n        {\n            m_resource_pointer_set.erase(p_resource);\n        }\n    };\n\nprivate:\n    std::shared_ptr<Storage> m_sp_storage;\n\npublic:\n    CResourceTracker()\n        : m_sp_storage{std::make_shared<CResourceTracker>()}\n    {\n    }\n    CResourceTracker(std::shared_ptr<Storage> m_sp_storage)\n        : m_sp_storage{m_sp_storage}\n    {\n    }\n    auto GetTrackerSet() const noexcept\n        -> const std::unordered_set<ResourcePointer>&\n    {\n        return m_sp_storage->GetResourcePointerSet();\n    }\n    auto GetSharedResourceTrackerStorage()\n        -> std::shared_ptr<Storage>\n    {\n        return m_sp_storage;\n    }\n};\n\n#define TRAFFICMONITOR_DV_V_ARGS(v) decltype(v), v\n\ntemplate <class T, T PClassFunction, class Resource, class... Args>\nvoid CallFunctionForEachResource(CResourceTracker<Resource>& tracker, Args&&... args)\n{\n    static_assert(!std::is_base_of<decltype(*tracker.GetTrackerSet().begin()), Resource>{},\n                  \"Type Resource is not derived from std::remove_pointer_t<CResourceTracker<Resource>::ResourcePointer>\");\n\n    auto ref_track_set = tracker.GetTrackerSet();\n    for (auto&& it : ref_track_set)\n    {\n        auto* it_impl = static_cast<Resource*>(it);\n        (it_impl->*PClassFunction)(std::forward<Args>(args)...);\n    }\n}\n\ntemplate <class Resource, class Device>\nvoid NotifyAllResourceWhenDeviceRecreate(CResourceTracker<Resource>& tracker, Device& device)\n{\n    CallFunctionForEachResource<TRAFFICMONITOR_DV_V_ARGS(&Resource::OnDeviceRecreate)>(tracker, device);\n}\n\ntemplate <class Device>\nclass CDeviceResourceBase\n{\npublic:\n    using DeviceType = typename Device::Type;\n    using Storage = typename Device::Storage;\n\nprivate:\n    static_assert(TRAFFICMONITOR_HAS_FUNCTION_CALL(AddResource, Storage), \"Function Storage::AddResource not found.\");\n    static_assert(TRAFFICMONITOR_HAS_FUNCTION_CALL(RemoveResource, Storage), \"Function Storage::RemoveResource not found.\");\n\n    std::weak_ptr<Storage> m_wp_device_storage;\n\n    static void BeginTrack(CDeviceResourceBase& device_resource)\n    {\n        auto sp_device_storage = device_resource.m_wp_device_storage.lock();\n        if (sp_device_storage)\n        {\n            sp_device_storage->AddResource(std::addressof(device_resource));\n        }\n    }\n    static void EndTrack(CDeviceResourceBase& device_resource)\n    {\n        auto sp_device_storage = device_resource.m_wp_device_storage.lock();\n        if (sp_device_storage)\n        {\n            sp_device_storage->RemoveResource(std::addressof(device_resource));\n        }\n    }\n\npublic:\n    CDeviceResourceBase(const std::shared_ptr<Storage> sp_device_storage)\n        : m_wp_device_storage{sp_device_storage}\n    {\n        BeginTrack(*this);\n    }\n\nprotected:\n    ~CDeviceResourceBase()\n    {\n        EndTrack(*this);\n    }\n\npublic:\n    CDeviceResourceBase(const CDeviceResourceBase& other)\n        : m_wp_device_storage{other.m_wp_device_storage}\n    {\n        BeginTrack(*this);\n    }\n    CDeviceResourceBase& operator=(CDeviceResourceBase& other)\n    {\n        this->m_wp_device_storage = other.m_wp_device;\n        BeginTrack(*this);\n        return *this;\n    }\n    CDeviceResourceBase(CDeviceResourceBase&& other)\n        : m_wp_device_storage{}\n    {\n        EndTrack(other);\n        m_wp_device_storage = std::exchange(other.m_wp_device_storage, nullptr);\n        BeginTrack(*this);\n    }\n    CDeviceResourceBase& operator=(CDeviceResourceBase&& other)\n    {\n        EndTrack(other);\n        this->m_wp_device_storage = std::exchange(other.m_wp_device_storage, nullptr);\n        BeginTrack(*this);\n        return *this;\n    }\n};\n\ntemplate <class Device>\nclass CDeviceResource : public CDeviceResourceBase<Device>\n{\nprivate:\n    using Base = CDeviceResourceBase<Device>;\n\npublic:\n    using Base::Base;\n    using typename Base::DeviceType;\n\n    virtual void OnDeviceRecreate(DeviceType new_device) noexcept = 0;\n};\n"
  },
  {
    "path": "TrafficMonitor/SelectConnectionsDlg.cpp",
    "content": "﻿// SelectConnectionsDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"SelectConnectionsDlg.h\"\n#include \"afxdialogex.h\"\n#include \"AdapterCommon.h\"\n\n// CSelectConnectionsDlg 对话框\n\nIMPLEMENT_DYNAMIC(CSelectConnectionsDlg, CBaseDialog)\n\nCSelectConnectionsDlg::CSelectConnectionsDlg(const StringSet& connections_hide, CWnd* pParent /*=nullptr*/)\n\t: m_connections_hide(connections_hide), CBaseDialog(IDD_SELECT_CONNECTIONS_DIALOG, pParent)\n{\n    std::vector<NetWorkConection> connections;\n    CAdapterCommon::GetAdapterInfo(connections);\n    for (const auto& item : connections)\n        m_all_connection_names.push_back(CCommon::StrToUnicode(item.description.c_str()));\n}\n\nCSelectConnectionsDlg::~CSelectConnectionsDlg()\n{\n}\n\nvoid CSelectConnectionsDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_LIST1, m_list_ctrl);\n}\n\n\nCString CSelectConnectionsDlg::GetDialogName() const\n{\n    //throw std::logic_error(\"The method or operation is not implemented.\");\n    return _T(\"SelectConnectionsDlg\");\n}\n\nBEGIN_MESSAGE_MAP(CSelectConnectionsDlg, CBaseDialog)\nEND_MESSAGE_MAP()\n\n\n// CSelectConnectionsDlg 消息处理程序\n\n\nBOOL CSelectConnectionsDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_CONNECTION), FALSE);\n    m_list_ctrl.SetItemHeight(0, theApp.DPI(20));\n\n    //向列表中添加项目\n    for (const auto& connection_name : m_all_connection_names)\n    {\n        m_list_ctrl.AddString(connection_name.c_str());\n        if (!m_connections_hide.Contains(connection_name))\n            m_list_ctrl.SetCheck(m_list_ctrl.GetCount() - 1, TRUE);\n        else\n            m_list_ctrl.SetCheck(m_list_ctrl.GetCount() - 1, FALSE);\n    }\n\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CSelectConnectionsDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //保存每个项目的勾选状态\n    bool is_empty{ true };\n    for (int i = 0; i < static_cast<int>(m_all_connection_names.size()); i++)\n    {\n        bool is_checked = (m_list_ctrl.GetCheck(i) != 0);\n        if (is_checked)\n            is_empty = false;\n        m_connections_hide.SetStrContained(m_all_connection_names[i], !is_checked);\n    }\n\n    if (is_empty)\n    {\n        MessageBox(CCommon::LoadText(IDS_SELECT_AT_LEASE_ONE_WARNING), NULL, MB_ICONWARNING | MB_OK);\n        return;\n    }\n\n    CBaseDialog::OnOK();\n}\n"
  },
  {
    "path": "TrafficMonitor/SelectConnectionsDlg.h",
    "content": "﻿#pragma once\n#include \"CommonData.h\"\n#include \"BaseDialog.h\"\n\n// CSelectConnectionsDlg 对话框\n\nclass CSelectConnectionsDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CSelectConnectionsDlg)\n\npublic:\n\tCSelectConnectionsDlg(const StringSet& connections_hide, CWnd* pParent = nullptr);   // 标准构造函数\n\tvirtual ~CSelectConnectionsDlg();\n\n    const StringSet& GetData() const { return m_connections_hide; }\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_SELECT_CONNECTIONS_DIALOG };\n#endif\n\nprivate:\n    CCheckListBox m_list_ctrl;\n    std::vector<std::wstring> m_all_connection_names;\n    StringSet m_connections_hide;\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    virtual CString GetDialogName() const override;\n\n\tDECLARE_MESSAGE_MAP()\n\npublic:\n    virtual BOOL OnInitDialog();\n    virtual void OnOK();\n};\n"
  },
  {
    "path": "TrafficMonitor/SetItemOrderDlg.cpp",
    "content": "﻿// SetItemOrderDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"SetItemOrderDlg.h\"\n#include \"afxdialogex.h\"\n\n\n// CSetItemOrderDlg 对话框\n\nIMPLEMENT_DYNAMIC(CSetItemOrderDlg, CBaseDialog)\n\nCSetItemOrderDlg::CSetItemOrderDlg(CWnd* pParent /*=nullptr*/)\n    : CBaseDialog(IDD_SELECT_ORDER_DIALOG, pParent), m_item_order(true)\n{\n    m_item_order.Init();\n}\n\nCSetItemOrderDlg::~CSetItemOrderDlg()\n{\n}\n\nvoid CSetItemOrderDlg::SetItemOrder(const std::vector<int>& item_order)\n{\n    m_item_order.SetOrder(item_order);\n}\n\nconst std::vector<int>& CSetItemOrderDlg::GetItemOrder() const\n{\n    return m_item_order.GetItemOrderConst();\n}\n\nvoid CSetItemOrderDlg::SetDisplayItem(const DisplayItemSet& display_item)\n{\n    m_display_item = display_item;\n}\n\nDisplayItemSet CSetItemOrderDlg::GetDisplayItem() const\n{\n    return m_display_item;\n}\n\nvoid CSetItemOrderDlg::SetPluginDisplayItem(const StringSet& plugin_item)\n{\n    m_plugin_item = plugin_item;\n}\n\nconst StringSet& CSetItemOrderDlg::GetPluginDisplayItem() const\n{\n    return m_plugin_item;\n}\n\nvoid CSetItemOrderDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_LIST1, m_list_ctrl);\n}\n\n\nBEGIN_MESSAGE_MAP(CSetItemOrderDlg, CBaseDialog)\n    ON_BN_CLICKED(IDC_MOVE_UP_BUTTON, &CSetItemOrderDlg::OnBnClickedMoveUpButton)\n    ON_BN_CLICKED(IDC_MOVE_DOWN_BUTTON, &CSetItemOrderDlg::OnBnClickedMoveDownButton)\n    ON_BN_CLICKED(IDC_RESTORE_DEFAULT_BUTTON, &CSetItemOrderDlg::OnBnClickedRestoreDefaultButton)\n    ON_LBN_SELCHANGE(IDC_LIST1, &CSetItemOrderDlg::OnLbnSelchangeList1)\n    ON_CLBN_CHKCHANGE(IDC_LIST1, &CSetItemOrderDlg::OnCheckChanged)\nEND_MESSAGE_MAP()\n\n\n// CSetItemOrderDlg 消息处理程序\n\n\nBOOL CSetItemOrderDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_ITEM), FALSE);\t\t// 设置小图标\n\n    m_list_ctrl.SetItemHeight(0, DPI(20));\n    EnableCtrl(-1);\n    ShowItem();\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\nvoid CSetItemOrderDlg::ShowItem()\n{\n    //向列表中添加项目\n    m_list_ctrl.ResetContent();\n    m_all_displayed_item = m_item_order.GetAllDisplayItemsWithOrder();\n    for (const auto& item : m_all_displayed_item)\n    {\n        m_list_ctrl.AddString(CTaskbarItemOrderHelper::GetItemDisplayName(item));\n        if (GetItemChecked(item))\n            m_list_ctrl.SetCheck(m_list_ctrl.GetCount() - 1, TRUE);\n        else\n            m_list_ctrl.SetCheck(m_list_ctrl.GetCount() - 1, FALSE);\n    }\n}\n\nvoid CSetItemOrderDlg::EnableCtrl(int list_selected)\n{\n    EnableDlgCtrl(IDC_MOVE_UP_BUTTON, list_selected > 0 && list_selected < static_cast<int>(m_all_displayed_item.size()));\n    EnableDlgCtrl(IDC_MOVE_DOWN_BUTTON, list_selected >= 0 && list_selected < static_cast<int>(m_all_displayed_item.size()) - 1);\n}\n\nvoid CSetItemOrderDlg::EnableDlgCtrl(UINT id, bool enable)\n{\n    CWnd* pCtrl = GetDlgItem(id);\n    if (pCtrl != nullptr)\n        pCtrl->EnableWindow(enable);\n}\n\nbool CSetItemOrderDlg::GetItemChecked(CommonDisplayItem item)\n{\n    if (item.IsPlugin())\n    {\n        if (item.PluginItem() != nullptr)\n            return m_plugin_item.Contains(item.PluginItem()->GetItemId());\n    }\n    else\n    {\n        return m_display_item.Contains(item.ItemType());\n    }\n    return false;\n}\n\nvoid CSetItemOrderDlg::SaveItemChecked(CommonDisplayItem item, bool checked)\n{\n    if (item.IsPlugin())\n    {\n        if (item.PluginItem() != nullptr)\n            m_plugin_item.SetStrContained(item.PluginItem()->GetItemId(), checked);\n    }\n    else\n    {\n        if (checked)\n            m_display_item.Add(item.ItemType());\n        else\n            m_display_item.Remove(item.ItemType());\n    }\n}\n\n\nvoid CSetItemOrderDlg::OnBnClickedMoveUpButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    auto& item_list{ m_item_order.GetItemOrder() };\n    int cur_index{ m_list_ctrl.GetCurSel() };\n    int item_count{ static_cast<int>(item_list.size()) };\n    if (cur_index > 0 && cur_index < item_count)\n    {\n        std::swap(item_list[cur_index], item_list[cur_index - 1]);\n        ShowItem();\n        m_list_ctrl.SetCurSel(cur_index - 1);\n        EnableCtrl(cur_index - 1);\n    }\n}\n\n\nvoid CSetItemOrderDlg::OnBnClickedMoveDownButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    auto& item_list{ m_item_order.GetItemOrder() };\n    int cur_index{ m_list_ctrl.GetCurSel() };\n    int item_count{ static_cast<int>(item_list.size()) };\n    if (cur_index >= 0 && cur_index < item_count - 1)\n    {\n        std::swap(item_list[cur_index], item_list[cur_index + 1]);\n        ShowItem();\n        m_list_ctrl.SetCurSel(cur_index + 1);\n        EnableCtrl(cur_index + 1);\n    }\n}\n\n\nvoid CSetItemOrderDlg::OnBnClickedRestoreDefaultButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    auto item_list{ m_item_order.GetItemOrder() };\n    std::sort(item_list.begin(), item_list.end());\n    m_item_order.SetOrder(item_list);\n    ShowItem();\n}\n\nCString CSetItemOrderDlg::GetDialogName() const\n{\n    return _T(\"SetItemOrderDlg\");\n}\n\n\nvoid CSetItemOrderDlg::OnLbnSelchangeList1()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    int cur_index{ m_list_ctrl.GetCurSel() };\n    EnableCtrl(cur_index);\n}\n\n\nvoid CSetItemOrderDlg::OnCheckChanged()\n{\n    //当用户点击项目前面的复选框时保存该项目的勾选状态\n    int cur_index{ m_list_ctrl.GetCurSel() };\n    if (cur_index >= 0 && cur_index < static_cast<int>(m_all_displayed_item.size()))\n    {\n        bool is_checked = (m_list_ctrl.GetCheck(cur_index) != 0);\n        CommonDisplayItem item = m_all_displayed_item[cur_index];\n        SaveItemChecked(item, is_checked);\n    }\n}\n\nvoid CSetItemOrderDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n\n    //保存每个项目的勾选状态\n    //auto item_list = m_item_order.GetAllDisplayItemsWithOrder();\n    //int i = 0;\n    //for (; i < static_cast<int>(item_list.size()); i++)\n    //{\n    //    bool is_checked = (m_list_ctrl.GetCheck(i) != 0);\n    //    CommonDisplayItem item = item_list[i];\n    //    SaveItemChecked(item, is_checked);\n    //}\n\n    if (m_display_item.IsEmpty() && m_plugin_item.data().empty())\n        m_display_item.Add(TDI_UP);\n\n    CBaseDialog::OnOK();\n}\n"
  },
  {
    "path": "TrafficMonitor/SetItemOrderDlg.h",
    "content": "﻿#pragma once\n#include \"BaseDialog.h\"\n\n// CSetItemOrderDlg 对话框\n\nclass CSetItemOrderDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CSetItemOrderDlg)\n\npublic:\n    CSetItemOrderDlg(CWnd* pParent = nullptr);   // 标准构造函数\n    virtual ~CSetItemOrderDlg();\n\n    //设置/获取显示顺序\n    void SetItemOrder(const std::vector<int>& item_order);\n    const std::vector<int>& GetItemOrder() const;\n\n    //设置/获取显示项目\n    void SetDisplayItem(const DisplayItemSet& display_item);\n    DisplayItemSet GetDisplayItem() const;\n\n    void SetPluginDisplayItem(const StringSet& plugin_item);\n    const StringSet& GetPluginDisplayItem() const;\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_SELECT_ORDER_DIALOG };\n#endif\n\nprivate:\n    CTaskbarItemOrderHelper m_item_order;   //显示项目的顺序\n    CCheckListBox m_list_ctrl;\n    DisplayItemSet m_display_item;        //要显示的内置项目\n    StringSet m_plugin_item;            //要显示的插件项目\n    std::vector<CommonDisplayItem> m_all_displayed_item;    //在列表中显示的所有项目\n\nprotected:\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    void ShowItem();\n    void EnableCtrl(int list_selected);\n    void EnableDlgCtrl(UINT id, bool enable);\n\n    bool GetItemChecked(CommonDisplayItem item);\n    void SaveItemChecked(CommonDisplayItem item, bool checked);\n\n    // 通过 CBaseDialog 继承\n    virtual CString GetDialogName() const override;\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    afx_msg void OnBnClickedMoveUpButton();\n    afx_msg void OnBnClickedMoveDownButton();\n    afx_msg void OnBnClickedRestoreDefaultButton();\n    afx_msg void OnLbnSelchangeList1();\n    afx_msg void OnCheckChanged();\n    virtual void OnOK();\n};\n"
  },
  {
    "path": "TrafficMonitor/SettingsHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"SettingsHelper.h\"\n#include \"TrafficMonitor.h\"\n\nCSettingsHelper::CSettingsHelper()\n    : CIniHelper(theApp.m_config_path)\n{\n}\n\nCSettingsHelper::CSettingsHelper(const std::wstring& file_path)\n    : CIniHelper(file_path)\n{\n}\n\nvoid CSettingsHelper::SaveFontData(const wchar_t* AppName, const FontInfo& font)\n{\n    WriteString(AppName, L\"font_name\", wstring(font.name));\n    WriteInt(AppName, L\"font_size\", font.size);\n    bool style[4];\n    style[0] = font.bold;\n    style[1] = font.italic;\n    style[2] = font.underline;\n    style[3] = font.strike_out;\n    WriteBoolArray(AppName, L\"font_style\", style, 4);\n}\n\nvoid CSettingsHelper::LoadFontData(const wchar_t* AppName, FontInfo& font, const FontInfo& default_font) const\n{\n    font.name = GetString(AppName, L\"font_name\", default_font.name).c_str();\n    font.size = GetInt(AppName, L\"font_size\", default_font.size);\n    bool style[4];\n    GetBoolArray(AppName, L\"font_style\", style, 4);\n    font.bold = style[0];\n    font.italic = style[1];\n    font.underline = style[2];\n    font.strike_out = style[3];\n}\n\nvoid CSettingsHelper::LoadMainWndColors(const wchar_t* AppName, const wchar_t* KeyName, const std::set<CommonDisplayItem>& all_items, std::map<CommonDisplayItem, COLORREF>& text_colors, COLORREF default_color)\n{\n    CString default_str;\n    default_str.Format(_T(\"%d\"), default_color);\n    wstring str{ default_str.GetString() };\n    _GetString(AppName, KeyName, str);\n    std::vector<wstring> split_result;\n    CCommon::StringSplit(str, L',', split_result);\n    size_t index = 0;\n    const std::set<CommonDisplayItem>& items{ all_items.empty() ? theApp.m_plugins.AllDisplayItemsWithPlugins() : all_items };\n    for (auto iter = items.begin(); iter != items.end(); ++iter)\n    {\n        if (index < split_result.size())\n            text_colors[*iter] = _wtoi(split_result[index].c_str());\n        else if (!split_result.empty())\n            text_colors[*iter] = _wtoi(split_result[0].c_str());\n        else\n            text_colors[*iter] = default_color;\n        index++;\n    }\n}\n\nvoid CSettingsHelper::SaveMainWndColors(const wchar_t* AppName, const wchar_t* KeyName, const std::map<CommonDisplayItem, COLORREF>& text_colors)\n{\n    CString str;\n    for (auto iter = text_colors.begin(); iter != text_colors.end(); ++iter)\n    {\n        CString tmp;\n        tmp.Format(_T(\"%d,\"), iter->second);\n        str += tmp;\n    }\n    _WriteString(AppName, KeyName, wstring(str));\n}\n\nvoid CSettingsHelper::LoadTaskbarWndColors(const wchar_t* AppName, const wchar_t* KeyName, std::map<CommonDisplayItem, TaskbarItemColor>& text_colors, const wchar_t* default_str)\n{\n    wstring str{ default_str };\n    _GetString(AppName, KeyName, str);\n    std::vector<wstring> split_result;\n    CCommon::StringSplit(str, L',', split_result);\n    size_t index = 0;\n    COLORREF default_color = _wtoi(default_str);\n    for (auto iter = theApp.m_plugins.AllDisplayItemsWithPlugins().begin(); iter != theApp.m_plugins.AllDisplayItemsWithPlugins().end(); ++iter)\n    {\n        if (index < split_result.size())\n            text_colors[*iter].label = _wtoi(split_result[index].c_str());\n        //else if (!split_result.empty())\n        //    text_colors[*iter].label = _wtoi(split_result[0].c_str());\n        else\n            text_colors[*iter].label = default_color;\n\n        if (index + 1 < split_result.size())\n            text_colors[*iter].value = _wtoi(split_result[index + 1].c_str());\n        //else if (split_result.size() > 1)\n        //    text_colors[*iter].value = _wtoi(split_result[1].c_str());\n        else\n            text_colors[*iter].value = default_color;\n        index += 2;\n    }\n}\n\nvoid CSettingsHelper::LoadTaskbarWndColors(const wchar_t* AppName, const wchar_t* KeyName, std::map<CommonDisplayItem, TaskbarItemColor>& text_colors, COLORREF default_color)\n{\n    CString default_str;\n    default_str.Format(_T(\"%d\"), default_color);\n    LoadTaskbarWndColors(AppName, KeyName, text_colors, default_str.GetString());\n}\n\nvoid CSettingsHelper::SaveTaskbarWndColors(const wchar_t* AppName, const wchar_t* KeyName, const std::map<CommonDisplayItem, TaskbarItemColor>& text_colors)\n{\n    CString str;\n    for (auto iter = text_colors.begin(); iter != text_colors.end(); ++iter)\n    {\n        CString tmp;\n        tmp.Format(_T(\"%d,%d,\"), iter->second.label, iter->second.value);\n        str += tmp;\n    }\n    _WriteString(AppName, KeyName, wstring(str));\n}\n\nvoid CSettingsHelper::LoadDisplayStr(const wchar_t* AppName, DispStrings& disp_str, bool is_main_window) const\n{\n    for (auto display_item : AllDisplayItems)\n    {\n        std::wstring str{ CommonDisplayItem(display_item).DefaultString(is_main_window)};\n        bool exist = GetString(AppName, CommonDisplayItem(display_item).GetItemIniKeyName(), str);\n        //主窗口只读取配置文件中存在的项，任务栏窗口读取所有项\n        if (!is_main_window || exist)\n            disp_str.Get(display_item) = str;\n    }\n}\n\nvoid CSettingsHelper::SaveDisplayStr(const wchar_t* AppName, const DispStrings& disp_str)\n{\n    for (const auto& item : disp_str.GetAllItems())\n    {\n        if (!item.first.IsPlugin())\n        {\n            WriteString(AppName, item.first.GetItemIniKeyName(), item.second);\n        }\n    }\n}\n\nvoid CSettingsHelper::LoadPluginDisplayStr(const wchar_t* AppName, DispStrings& disp_str, bool is_main_window)\n{\n    for (const auto& plugin : theApp.m_plugins.GetPluginItems())\n    {\n        std::wstring str{ plugin->GetItemLableText() };\n        bool exist = GetString(AppName, plugin->GetItemId(), str);\n        //主窗口只读取配置文件中存在的项，任务栏窗口读取所有项\n        if (!is_main_window || exist)\n            disp_str.Load(plugin->GetItemId(), str);\n    }\n}\n\nvoid CSettingsHelper::SavePluginDisplayStr(const wchar_t* AppName, const DispStrings& disp_str)\n{\n    for (const auto& plugin : theApp.m_plugins.GetPluginItems())\n    {\n        if (disp_str.GetAllItems().find(plugin) != disp_str.GetAllItems().end())\n            WriteString(AppName, plugin->GetItemId(), disp_str.GetConst(plugin));\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/SettingsHelper.h",
    "content": "﻿#pragma once\n#include \"IniHelper.h\"\n#include \"CommonData.h\"\n\nclass CSettingsHelper : public CIniHelper\n{\npublic:\n    CSettingsHelper();\n    CSettingsHelper(const std::wstring& file_path);\n\n    void SaveFontData(const wchar_t* AppName, const FontInfo& font);\n    void LoadFontData(const wchar_t* AppName, FontInfo& font, const FontInfo& default_font) const;\n\n    /**\n     * @brief  读取主窗口颜色设置\n     * @param AppName[in] ini文件的段\n     * @param KeyName[in] ini文件的key\n     * @param text_colors[out] 保存读取到的颜色\n     * @param default_color[in] 默认颜色\n     */\n    void LoadMainWndColors(const wchar_t* AppName, const wchar_t* KeyName, const std::set<CommonDisplayItem>& all_items, std::map<CommonDisplayItem, COLORREF>& text_colors, COLORREF default_color);\n    \n    /**\n     * @brief  保存主窗口颜色设置\n     * @param AppName ini文件的段\n     * @param KeyName ini文件的key\n     * @param text_colors 要保存的颜色\n     */\n    void SaveMainWndColors(const wchar_t* AppName, const wchar_t* KeyName, const std::map<CommonDisplayItem, COLORREF>& text_colors);\n\n    void LoadTaskbarWndColors(const wchar_t* AppName, const wchar_t* KeyName, std::map<CommonDisplayItem, TaskbarItemColor>& text_colors, const wchar_t* default_str);\n    void LoadTaskbarWndColors(const wchar_t* AppName, const wchar_t* KeyName, std::map<CommonDisplayItem, TaskbarItemColor>& text_colors, COLORREF default_color);\n    void SaveTaskbarWndColors(const wchar_t* AppName, const wchar_t* KeyName, const std::map<CommonDisplayItem, TaskbarItemColor>& text_colors);\n\n    void LoadDisplayStr(const wchar_t* AppName, DispStrings& disp_str, bool is_main_window) const;\n    void SaveDisplayStr(const wchar_t* AppName, const DispStrings& disp_str);\n\n    void LoadPluginDisplayStr(const wchar_t* AppName, DispStrings& disp_str, bool is_main_window);\n    void SavePluginDisplayStr(const wchar_t* AppName, const DispStrings& disp_str);\n\n};\n\n"
  },
  {
    "path": "TrafficMonitor/SimpleXML.cpp",
    "content": "#include \"stdafx.h\"\n#include \"SimpleXML.h\"\n\n\nCSimpleXML::CSimpleXML(const wstring & xml_path)\n{\n\tifstream file_stream{ xml_path };\n\tif (file_stream.fail())\n\t{\n\t\treturn;\n\t}\n\t//ȡļ\n\tstring xml_str;\n\twhile (!file_stream.eof())\n\t{\n\t\txml_str.push_back(file_stream.get());\n\t}\n\txml_str.pop_back();\n\tif (!xml_str.empty() && xml_str.back() != L'\\n')\t\t//ȷļĩβлس\n\t\txml_str.push_back(L'\\n');\n\t//жļǷutf8\n\tbool is_utf8;\n\tif (xml_str.size() >= 3 && xml_str[0] == -17 && xml_str[1] == -69 && xml_str[2] == -65)\n\t{\n\t\t//UTF8BOMɾBOM\n\t\tis_utf8 = true;\n\t\txml_str = xml_str.substr(3);\n\t}\n\telse\n\t{\n\t\tis_utf8 = false;\n\t}\n\t//תUnicode\n\tm_xml_content = CCommon::StrToUnicode(xml_str.c_str(), is_utf8);\n}\n\nCSimpleXML::CSimpleXML()\n{\n}\n\n\nCSimpleXML::~CSimpleXML()\n{\n}\n\nwstring CSimpleXML::GetNode(const wchar_t * node, const wchar_t * parent) const\n{\n\twstring node_content = _GetNode(parent, m_xml_content);\n\treturn _GetNode(node, node_content);\n}\n\nwstring CSimpleXML::GetNode(const wchar_t * node) const\n{\n\treturn _GetNode(node, m_xml_content);\n}\n\nwstring CSimpleXML::_GetNode(const wchar_t * node, const wstring & content)\n{\n\twstring result;\n\twstring node_start{ L'<' };\n\twstring node_end{ L'<' };\n\tnode_start += node;\n\tnode_start += L'>';\n\tnode_end += L'/';\n\tnode_end += node;\n\tnode_end += L'>';\n\n\tsize_t index_start, index_end;\n\tindex_start = content.find(node_start);\n\tindex_end = content.find(node_end);\n\tif (index_start == wstring::npos || index_end == wstring::npos)\n\t\treturn wstring();\n\n\tresult = content.substr(index_start + node_start.size(), index_end - index_start - node_start.size());\n\treturn result;\n}\n"
  },
  {
    "path": "TrafficMonitor/SimpleXML.h",
    "content": "//һ׵XML\n#pragma once\n#include \"Common.h\"\n\nclass CSimpleXML\n{\npublic:\n\tCSimpleXML(const wstring& xml_path);\n\tCSimpleXML();\n\t~CSimpleXML();\n\n\tvoid LoadXMLContentDirect(const wstring& xml_content) { m_xml_content = xml_content; }\n\n\twstring GetNode(const wchar_t* node, const wchar_t* parent) const;\n\twstring GetNode(const wchar_t* node) const;\n\n\tstatic wstring _GetNode(const wchar_t* node, const wstring& content);\n\nprotected:\n\twstring m_xml_content;\n\n};\n\n"
  },
  {
    "path": "TrafficMonitor/SkinAutoAdaptSettingDlg.cpp",
    "content": "﻿// SkinAutoAdaptSettingDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"afxdialogex.h\"\n#include \"SkinAutoAdaptSettingDlg.h\"\n#include \"SkinManager.h\"\n\n\n// CSkinAutoAdaptSettingDlg 对话框\n\nIMPLEMENT_DYNAMIC(CSkinAutoAdaptSettingDlg, CBaseDialog)\n\nCSkinAutoAdaptSettingDlg::CSkinAutoAdaptSettingDlg(CWnd* pParent /*=nullptr*/)\n\t: CBaseDialog(IDD_SKIN_AUTO_ADAPT_DLG, pParent)\n{\n\n}\n\nCSkinAutoAdaptSettingDlg::~CSkinAutoAdaptSettingDlg()\n{\n}\n\nvoid CSkinAutoAdaptSettingDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_DARK_MODE_SKIN_COMBO, m_dark_mode_skin_combo);\n    DDX_Control(pDX, IDC_LIGHT_MODE_SKIN_COMBO, m_light_mode_skin_combo);\n}\n\nCString CSkinAutoAdaptSettingDlg::GetDialogName() const\n{\n    return _T(\"SkinAutoAdaptSettingDlg\");\n}\n\nbool CSkinAutoAdaptSettingDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_DARK_MODE_STATIC },\n        { CtrlTextInfo::C0, IDC_DARK_MODE_SKIN_COMBO },\n        { CtrlTextInfo::L1, IDC_LIGHT_MODE_STATIC },\n        { CtrlTextInfo::C0, IDC_LIGHT_MODE_SKIN_COMBO }\n    });\n    return true;\n}\n\n\nBEGIN_MESSAGE_MAP(CSkinAutoAdaptSettingDlg, CBaseDialog)\nEND_MESSAGE_MAP()\n\n\n// CSkinAutoAdaptSettingDlg 消息处理程序\n\n\nBOOL CSkinAutoAdaptSettingDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    //初始化下拉列表\n    for (const auto& skin_name : CSkinManager::Instance().GetSkinNames())\n    {\n        m_dark_mode_skin_combo.AddString(skin_name.c_str());\n        m_light_mode_skin_combo.AddString(skin_name.c_str());\n    }\n\n    int dark_mode_skin = CSkinManager::Instance().FindSkinIndex(theApp.m_cfg_data.skin_name_dark_mode);\n    int light_mode_skin = CSkinManager::Instance().FindSkinIndex(theApp.m_cfg_data.skin_name_light_mode);\n    m_dark_mode_skin_combo.SetCurSel(dark_mode_skin);\n    m_light_mode_skin_combo.SetCurSel(light_mode_skin);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n    // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CSkinAutoAdaptSettingDlg::OnOK()\n{\n    m_dark_mode_skin = m_dark_mode_skin_combo.GetCurSel();\n    m_light_mode_skin = m_light_mode_skin_combo.GetCurSel();\n\n    CBaseDialog::OnOK();\n}\n"
  },
  {
    "path": "TrafficMonitor/SkinAutoAdaptSettingDlg.h",
    "content": "﻿#pragma once\n#include \"afxdialogex.h\"\n#include \"BaseDialog.h\"\n\n// CSkinAutoAdaptSettingDlg 对话框\n\nclass CSkinAutoAdaptSettingDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CSkinAutoAdaptSettingDlg)\n\npublic:\n\tCSkinAutoAdaptSettingDlg(CWnd* pParent = nullptr);   // 标准构造函数\n\tvirtual ~CSkinAutoAdaptSettingDlg();\n\n    int GetDarkModeSkin() const { return m_dark_mode_skin; }\n    int GetLightModeSkin() const { return m_light_mode_skin; }\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_SKIN_AUTO_ADAPT_DLG };\n#endif\n\nprivate:\n    CComboBox m_dark_mode_skin_combo;\n    CComboBox m_light_mode_skin_combo;\n\n    int m_dark_mode_skin{};\n    int m_light_mode_skin{};\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    virtual CString GetDialogName() const override;\n    virtual bool InitializeControls() override;\n\n\tDECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    virtual void OnOK();\n};\n"
  },
  {
    "path": "TrafficMonitor/SkinDlg.cpp",
    "content": "﻿// SkinDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"SkinDlg.h\"\n#include \"afxdialogex.h\"\n#include \"SkinAutoAdaptSettingDlg.h\"\n#include \"SkinManager.h\"\n\n\n// CSkinDlg 对话框\n\nIMPLEMENT_DYNAMIC(CSkinDlg, CBaseDialog)\n\nCSkinDlg::CSkinDlg(CWnd* pParent /*=NULL*/)\n    : CBaseDialog(IDD_SKIN_DIALOG, pParent)\n{\n\n}\n\nCSkinDlg::~CSkinDlg()\n{\n}\n\nCString CSkinDlg::GetDialogName() const\n{\n    return _T(\"SkinDlg\");\n}\n\nbool CSkinDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_SKIN_AUTO_ADAPT_CHECK, CtrlTextInfo::W32 },\n        { CtrlTextInfo::L3, IDC_SKIN_AUTO_ADAPT_BUTTON, CtrlTextInfo::W16 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_SKIN_DOWNLOAD_STATIC },\n        { CtrlTextInfo::L3, IDC_SKIN_COURSE_STATIC },\n        { CtrlTextInfo::L2, IDC_OPEN_SKIN_DIR_STATIC }\n    });\n\n    return true;\n}\n\nvoid CSkinDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_SKIN_COURSE_STATIC, m_skin_course);\n    DDX_Control(pDX, IDC_SKIN_DOWNLOAD_STATIC, m_skin_download);\n    DDX_Control(pDX, IDC_PREVIEW_GROUP_STATIC, m_preview_static);\n    DDX_Control(pDX, IDC_NOTIFY_STATIC, m_notify_static);\n    DDX_Control(pDX, IDC_OPEN_SKIN_DIR_STATIC, m_open_skin_dir_lnk);\n    DDX_Control(pDX, IDC_LIST1, m_skin_list_box);\n}\n\n\nvoid CSkinDlg::ShowPreview()\n{\n    //载入布局数据\n    m_skin_data.Load(CSkinManager::Instance().GetSkinName(m_skin_selected));\n    //获取当前皮肤中用户更改字体\n    SkinSettingData cur_skin_data;\n    if (CSkinManager::Instance().GetSkinSettingDataByIndex(m_skin_selected, cur_skin_data))\n    {\n        m_skin_data.SetSettingData(cur_skin_data);\n    }\n    //获取预览区大小\n    m_view->SetSize(m_skin_data.GetPreviewInfo().width, m_skin_data.GetPreviewInfo().height);\n    //刷新预览图\n    m_view->Invalidate();\n\n    //显示皮肤作者\n    SetDlgItemText(IDC_SKIN_INFO, CCommon::LoadText(IDS_SKIN_AUTHOUR, m_skin_data.GetSkinInfo().skin_author.c_str()));\n    ////设置提示信息\n    //bool cover_font_setting{ !m_skin_data.GetSkinInfo().font_info.name.IsEmpty() || (m_skin_data.GetSkinInfo().font_info.size >= MIN_FONT_SIZE && m_skin_data.GetSkinInfo().font_info.size <= MAX_FONT_SIZE) };\n    //bool cover_str_setting{ !m_skin_data.GetSkinInfo().display_text.IsInvalid() };\n    //cover_font_setting = cover_font_setting && theApp.m_general_data.allow_skin_cover_font;\n    //cover_str_setting = cover_str_setting && theApp.m_general_data.allow_skin_cover_text;\n    //if (cover_font_setting && cover_str_setting)\n    //    m_notify_static.SetWindowTextEx(CCommon::LoadText(IDS_OVERWRITE_FONT_TEXT_WARNING));\n    //else if (cover_font_setting)\n    //    m_notify_static.SetWindowTextEx(CCommon::LoadText(IDS_OVERWRITE_FONT_WARNING));\n    //else if (cover_str_setting)\n    //    m_notify_static.SetWindowTextEx(CCommon::LoadText(IDS_OVERWRITE_TEXT_WARNING));\n    //else\n    //m_notify_static.SetWindowTextEx(_T(\"\"));\n}\n\n\nCRect CSkinDlg::CalculateViewRect()\n{\n    CRect rect;\n    m_preview_static.GetWindowRect(rect);\t\t//获取“预览” group box 的位置\n    ScreenToClient(&rect);\n    CRect scroll_view_rect{ rect };\n    scroll_view_rect.DeflateRect(DPI(12), DPI(40));\n    scroll_view_rect.top = rect.top + DPI(28);\n    return scroll_view_rect;\n}\n\n\nBEGIN_MESSAGE_MAP(CSkinDlg, CBaseDialog)\n    ON_LBN_SELCHANGE(IDC_LIST1, &CSkinDlg::OnLbnSelchangeList1)\n    ON_WM_SIZE()\n    ON_MESSAGE(WM_LINK_CLICKED, &CSkinDlg::OnLinkClicked)\n    ON_BN_CLICKED(IDC_SKIN_AUTO_ADAPT_BUTTON, &CSkinDlg::OnBnClickedSkinAutoAdaptButton)\n    ON_BN_CLICKED(IDC_SKIN_AUTO_ADAPT_CHECK, &CSkinDlg::OnBnClickedSkinAutoAdaptCheck)\nEND_MESSAGE_MAP()\n\n\n// CSkinDlg 消息处理程序\n\nBOOL CSkinDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetIcon(theApp.GetMenuIcon(IDI_SKIN), FALSE);\t\t// 设置小图标\n    //初始化选择框\n    m_skin_list_box.SetItemHeight(0, DPI(18));\n    for (const auto& skin_name : CSkinManager::Instance().GetSkinNames())\n    {\n        m_skin_list_box.AddString(skin_name.c_str());\n    }\n    m_skin_list_box.SetCurSel(m_skin_selected);\n    //初始化预览视图\n    m_view = (CSkinPreviewView*)RUNTIME_CLASS(CSkinPreviewView)->CreateObject();\n    m_view->Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL, CalculateViewRect(), this, 3000);\n    m_view->InitialUpdate();\n    m_view->SetSkinData(&m_skin_data);\n    m_view->ShowWindow(SW_SHOW);\n\n    //设置提示信息\n    m_notify_static.SetTextColor(RGB(252, 128, 45));\n    m_notify_static.SetBackColor(GetSysColor(COLOR_BTNFACE));\n    m_notify_static.SetWindowTextEx(_T(\"\"));\n\n    //显示预览图片\n    ShowPreview();\n\n    //初始化控件\n    CheckDlgButton(IDC_SKIN_AUTO_ADAPT_CHECK, theApp.m_cfg_data.skin_auto_adapt);\n    EnableDlgCtrl(IDC_SKIN_AUTO_ADAPT_BUTTON, theApp.m_cfg_data.skin_auto_adapt);\n\n    //设置超链接\n    m_skin_course.SetURL(_T(\"https://github.com/zhongyang219/TrafficMonitor/wiki/%E7%9A%AE%E8%82%A4%E5%88%B6%E4%BD%9C%E6%95%99%E7%A8%8B\"));\n    if (theApp.m_general_data.update_source == 1)\n        m_skin_download.SetURL(_T(\"https://gitee.com/zhongyang219/TrafficMonitorSkin/blob/master/%E7%9A%AE%E8%82%A4%E4%B8%8B%E8%BD%BD.md\"));\n    else\n        m_skin_download.SetURL(_T(\"https://github.com/zhongyang219/TrafficMonitorSkin/blob/master/皮肤下载.md\"));\n    m_open_skin_dir_lnk.SetLinkIsURL(false);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CSkinDlg::OnLbnSelchangeList1()\n{\n    m_skin_selected = m_skin_list_box.GetCurSel();\n    ShowPreview();\n}\n\n\nvoid CSkinDlg::OnSize(UINT nType, int cx, int cy)\n{\n    CBaseDialog::OnSize(nType, cx, cy);\n\n    // TODO: 在此处添加消息处理程序代码\n    if (m_preview_static.m_hWnd != NULL && nType != SIZE_MINIMIZED && m_view != nullptr)\n        m_view->MoveWindow(CalculateViewRect());\n}\n\n\nafx_msg LRESULT CSkinDlg::OnLinkClicked(WPARAM wParam, LPARAM lParam)\n{\n    CWnd* pCtrl = (CWnd*)wParam;\n    //点击了“打开皮肤目录”\n    if (pCtrl == &m_open_skin_dir_lnk)\n    {\n        CreateDirectory(theApp.m_skin_path.c_str(), NULL);       //如果皮肤目录不存在，则创建它\n        ShellExecute(NULL, _T(\"open\"), _T(\"explorer\"), theApp.m_skin_path.c_str(), NULL, SW_SHOWNORMAL);\n    }\n    return 0;\n}\n\n\nvoid CSkinDlg::OnBnClickedSkinAutoAdaptButton()\n{\n    CSkinAutoAdaptSettingDlg dlg;\n    const auto& skins{ CSkinManager::Instance().GetSkinNames() };\n    if (dlg.DoModal() == IDOK)\n    {\n        int dark_mode_skin = dlg.GetDarkModeSkin();\n        int light_mode_skin = dlg.GetLightModeSkin();\n        if (dark_mode_skin >= 0 && dark_mode_skin < static_cast<int>(skins.size()))\n            theApp.m_cfg_data.skin_name_dark_mode = skins[dark_mode_skin];\n        if (light_mode_skin >= 0 && light_mode_skin < static_cast<int>(skins.size()))\n            theApp.m_cfg_data.skin_name_light_mode = skins[light_mode_skin];\n    }\n}\n\n\nvoid CSkinDlg::OnOK()\n{\n    theApp.m_cfg_data.skin_auto_adapt = (IsDlgButtonChecked(IDC_SKIN_AUTO_ADAPT_CHECK) != FALSE);\n\n    CBaseDialog::OnOK();\n}\n\n\nvoid CSkinDlg::OnBnClickedSkinAutoAdaptCheck()\n{\n    bool skin_auto_adapt_checked = (IsDlgButtonChecked(IDC_SKIN_AUTO_ADAPT_CHECK) != FALSE);\n    EnableDlgCtrl(IDC_SKIN_AUTO_ADAPT_BUTTON, skin_auto_adapt_checked);\n}\n"
  },
  {
    "path": "TrafficMonitor/SkinDlg.h",
    "content": "﻿#pragma once\n#include \"afxwin.h\"\n#include\"StaticEx.h\"\n#include \"PictureStatic.h\"\n#include \"CSkinPreviewView.h\"\n#include \"LinkStatic.h\"\n#include \"BaseDialog.h\"\n\n// CSkinDlg 对话框\n\nclass CSkinDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CSkinDlg)\n\npublic:\n    CSkinDlg(CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~CSkinDlg();\n\n    int m_skin_selected;\t\t\t//选择的皮肤\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_SKIN_DIALOG };\n#endif\n\n    const CSkinFile& GetSkinData() const { return m_skin_data; }\n\nprotected:\n    virtual CString GetDialogName() const override;\n    virtual bool InitializeControls() override;\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\nprotected:\n    //控件变量\n    CListBox m_skin_list_box;   //选择皮肤列表\n    CLinkStatic m_skin_course;\t//“皮肤制作教程”超链接\n    CLinkStatic m_skin_download;\t//“更多皮肤下载”超链接\n    CLinkStatic m_open_skin_dir_lnk;\n    CSkinPreviewView* m_view;\t//预览区视图类\n    CStatic m_preview_static;\n    CStaticEx m_notify_static;\t//显示提示信息的static控件\n\n    CSkinFile m_skin_data;\t\t//皮肤数据\n\n    void ShowPreview();\t\t//显示皮肤预览\n    CRect CalculateViewRect();\t\t//根据窗口大小计算预览视图的大小\n\n    DECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    afx_msg void OnLbnSelchangeList1();\n    afx_msg void OnSize(UINT nType, int cx, int cy);\nprotected:\n    afx_msg LRESULT OnLinkClicked(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnBnClickedSkinAutoAdaptButton();\n    virtual void OnOK();\n    afx_msg void OnBnClickedSkinAutoAdaptCheck();\n};\n"
  },
  {
    "path": "TrafficMonitor/SkinFile.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"SkinFile.h\"\n#include \"Common.h\"\n#include \"FilePathHelper.h\"\n#include \"TrafficMonitor.h\"\n#include \"SettingsHelper.h\"\n#include \"DrawCommon.h\"\n#include \"DrawCommonEx.h\"\n#include \"SkinManager.h\"\n\n\nCSkinFile::CSkinFile()\n{\n}\n\n\nCSkinFile::~CSkinFile()\n{\n    SAFE_DELETE(m_background_png_s);\n    SAFE_DELETE(m_background_png_l);\n}\n\nstatic CSkinFile::LayoutItem LayoutItemFromXmlNode(tinyxml2::XMLElement* ele)\n{\n    CSkinFile::LayoutItem layout_item;\n    layout_item.x = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele, \"x\")));\n    layout_item.y = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele, \"y\")));\n    layout_item.width = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele, \"width\")));\n    layout_item.align = static_cast<CSkinFile::Alignment>(atoi(CTinyXml2Helper::ElementAttribute(ele, \"align\")));\n    layout_item.show = CTinyXml2Helper::StringToBool(CTinyXml2Helper::ElementAttribute(ele, \"show\"));\n    return layout_item;\n}\n\nCSkinFile::Layout CSkinFile::LayoutFromXmlNode(tinyxml2::XMLElement* ele)\n{\n    CSkinFile::Layout layout;\n    layout.width = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele, \"width\")));\n    layout.height = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele, \"height\")));\n    CTinyXml2Helper::IterateChildNode(ele, [&](tinyxml2::XMLElement* ele_layout_item)\n        {\n            string str_layout_item = CTinyXml2Helper::ElementName(ele_layout_item);\n            for (auto display_item : AllDisplayItems)\n            {\n                if (str_layout_item == CSkinFile::GetDisplayItemXmlNodeName(display_item))\n                {\n                    layout.layout_items[display_item] = LayoutItemFromXmlNode(ele_layout_item);\n                    break;\n                }\n            }\n            wstring plugin_id = CCommon::StrToUnicode(m_plugin_map[str_layout_item].c_str(), true);\n            if (!plugin_id.empty())\n            {\n                for (const auto& plugin_item : theApp.m_plugins.GetPluginItems())\n                {\n                    if (plugin_id == plugin_item->GetItemId())\n                    {\n                        layout.layout_items[plugin_item] = LayoutItemFromXmlNode(ele_layout_item);\n                        break;\n                    }\n                }\n            }\n        });\n    return layout;\n}\n\nvoid CSkinFile::DrawSkinText(IDrawCommon& drawer, DrawStr draw_str, CRect rect, COLORREF color, Alignment align)\n{\n    int text_width = drawer.GetTextWidth(draw_str.GetStr());\n    //标签和数值两端对齐\n    if (align == Alignment::SIDE && text_width < rect.Width())      //只有文本宽度小于矩形的宽度时才使用两端对齐\n    {\n        //绘制标签\n        drawer.DrawWindowText(rect, draw_str.label, color, IDrawCommon::Alignment::LEFT);\n        //绘制数值\n        drawer.DrawWindowText(rect, draw_str.value, color, IDrawCommon::Alignment::RIGHT);\n    }\n    else\n    {\n        IDrawCommon::Alignment text_align = IDrawCommon::Alignment::LEFT;\n        if (align == Alignment::RIGHT)\n            text_align = IDrawCommon::Alignment::RIGHT;\n        else if (align == Alignment::CENTER)\n            text_align = IDrawCommon::Alignment::CENTER;\n        drawer.DrawWindowText(rect, draw_str.GetStr(), color, text_align);\n    }\n}\n\nbool CSkinFile::Load(const wstring& skin_name)\n{\n    std::wstring file_path{ theApp.m_skin_path + skin_name + L\"\\\\skin.xml\" };\n    if (!CCommon::FileExist(file_path.c_str()))\n        file_path = theApp.m_skin_path + skin_name + L\"\\\\skin.ini\";\n    CFilePathHelper file_path_helper{ file_path };\n    wstring ext = file_path_helper.GetFileExtension();\n    m_is_error = false;\n    if (ext == L\"ini\")\n    {\n        LoadFromIni(file_path);\n    }\n    else\n    {\n        if (!LoadFromXml(file_path))\n        {\n            LoadFromIni(std::wstring());\n            m_skin_info.text_color = { RGB(255, 255, 255) };\n            m_is_error = true;\n        }\n    }\n\n    CSkinManager::SkinSettingDataFronSkin(m_setting_data, *this);\n\n    if (m_font.m_hObject)\n        m_font.DeleteObject();\n\n    //创建字体对象\n    if (!m_skin_info.font_info.name.IsEmpty() && m_skin_info.font_info.size > 0)\n    {\n        m_skin_info.font_info.Create(m_font, theApp.GetDpi());\n    }\n    else\n    {\n        FontInfo font_info;\n        font_info.name = theApp.m_str_table.GetLanguageInfo().default_font_name.c_str();\n        font_info.size = 10;\n        font_info.Create(m_font, theApp.GetDpi());\n    }\n\n    wstring path_dir = file_path_helper.GetDir();\n\n    //载入png背景图\n    m_is_png = true;\n    //先尝试加载png格式，失败则加载bmp格式\n    SAFE_DELETE(m_background_png_s);\n    m_background_png_s = new Gdiplus::Image((path_dir + BACKGROUND_IMAGE_S_PNG).c_str());\n    if (m_background_png_s->GetLastStatus() != Gdiplus::Ok)\n    {\n        m_is_png = false;\n    }\n    SAFE_DELETE(m_background_png_l);\n    m_background_png_l = new Gdiplus::Image((path_dir + BACKGROUND_IMAGE_L_PNG).c_str());\n    if (m_background_png_l->GetLastStatus() != Gdiplus::Ok)\n    {\n        m_is_png = false;\n    }\n\n    //png背景图加载失败，使用bmp背景图\n    if (!m_is_png)\n    {\n        m_background_s.Destroy();\n        m_background_s.Load((path_dir + BACKGROUND_IMAGE_S).c_str());\n        m_background_l.Destroy();\n        m_background_l.Load((path_dir + BACKGROUND_IMAGE_L).c_str());\n    }\n    return CCommon::FileExist(file_path.c_str());\n}\n\nbool CSkinFile::LoadFromXml(const wstring& file_path)\n{\n    m_skin_info = SkinInfo();\n    m_layout_info = LayoutInfo();\n    m_preview_info = PreviewInfo();\n    std::map<std::string, std::wstring> display_text_map;  //显示项目的文本和xml节点的映射关系。key是xml节点，value是显示文本\n\n    tinyxml2::XMLDocument doc;\n    if (CTinyXml2Helper::LoadXmlFile(doc, file_path.c_str()))\n    {\n        CTinyXml2Helper::IterateChildNode(doc.FirstChildElement(), [&](tinyxml2::XMLElement* child) {\n            string ele_name = CTinyXml2Helper::ElementName(child);\n            //读取皮肤信息\n            if (ele_name == \"skin\")\n            {\n                CTinyXml2Helper::IterateChildNode(child, [&](tinyxml2::XMLElement* skin_item) {\n                    string skin_item_name = CTinyXml2Helper::ElementName(skin_item);\n                    //文本颜色\n                    if (skin_item_name == \"text_color\")\n                    {\n                        string str_text_color = CTinyXml2Helper::ElementText(skin_item);\n                        std::vector<string> split_result;\n                        CCommon::StringSplit(str_text_color, L',', split_result);\n                        for (const auto& str : split_result)\n                        {\n                            m_skin_info.text_color.push_back(atoi(str.c_str()));\n                        }\n                        if (m_skin_info.text_color.size() < theApp.m_plugins.AllDisplayItemsWithPlugins().size())\n                        {\n                            COLORREF default_color{};\n                            if (!m_skin_info.text_color.empty())\n                                default_color = m_skin_info.text_color.front();\n                            m_skin_info.text_color.resize(theApp.m_plugins.AllDisplayItemsWithPlugins().size(), default_color);\n                        }\n                    }\n                    //指定每个项目的颜色\n                    else if (skin_item_name == \"specify_each_item_color\")\n                    {\n                        m_skin_info.specify_each_item_color = CTinyXml2Helper::StringToBool(CTinyXml2Helper::ElementText(skin_item));\n                    }\n                    //皮肤作者\n                    else if (skin_item_name == \"skin_author\")\n                    {\n                        m_skin_info.skin_author = CCommon::StrToUnicode(CTinyXml2Helper::ElementText(skin_item), true);\n                    }\n                    //字体\n                    else if (skin_item_name == \"font\")\n                    {\n                        m_skin_info.font_info.name = CCommon::StrToUnicode(CTinyXml2Helper::ElementAttribute(skin_item, \"name\"), true).c_str();\n                        m_skin_info.font_info.size = atoi(CTinyXml2Helper::ElementAttribute(skin_item, \"size\"));\n                        int font_style = atoi(CTinyXml2Helper::ElementAttribute(skin_item, \"style\"));\n                        m_skin_info.font_info.bold = CCommon::GetNumberBit(font_style, 0);\n                        m_skin_info.font_info.italic = CCommon::GetNumberBit(font_style, 1);\n                        m_skin_info.font_info.underline = CCommon::GetNumberBit(font_style, 2);\n                        m_skin_info.font_info.strike_out = CCommon::GetNumberBit(font_style, 3);\n                    }\n                    else if (skin_item_name == \"display_text\")\n                    {\n                        //这里先保存所有显示文本到display_text_map\n                        CTinyXml2Helper::IterateChildNode(skin_item, [&](tinyxml2::XMLElement* display_text_item) {\n                            string item_name = CTinyXml2Helper::ElementName(display_text_item);\n                            wstring item_text = CCommon::StrToUnicode(CTinyXml2Helper::ElementText(display_text_item), true);\n                            display_text_map[item_name] = item_text;\n                        });\n                    }\n                });\n            }\n            //布局信息\n            else if (ele_name == \"layout\")\n            {\n                m_layout_info.text_height = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(child, \"text_height\")));\n                m_layout_info.no_label = CTinyXml2Helper::StringToBool(CTinyXml2Helper::ElementAttribute(child, \"no_label\"));\n                CTinyXml2Helper::IterateChildNode(child, [this](tinyxml2::XMLElement* ele_layout) {\n                    string str_layout = CTinyXml2Helper::ElementName(ele_layout);\n                    if (str_layout == \"layout_l\")\n                        m_layout_info.layout_l = LayoutFromXmlNode(ele_layout);\n                    else if (str_layout == \"layout_s\")\n                        m_layout_info.layout_s = LayoutFromXmlNode(ele_layout);\n                });\n            }\n            //预览图\n            else if (ele_name == \"preview\")\n            {\n                m_preview_info.width = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(child, \"width\")));\n                m_preview_info.height = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(child, \"height\")));\n                CTinyXml2Helper::IterateChildNode(child, [this](tinyxml2::XMLElement* ele_priview_item) {\n                    string str_item_name = CTinyXml2Helper::ElementName(ele_priview_item);\n                    if (str_item_name == \"l\")\n                    {\n                        m_preview_info.l_pos.x = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele_priview_item, \"x\")));\n                        m_preview_info.l_pos.y = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele_priview_item, \"y\")));\n                    }\n                    else if (str_item_name == \"s\")\n                    {\n                        m_preview_info.s_pos.x = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele_priview_item, \"x\")));\n                        m_preview_info.s_pos.y = theApp.DPI(atoi(CTinyXml2Helper::ElementAttribute(ele_priview_item, \"y\")));\n                    }\n                });\n            }\n            //插件名称映射\n            else if (ele_name == \"plugin_map\")\n            {\n                CTinyXml2Helper::IterateChildNode(child, [this](tinyxml2::XMLElement* plugin_item) {\n                    string ele_name = CTinyXml2Helper::ElementName(plugin_item);\n                    string ele_text = CTinyXml2Helper::ElementText(plugin_item);\n                    m_plugin_map[ele_name] = ele_text;\n                });\n            }\n        });\n    }\n    else\n    {\n        //xml解析失败\n        return false;\n    }\n\n    //载入显示文本\n    for (const auto& display_text_item : display_text_map)\n    {\n        std::string node_name = display_text_item.first;\n        std::wstring item_text = display_text_item.second;\n        //查找内建显示项目\n        for (auto display_item : AllDisplayItems)\n        {\n            if (node_name == CSkinFile::GetDisplayItemXmlNodeName(display_item))\n            {\n                m_skin_info.display_text.Get(display_item) = item_text;\n                break;\n            }\n        }\n        //查找插件项目\n        for (const auto& item : m_plugin_map)\n        {\n            if (node_name == item.first && !item.second.empty())\n            {\n                std::wstring plugin_id = CCommon::StrToUnicode(item.second.c_str(), true);\n                IPluginItem* plugin_item = theApp.m_plugins.GetItemById(plugin_id);\n                if (plugin_item != nullptr)\n                    m_skin_info.display_text.Get(plugin_item) = item_text;\n            }\n        }\n    }\n    return true;\n}\n\nvoid CSkinFile::LoadFromIni(const wstring& file_path)\n{\n    m_skin_info = SkinInfo();\n    m_layout_info = LayoutInfo();\n    m_preview_info = PreviewInfo();\n\n    //获取皮肤信息\n    CSettingsHelper ini(file_path);\n    //获取当前皮肤的文字颜色\n    std::map<CommonDisplayItem, COLORREF> text_colors{};\n    ini.LoadMainWndColors(_T(\"skin\"), _T(\"text_color\"), { TDI_UP, TDI_DOWN, TDI_CPU, TDI_MEMORY }, text_colors, 0);\n    for (const auto& item : text_colors)\n    {\n        m_skin_info.text_color.push_back(item.second);\n    }\n\n    m_skin_info.specify_each_item_color = ini.GetBool(_T(\"skin\"), _T(\"specify_each_item_color\"), false);\n    //获取当前皮肤的字体\n    FontInfo default_font{};\n    default_font.name = theApp.m_str_table.GetLanguageInfo().default_font_name.c_str();\n    default_font.size = 10;\n    ini.LoadFontData(L\"skin\", m_skin_info.font_info, default_font);\n    //获取皮肤作者\n    m_skin_info.skin_author = ini.GetString(_T(\"skin\"), _T(\"skin_author\"), _T(\"unknow\"));\n    //获取显示文本\n    auto getDisplayTextFromIni = [&](DisplayItem display_item, const wchar_t* key_name) {\n        std::wstring str;\n        if (ini.GetString(L\"skin\", key_name, str))\n            m_skin_info.display_text.Get(display_item) = str;\n    };\n    getDisplayTextFromIni(TDI_UP, L\"up_string\");\n    getDisplayTextFromIni(TDI_DOWN, L\"down_string\");\n    getDisplayTextFromIni(TDI_CPU, L\"cpu_string\");\n    getDisplayTextFromIni(TDI_MEMORY, L\"memory_string\");\n    //获取预览区大小\n    m_preview_info.width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"preview_width\"), 238));\n    m_preview_info.height = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"preview_height\"), 105));\n\n    //从ini文件读取皮肤布局，并根据DPI进行缩放\n    m_layout_info.text_height = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"text_height\"), 20));\n    m_layout_info.no_label = ini.GetBool(_T(\"layout\"), _T(\"no_text\"), false);\n\n    m_layout_info.layout_l.width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"width_l\"), 220));\n    m_layout_info.layout_l.height = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"height_l\"), 43));\n    m_layout_info.layout_l.layout_items[TDI_UP].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"up_x_l\"), 6));\n    m_layout_info.layout_l.layout_items[TDI_UP].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"up_y_l\"), 2));\n    m_layout_info.layout_l.layout_items[TDI_UP].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"up_width_l\"), 108));\n    m_layout_info.layout_l.layout_items[TDI_UP].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"up_align_l\"), 0));\n    m_layout_info.layout_l.layout_items[TDI_DOWN].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"down_x_l\"), 114));\n    m_layout_info.layout_l.layout_items[TDI_DOWN].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"down_y_l\"), 2));\n    m_layout_info.layout_l.layout_items[TDI_DOWN].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"down_width_l\"), 110));\n    m_layout_info.layout_l.layout_items[TDI_DOWN].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"down_align_l\"), 0));\n    m_layout_info.layout_l.layout_items[TDI_CPU].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"cpu_x_l\"), 6));\n    m_layout_info.layout_l.layout_items[TDI_CPU].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"cpu_y_l\"), 21));\n    m_layout_info.layout_l.layout_items[TDI_CPU].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"cpu_width_l\"), 108));\n    m_layout_info.layout_l.layout_items[TDI_CPU].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"cpu_align_l\"), 0));\n    m_layout_info.layout_l.layout_items[TDI_MEMORY].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"memory_x_l\"), 114));\n    m_layout_info.layout_l.layout_items[TDI_MEMORY].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"memory_y_l\"), 21));\n    m_layout_info.layout_l.layout_items[TDI_MEMORY].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"memory_width_l\"), 110));\n    m_layout_info.layout_l.layout_items[TDI_MEMORY].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"memory_align_l\"), 0));\n    m_layout_info.layout_l.layout_items[TDI_UP].show = ini.GetBool(_T(\"layout\"), _T(\"show_up_l\"), true);\n    m_layout_info.layout_l.layout_items[TDI_DOWN].show = ini.GetBool(_T(\"layout\"), _T(\"show_down_l\"), true);\n    m_layout_info.layout_l.layout_items[TDI_CPU].show = ini.GetBool(_T(\"layout\"), _T(\"show_cpu_l\"), true);\n    m_layout_info.layout_l.layout_items[TDI_MEMORY].show = ini.GetBool(_T(\"layout\"), _T(\"show_memory_l\"), true);\n    m_preview_info.l_pos.x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"preview_x_l\"), 0));\n    m_preview_info.l_pos.y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"preview_y_l\"), 47));\n\n    m_layout_info.layout_s.width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"width_s\"), 220));\n    m_layout_info.layout_s.height = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"height_s\"), 28));\n    m_layout_info.layout_s.layout_items[TDI_UP].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"up_x_s\"), 6));\n    m_layout_info.layout_s.layout_items[TDI_UP].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"up_y_s\"), 4));\n    m_layout_info.layout_s.layout_items[TDI_UP].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"up_width_s\"), 108));\n    m_layout_info.layout_s.layout_items[TDI_UP].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"up_align_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_DOWN].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"down_x_s\"), 114));\n    m_layout_info.layout_s.layout_items[TDI_DOWN].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"down_y_s\"), 4));\n    m_layout_info.layout_s.layout_items[TDI_DOWN].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"down_width_s\"), 110));\n    m_layout_info.layout_s.layout_items[TDI_DOWN].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"down_align_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_CPU].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"cpu_x_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_CPU].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"cpu_y_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_CPU].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"cpu_width_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_CPU].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"cpu_align_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_MEMORY].x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"memory_x_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_MEMORY].y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"memory_y_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_MEMORY].width = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"memory_width_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_MEMORY].align = static_cast<Alignment>(ini.GetInt(_T(\"layout\"), _T(\"memory_align_s\"), 0));\n    m_layout_info.layout_s.layout_items[TDI_UP].show = ini.GetBool(_T(\"layout\"), _T(\"show_up_s\"), true);\n    m_layout_info.layout_s.layout_items[TDI_DOWN].show = ini.GetBool(_T(\"layout\"), _T(\"show_down_s\"), true);\n    m_layout_info.layout_s.layout_items[TDI_CPU].show = ini.GetBool(_T(\"layout\"), _T(\"show_cpu_s\"), false);\n    m_layout_info.layout_s.layout_items[TDI_MEMORY].show = ini.GetBool(_T(\"layout\"), _T(\"show_memory_s\"), false);\n    m_preview_info.s_pos.x = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"preview_x_s\"), 0));\n    m_preview_info.s_pos.y = theApp.DPI(ini.GetInt(_T(\"layout\"), _T(\"preview_y_s\"), 0));\n}\n\n\nvoid CSkinFile::SetAlpha(int alpha)\n{\n    m_alpha = alpha;\n}\n\nvoid CSkinFile::SetSettingData(const SkinSettingData& setting_data)\n{\n    //如果字体有变化，则重新创建字体\n    if (m_setting_data.font != setting_data.font)\n    {\n        if (m_font.m_hObject)   //如果m_font已经关联了一个字体资源对象，则释放它\n            m_font.DeleteObject();\n        setting_data.font.Create(m_font, theApp.GetDpi());\n    }\n    m_setting_data = setting_data;\n}\n\nvoid CSkinFile::DrawPreview(CDC* pDC, CRect rect)\n{\n    CDrawCommon draw;\n    draw.Create(pDC, nullptr);\n    //设置字体\n    draw.SetFont(&m_font);\n    if (m_is_error)\n    {\n        //显示错误信息\n        draw.DrawWindowText(rect, CCommon::LoadText(IDS_SKIN_FILE_ERROR_INFO), RGB(252, 128, 45));\n    }\n    else\n    {\n        //绘制背景\n        CRect rect_s(CPoint(m_preview_info.s_pos.x, m_preview_info.s_pos.y), CSize(m_layout_info.layout_s.width, m_layout_info.layout_s.height));\n        CRect rect_l(CPoint(m_preview_info.l_pos.x, m_preview_info.l_pos.y), CSize(m_layout_info.layout_l.width, m_layout_info.layout_l.height));\n        if (IsPNG())    //png背景使用GDI+绘制\n        {\n            CDrawCommonEx gdiplus_drawer(pDC);\n            gdiplus_drawer.DrawImage(m_background_png_s, rect_s.TopLeft(), rect_s.Size(), IDrawCommon::StretchMode::STRETCH);\n            gdiplus_drawer.DrawImage(m_background_png_l, rect_l.TopLeft(), rect_l.Size(), IDrawCommon::StretchMode::STRETCH);\n        }\n        else\n        {\n            if (m_background_s.IsNull())\n                draw.FillRect(rect_s, RGB(230, 230, 230));\n            else\n                draw.DrawBitmap(m_background_s, rect_s.TopLeft(), rect_s.Size());\n            if (m_background_l.IsNull())\n                draw.FillRect(rect_l, RGB(230, 230, 230));\n            draw.DrawBitmap(m_background_l, rect_l.TopLeft(), rect_l.Size());\n        }\n\n        std::set<CommonDisplayItem> all_skin_items;\n        GetSkinDisplayItems(all_skin_items);\n\n        //获取每个项目显示的文本\n        std::map<DisplayItem, DrawStr> map_str;\n        for (auto iter = all_skin_items.begin(); iter != all_skin_items.end(); ++iter)\n        {\n            if (iter->IsPlugin())\n                continue;\n            DrawStr draw_str;\n            draw_str.value = CommonDisplayItem(iter->ItemType()).GetItemValueSampleText(true);\n            if (!m_layout_info.no_label)\n            {\n                if (m_setting_data.disp_str.IsInvalid())\n                    draw_str.label = iter->DefaultString(true).c_str();\n                else\n                    draw_str.label = m_setting_data.disp_str.GetConst(*iter).c_str();\n            }\n            map_str[iter->ItemType()] = draw_str;\n        }\n\n        //获取文本颜色\n        std::map<CommonDisplayItem, COLORREF> text_colors{};\n        if (m_setting_data.specify_each_item_color)\n        {\n            text_colors = m_setting_data.text_colors;\n        }\n        else if (!m_setting_data.text_colors.empty())\n        {\n            for (const auto& item : all_skin_items)\n            {\n                text_colors[item] = m_setting_data.text_colors.begin()->second;\n            }\n        }\n\n        //绘制预览图文本\n        auto drawPreviewText = [&](const Layout& layout, const PreviewInfo::Pos& pos) {\n            for (auto iter = map_str.begin(); iter != map_str.end(); ++iter)\n            {\n                auto layout_iter = layout.layout_items.find(iter->first);\n                if (layout_iter == layout.layout_items.end())\n                    continue;\n                auto layout_item = layout_iter->second;\n                if (layout_item.show)\n                {\n                    CPoint point;\n                    point.SetPoint(layout_item.x, layout_item.y);\n                    point.Offset(pos.x, pos.y);\n                    CRect rect(point, CSize(layout_item.width, m_layout_info.text_height));\n                    COLORREF text_color{};\n                    text_color = text_colors[iter->first];\n                    DrawSkinText(draw, iter->second, rect, text_color, layout_item.align);\n                }\n            }\n\n            //绘制插件项目\n            for (const auto& plugin_item : theApp.m_plugins.GetPluginItems())\n            {\n                LayoutItem layout_item = layout.GetItem(plugin_item);\n                if (layout_item.show)\n                {\n                    COLORREF cl{};\n                    auto iter = text_colors.find(plugin_item);\n                    if (iter != text_colors.end())\n                        cl = iter->second;\n                    else if (!text_colors.empty())\n                        cl = text_colors.begin()->second;\n                    //矩形区域\n                    CPoint point;\n                    point.SetPoint(layout_item.x, layout_item.y);\n                    point.Offset(pos.x, pos.y);\n                    CRect rect(point, CSize(layout_item.width, m_layout_info.text_height));\n                    ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(plugin_item);\n                    if (plugin != nullptr && plugin->GetAPIVersion() >= 2)\n                    {\n                        plugin->OnExtenedInfo(ITMPlugin::EI_DRAW_TASKBAR_WND, L\"0\");\n                    }\n                    if (plugin_item->IsCustomDraw())\n                    {\n                        int brightness{ (GetRValue(cl) + GetGValue(cl) + GetBValue(cl)) / 2 };\n                        if (plugin != nullptr && plugin->GetAPIVersion() >= 2)\n                        {\n                            plugin->OnExtenedInfo(ITMPlugin::EI_VALUE_TEXT_COLOR, std::to_wstring(cl).c_str());\n                        }\n                        draw.GetDC()->SetTextColor(cl);\n                        plugin_item->DrawItem(draw.GetDC()->GetSafeHdc(), point.x, point.y, layout_item.width, m_layout_info.text_height, brightness >= 128);\n                    }\n                    else\n                    {\n                        //绘制文本\n                        DrawStr draw_str;\n                        if (m_skin_info.display_text.IsInvalid())\n                            draw_str.label = plugin_item->GetItemLableText();\n                        else\n                            draw_str.label = m_skin_info.display_text.GetConst(plugin_item).c_str();\n                        draw_str.value = plugin_item->GetItemValueSampleText();\n                        DrawSkinText(draw, draw_str, rect, cl, layout_item.align);\n                    }\n                }\n            }\n        };\n\n        //绘制小预览图文本\n        drawPreviewText(m_layout_info.layout_s, m_preview_info.s_pos);\n        //绘制大预览图文本\n        drawPreviewText(m_layout_info.layout_l, m_preview_info.l_pos);\n    }\n}\n\nvoid CSkinFile::DrawInfo(CDC* pDC, bool show_more_info)\n{\n    //绘制背景图\n    Layout& layout{ show_more_info ? m_layout_info.layout_l : m_layout_info.layout_s };\n\n    CRect rect(CPoint(0, 0), CSize(layout.width, layout.height));\n\n    //如果是PNG格式背景，使用UpdateLayeredWindow函数以支持透明背景，显示项目使用GDI+绘制\n    if (IsPNG())\n    {\n        HDC hdcMemory = CreateCompatibleDC(pDC->GetSafeHdc());\n        HBITMAP hBitMap = CreateCompatibleBitmap(pDC->GetSafeHdc(), rect.Width(), rect.Height());\n        SelectObject(hdcMemory, hBitMap);\n\n        BLENDFUNCTION bf{};\n        bf.BlendOp = AC_SRC_OVER;\n        bf.BlendFlags = 0;\n        bf.AlphaFormat = 1;\n        bf.SourceConstantAlpha = m_alpha; // 窗口透明度最大为255，最小为0\n\n        HWND hWnd = theApp.m_pMainWnd->GetSafeHwnd();\n        //绘制背景\n        CDrawCommonEx gdiplus_drawer;\n        gdiplus_drawer.Create(CDC::FromHandle(hdcMemory));\n        Gdiplus::Image* background_image{ show_more_info ? m_background_png_l : m_background_png_s };\n        gdiplus_drawer.DrawImage(background_image, CPoint(0, 0), rect.Size(), CDrawCommon::StretchMode::FILL);\n        \n        //保存完全透明的像素点\n        std::set<DrawCommonHelper::Point> alpha_points;\n        DrawCommonHelper::GetBitmapAlphaPixel(hBitMap, alpha_points);\n\n        //绘制显示项目\n        DrawItemsInfo(gdiplus_drawer, layout, m_font);\n\n        //找出绘制显示项目前不透明，但是绘制后透明的点，并修正其alpha值\n        DrawCommonHelper::FixBitmapTextAlpha(hBitMap, m_alpha, alpha_points);\n\n        SIZE sizeWindow = rect.Size();\n        POINT ptSrc = { 0,0 };\n        ::UpdateLayeredWindow(hWnd, pDC->GetSafeHdc(), nullptr, &sizeWindow, hdcMemory, &ptSrc, 0, &bf, ULW_ALPHA);\n\n        gdiplus_drawer.GetGraphics()->ReleaseHDC(hdcMemory);\n        DeleteObject(hBitMap);\n        DeleteDC(hdcMemory);\n    }\n    //bmp格式背景，使用gdi绘制背景和显示项目\n    else\n    {\n        CDrawDoubleBuffer draw_double_buffer(pDC, rect);\n        CDrawCommon draw;\n        draw.Create(draw_double_buffer.GetMemDC(), nullptr);\n\n        CImage& background_image{ show_more_info ? m_background_l : m_background_s };\n        draw.DrawBitmap(background_image, CPoint(0, 0), CSize(layout.width, layout.height));\n\n        DrawItemsInfo(draw, layout, m_font);\n    }\n}\n\n\nvoid CSkinFile::DrawItemsInfo(IDrawCommon& drawer, Layout& layout, CFont& font) const\n{\n    //获取每个项目显示的文本和数值文本\n    std::map<DisplayItem, DrawStr> map_str;\n    for (const auto& display_item : AllDisplayItems)\n    {\n        if (!m_layout_info.no_label)\n            map_str[display_item].label = theApp.m_main_wnd_data.disp_str.GetConst(display_item).c_str();\n        map_str[display_item].value = CommonDisplayItem(display_item).GetItemValueText(true);\n    }\n\n    //获取文本颜色\n    std::map<CommonDisplayItem, COLORREF> text_colors{};\n    if (theApp.m_main_wnd_data.specify_each_item_color)\n    {\n        text_colors = theApp.m_main_wnd_data.text_colors;\n    }\n    else if (!theApp.m_main_wnd_data.text_colors.empty())\n    {\n        for (const auto& item : theApp.m_plugins.AllDisplayItemsWithPlugins())\n        {\n            text_colors[item] = theApp.m_main_wnd_data.text_colors.begin()->second;\n        }\n    }\n\n    //绘制文本\n    drawer.SetFont(&font);\n\n    //绘制文本\n    int index{};\n    for (auto iter = map_str.begin(); iter != map_str.end(); ++iter)\n    {\n        const auto& layout_item = layout.GetItem(iter->first);\n        if (layout_item.show)\n        {\n            //矩形区域\n            CRect rect(CPoint(layout_item.x, layout_item.y), CSize(layout_item.width, m_layout_info.text_height));\n\n            //文本颜色\n            COLORREF text_color = text_colors[iter->first];\n\n            //绘制文本\n            DrawSkinText(drawer, map_str[iter->first], rect, text_color, layout_item.align);\n        }\n        index++;\n    }\n\n    //绘制插件项目\n    for (const auto& plugin_item : theApp.m_plugins.GetPluginItems())\n    {\n        const auto& layout_item = layout.GetItem(plugin_item);\n        if (layout_item.show)\n        {\n            //插件项目自绘\n            COLORREF cl{};\n            auto iter = text_colors.find(plugin_item);\n            if (iter != text_colors.end())\n                cl = iter->second;\n            else if (!text_colors.empty())\n                cl = text_colors.begin()->second;\n            ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(plugin_item);\n            if (plugin != nullptr && plugin->GetAPIVersion() >= 2)\n            {\n                plugin->OnExtenedInfo(ITMPlugin::EI_DRAW_TASKBAR_WND, L\"0\");\n            }\n            if (plugin_item->IsCustomDraw())\n            {\n                int brightness{ (GetRValue(cl) + GetGValue(cl) + GetBValue(cl)) / 2 };\n                ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(plugin_item);\n                if (plugin != nullptr && plugin->GetAPIVersion() >= 2)\n                {\n                    plugin->OnExtenedInfo(ITMPlugin::EI_VALUE_TEXT_COLOR, std::to_wstring(cl).c_str());\n                }\n                drawer.GetDC()->SetTextColor(cl);\n                drawer.GetDC()->SetBkMode(TRANSPARENT);\n                plugin_item->DrawItem(drawer.GetDC()->GetSafeHdc(), layout_item.x, layout_item.y, layout_item.width, m_layout_info.text_height, brightness >= 128);\n            }\n            else\n            {\n                //矩形区域\n                CRect rect(CPoint(layout_item.x, layout_item.y), CSize(layout_item.width, m_layout_info.text_height));\n\n                //绘制文本\n                DrawStr draw_str;\n                draw_str.label = theApp.m_main_wnd_data.disp_str.GetConst(plugin_item).c_str();\n                draw_str.value = plugin_item->GetItemValueText();\n                DrawSkinText(drawer, draw_str, rect, cl, layout_item.align);\n            }\n        }\n    }\n}\n\n\nstring CSkinFile::GetDisplayItemXmlNodeName(DisplayItem display_item)\n{\n    switch (display_item)\n    {\n    case TDI_UP:\n        return \"up\";\n        break;\n    case TDI_DOWN:\n        return \"down\";\n        break;\n    case TDI_TOTAL_SPEED:\n        return \"total_speed\";\n        break;\n    case TDI_TODAY_TRAFFIC:\n        return \"today_traffic\";\n        break;\n    case TDI_CPU:\n        return \"cpu\";\n        break;\n    case TDI_MEMORY:\n        return \"memory\";\n        break;\n    case TDI_GPU_USAGE:\n        return \"gpu\";\n        break;\n    case TDI_CPU_TEMP:\n        return \"cpu_temperature\";\n        break;\n    case TDI_GPU_TEMP:\n        return \"gpu_temperature\";\n        break;\n    case TDI_HDD_TEMP:\n        return \"hdd_temperature\";\n        break;\n    case TDI_MAIN_BOARD_TEMP:\n        return \"main_board_temperature\";\n        break;\n    case TDI_HDD_USAGE:\n        return \"hdd\";\n        break;\n    case TDI_CPU_FREQ:\n        return \"cpu_freq\";\n        break;\n    default:\n        return string();\n        break;\n    }\n}\n\nvoid CSkinFile::GetSkinDisplayItems(std::set<CommonDisplayItem>& skin_all_items) const\n{\n    skin_all_items.clear();\n    for (const auto& layout_items : GetLayoutInfo().layout_l.layout_items)\n        skin_all_items.insert(layout_items.first);\n    for (const auto& layout_items : GetLayoutInfo().layout_s.layout_items)\n        skin_all_items.insert(layout_items.first);\n}\n"
  },
  {
    "path": "TrafficMonitor/SkinFile.h",
    "content": "﻿#pragma once\n#include \"CommonData.h\"\n#include \"TinyXml2Helper.h\"\n#include \"DrawCommon.h\"\n#include <gdiplus.h>\n\nclass CSkinFile\n{\npublic:\n    CSkinFile();\n    ~CSkinFile();\n\n\n    //\n    /**\n     * @brief  从文件载入皮肤信息\n     * @param skin_name 皮肤名称\n     */\n    bool Load(const wstring& skin_name);\n\n    //皮肤信息\n    struct SkinInfo\n    {\n        std::vector<COLORREF> text_color;   //文本颜色\n        bool specify_each_item_color{};     //是否指定每个项目的颜色\n        wstring skin_author;                //皮肤的作者\n        FontInfo font_info;                 //字体信息\n        DispStrings display_text;    //每一项的显示文本\n\n        COLORREF TextColor(size_t i) const\n        {\n            if (i >= 0 && i < text_color.size())\n                return text_color[i];\n            else if (!text_color.empty())\n                return text_color.front();\n            else\n                return 0;\n        }\n    };\n\n    //对齐方式\n    enum class Alignment\n    {\n        LEFT,       //左对齐\n        RIGHT,      //右对齐\n        CENTER,     //居中\n        SIDE        //两端对齐\n    };\n\n    //皮肤中每一项的布局信息\n    struct LayoutItem\n    {\n        int x{};            //X位置\n        int y{};            //Y位置\n        int width{};        //宽度\n        Alignment align{};  //对齐方式\n        bool show{};        //是否显示\n    };\n\n    //皮肤布局\n    struct Layout\n    {\n        int width{};        //宽度\n        int height{};       //高度\n        std::map<CommonDisplayItem, LayoutItem> layout_items; //每一项的布局信息\n        LayoutItem GetItem(CommonDisplayItem display_item) const\n        {\n            auto iter = layout_items.find(display_item);\n            if (iter != layout_items.end())\n                return iter->second;\n            return LayoutItem();\n        }\n    };\n\n    //皮肤布局信息\n    struct LayoutInfo\n    {\n        int text_height{};  //皮肤文本的高度\n        bool no_label{};    //是否不显示标签\n        Layout layout_l;    //“显示更多信息”时的布局\n        Layout layout_s;    //不“显示更多信息”时的布局\n    };\n\n    //皮肤预览图信息\n    struct PreviewInfo\n    {\n        struct Pos\n        {\n            int x{};\n            int y{};\n        };\n        int width{};    //预览图的宽度\n        int height{};   //预览图的高度\n        Pos l_pos;      //“显示更多信息”时的窗口在预览图中的位置\n        Pos s_pos;      //不“显示更多信息”时的窗口在预览图中的位置\n    };\n\n    const SkinInfo& GetSkinInfo() const { return m_skin_info; }\n    const LayoutInfo& GetLayoutInfo() const { return m_layout_info; }\n    const PreviewInfo& GetPreviewInfo() const { return m_preview_info; }\n\n    const CImage& GetBackgroundL() const { return m_background_l; }\n    const CImage& GetBackgroundS() const { return m_background_s; }\n\n    bool IsPNG() const { return m_is_png; }\n    void SetAlpha(int alpha);       //设置主窗口的不透明度，alpha:0~255，仅当使用png背景时有效\n\n    void SetSettingData(const SkinSettingData& setting_data);\n\n    //绘制预览图\n    //pDC: 绘图的CDC\n    //rect: 绘图区域\n    void DrawPreview(CDC* pDC, CRect rect);\n\n    //绘制主界面\n    void DrawInfo(CDC* pDC, bool show_more_info);\n\n    static string GetDisplayItemXmlNodeName(DisplayItem display_item);\n\n    //获取此皮肤上所有显示项目\n    void GetSkinDisplayItems(std::set<CommonDisplayItem>& skin_all_items) const;\n\nprivate:\n    bool LoadFromXml(const wstring& file_path);     //从xml文件读取皮肤数据\n    void LoadFromIni(const wstring& file_path);     //从ini文件读取皮肤数据（用于兼容旧版皮肤）\n\n    CSkinFile::Layout LayoutFromXmlNode(tinyxml2::XMLElement* ele);\n\n    struct DrawStr\n    {\n        CString label;\n        CString value;\n        CString GetStr() const\n        {\n            return label + value;\n        }\n    };\n\n    static void DrawSkinText(IDrawCommon& drawer, DrawStr draw_str, CRect rect, COLORREF color, Alignment align);\n\n    //绘制主界面中除背景图外所有显示项目\n    void DrawItemsInfo(IDrawCommon& drawer, Layout& layout, CFont& font) const;\n\nprivate:\n    SkinInfo m_skin_info;\n    LayoutInfo m_layout_info;\n    PreviewInfo m_preview_info;\n    std::map<std::string, std::string> m_plugin_map;  //插件名称与xml节点名称的映射关系。key是xml节点名称，value是插件ID\n\n    CFont m_font;\n    CImage m_background_s;\n    CImage m_background_l;\n    bool m_is_png{};\n    Gdiplus::Image* m_background_png_s{};\n    Gdiplus::Image* m_background_png_l{};\n    int m_alpha{ 255 };     //不透明度，仅当背景为png时有效\n    SkinSettingData m_setting_data;\n    bool m_is_error{ false };\n};\n"
  },
  {
    "path": "TrafficMonitor/SkinManager.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"SkinManager.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n#include \"SettingsHelper.h\"\n\nCSkinManager CSkinManager::m_instance;\n\nconst std::wstring SKIN_SETTINGS_PREFIX = L\"skin_\";\n\nvoid CSkinManager::Init()\n{\n    if (!m_init)    //防止重复加载\n    {\n        //获取所有皮肤名称\n        CCommon::GetFiles((theApp.m_skin_path + L\"*\").c_str(), [&](const wstring& file_name)\n            {\n                if (CCommon::IsFolder(theApp.m_skin_path + file_name))\n                    m_skins.push_back(file_name);\n            });\n        if (m_skins.empty())\n            m_skins.push_back(L\"\");\n\n        //载入所有皮肤的独立设置\n        CSettingsHelper ini;\n        std::vector<std::wstring> skin_data_app_names = ini.GetAllAppName(SKIN_SETTINGS_PREFIX);\n        for (const std::wstring& skin_name : skin_data_app_names)\n        {\n            std::wstring app_name = SKIN_SETTINGS_PREFIX + skin_name;\n            //判断皮肤是否存在\n            if (std::find(m_skins.begin(), m_skins.end(), skin_name) != m_skins.end())\n            {\n                CSkinFile skin_file;\n                if (!skin_file.Load(skin_name))\n                    continue;\n                //获取皮肤所有显示项目\n                std::set<CommonDisplayItem> skin_all_items;\n                skin_file.GetSkinDisplayItems(skin_all_items);\n\n                SkinSettingData data;\n                //文本颜色\n                ini.LoadMainWndColors(app_name.c_str(), L\"text_color\", skin_all_items, data.text_colors, 16384); //根据皮肤是否存在来设置默认的文本颜色，皮肤文件不存在时文本颜色默认为白色\n                data.specify_each_item_color = ini.GetBool(app_name.c_str(), L\"specify_each_item_color\", false);\n                //字体\n                FontInfo default_font{};\n                default_font.name = theApp.m_str_table.GetLanguageInfo().default_font_name.c_str();\n                default_font.size = 10;\n                ini.LoadFontData(app_name.c_str(), data.font, default_font);\n                //显示文本\n                ini.LoadDisplayStr(app_name.c_str(), data.disp_str, true);\n                ini.LoadPluginDisplayStr(app_name.c_str(), data.disp_str, true);\n\n                m_skin_setting_data_map[skin_name] = data;\n            }\n        }\n        m_init = true;\n    }\n}\n\nCSkinManager& CSkinManager::Instance()\n{\n    return m_instance;\n}\n\nstd::wstring CSkinManager::GetSkinName(int index) const\n{\n    if (index >= 0 && index < static_cast<int>(m_skins.size()))\n        return m_skins[index];\n    else\n        return std::wstring();\n}\n\nint CSkinManager::FindSkinIndex(const std::wstring& skin_name) const\n{\n    std::wstring _skin_name{ skin_name };\n    SkinNameNormalize(_skin_name);\n    for (size_t i{}; i < m_skins.size(); i++)\n    {\n        if (m_skins[i] == _skin_name)\n            return static_cast<int>(i);\n    }\n    return 0;\n}\n\nbool CSkinManager::GetSkinSettingDataByIndex(int index, SkinSettingData& skin_data)\n{\n    std::wstring skin_name = GetSkinName(index);\n    if (!skin_name.empty())\n    {\n        auto iter = m_skin_setting_data_map.find(skin_name);\n        if (iter != m_skin_setting_data_map.end())\n        {\n            skin_data = iter->second;\n            return true;\n        }\n    }\n    return false;\n}\n\nconst vector<wstring>& CSkinManager::GetSkinNames() const\n{\n    return m_skins;\n}\n\nint CSkinManager::Size() const\n{\n    return static_cast<int>(m_skins.size());\n}\n\nvoid CSkinManager::AddSkinSettingData(const std::wstring& skin_name, const SkinSettingData& data)\n{\n    m_skin_setting_data_map[skin_name] = data;\n}\n\nvoid CSkinManager::Save()\n{\n    //保存所有皮肤的独立配置\n    CSettingsHelper ini;\n    for (const auto& data : m_skin_setting_data_map)\n    {\n        std::wstring app_name = SKIN_SETTINGS_PREFIX + data.first;\n        //文本颜色\n        ini.SaveMainWndColors(app_name.c_str(), L\"text_color\", data.second.text_colors);\n        ini.WriteBool(app_name.c_str(), L\"specify_each_item_color\", data.second.specify_each_item_color);\n        //字体\n        ini.SaveFontData(app_name.c_str(), data.second.font);\n        //显示文本\n        ini.SaveDisplayStr(app_name.c_str(), data.second.disp_str);\n        ini.SavePluginDisplayStr(app_name.c_str(), data.second.disp_str);\n    }\n\n    //移除不存在的皮肤配置\n    //获取所有皮肤配置段\n    auto all_skin_section = ini.GetAllAppName(SKIN_SETTINGS_PREFIX);\n    for (const auto& skin_name : all_skin_section)\n    {\n        //判断皮肤配置是否存在\n        auto iter = m_skin_setting_data_map.find(skin_name);\n        //如果皮肤配置不存在，则将它从ini文件中移除\n        if (iter == m_skin_setting_data_map.end())\n        {\n            ini.RemoveSection(SKIN_SETTINGS_PREFIX + skin_name);\n        }\n    }\n\n    ini.Save();\n}\n\nvoid CSkinManager::SkinSettingDataFronSkin(SkinSettingData& skin_setting_data, const CSkinFile& skin_file)\n{\n    //获取皮肤所有显示项目\n    std::set<CommonDisplayItem> skin_all_items;\n    skin_file.GetSkinDisplayItems(skin_all_items);\n    //获取皮肤的文字颜色\n    skin_setting_data.specify_each_item_color = skin_file.GetSkinInfo().specify_each_item_color;\n    int i{};\n\n    for (const auto& item : skin_all_items)\n    {\n        skin_setting_data.text_colors[item] = skin_file.GetSkinInfo().TextColor(i);\n        i++;\n    }\n    //获取皮肤的字体\n    if (!skin_file.GetSkinInfo().font_info.name.IsEmpty())\n    {\n        skin_setting_data.font = skin_file.GetSkinInfo().font_info;\n    }\n    else\n    {\n        skin_setting_data.font.name = theApp.m_str_table.GetLanguageInfo().default_font_name.c_str();\n        skin_setting_data.font.size = 10;\n    }\n    if (skin_file.GetSkinInfo().font_info.size >= MIN_FONT_SIZE && skin_file.GetSkinInfo().font_info.size <= MAX_FONT_SIZE)\n        skin_setting_data.font.size = skin_file.GetSkinInfo().font_info.size;\n\n    //获取项目的显示文本\n    if (!skin_file.GetLayoutInfo().no_label)\n    {\n        if (!skin_file.GetSkinInfo().display_text.IsInvalid())\n        {\n            for (const auto& display_item : skin_all_items)\n                skin_setting_data.disp_str.Get(display_item) = skin_file.GetSkinInfo().display_text.GetConst(display_item);\n        }\n        //获取皮肤默认的显示文本\n        else\n        {\n            //获取所有显示项目的默认显示文本\n            for (const auto& display_item : skin_all_items)\n                skin_setting_data.disp_str.Get(display_item) = display_item.DefaultString(true);\n        }\n    }\n}\n\nvoid CSkinManager::SkinNameNormalize(std::wstring& skin_name)\n{\n    //如果名称前面有斜杠，则将它去掉\n    if (!skin_name.empty() && (skin_name[0] == L'\\\\' || skin_name[0] == L'/'))\n    {\n        skin_name = skin_name.substr(1);\n    }\n\n}\n"
  },
  {
    "path": "TrafficMonitor/SkinManager.h",
    "content": "﻿#pragma once\n#include \"CommonData.h\"\n#include \"SkinFile.h\"\n\nclass CSkinManager\n{\npublic:\n    void Init();\n    static CSkinManager& Instance();\n    std::wstring GetSkinName(int index) const;\n    int FindSkinIndex(const std::wstring& skin_name) const;\n    bool GetSkinSettingDataByIndex(int index, SkinSettingData& skin_data);\n    const vector<wstring>& GetSkinNames() const;\n    int Size() const;\n    void AddSkinSettingData(const std::wstring& skin_name, const SkinSettingData& data);\n\n    void Save();\n\n    //从一个皮肤文件获取SkinSettingData对象\n    static void SkinSettingDataFronSkin(SkinSettingData& skin_setting_data, const CSkinFile& skin_file);\n\n    //去掉皮肤名称前面的斜杠\n    static void SkinNameNormalize(std::wstring& skin_name);\n\nprivate:\n    CSkinManager()\n    {}\n\nprivate:\n    vector<wstring> m_skins;    //储存皮肤文件的路径\n    std::map<std::wstring, SkinSettingData> m_skin_setting_data_map;    //保存每个皮肤的字体、显示文本设置\n\n    static CSkinManager m_instance;\n    bool m_init{ false };\n};\n\n"
  },
  {
    "path": "TrafficMonitor/SpinEdit.cpp",
    "content": "﻿// SpinEdit.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"SpinEdit.h\"\n\n#define SPIN_ID 3100\n// CSpinEdit\n\nIMPLEMENT_DYNAMIC(CSpinEdit, CEdit)\n\nCSpinEdit::CSpinEdit()\n{\n\n}\n\nCSpinEdit::~CSpinEdit()\n{\n}\n\nvoid CSpinEdit::SetRange(short lower, short upper, short step)\n{\n    m_step = step;\n    if (m_spin.GetSafeHwnd() != NULL)\n        m_spin.SetRange(lower, upper);\n}\n\nvoid CSpinEdit::SetValue(int value)\n{\n    ASSERT(m_step != 0);    // 应当先设置Range\n    if (m_spin.GetSafeHwnd() != NULL)\n        m_spin.SetPos(value);\n}\n\nint CSpinEdit::GetValue()\n{\n    if (m_spin.GetSafeHwnd() != NULL)\n        return m_spin.GetPos32();\n    else\n        return 0;\n}\n\n\nvoid CSpinEdit::SetMouseWheelEnable(bool enable)\n{\n    m_mouse_wheel_enable = enable;\n}\n\n\nBEGIN_MESSAGE_MAP(CSpinEdit, CEdit)\n    ON_MESSAGE(WM_TABLET_QUERYSYSTEMGESTURESTATUS, &CSpinEdit::OnTabletQuerysystemgesturestatus)\n    ON_NOTIFY(UDN_DELTAPOS, SPIN_ID, &CSpinEdit::OnDeltaposSpin)\n    ON_WM_KILLFOCUS()\n    ON_WM_ENABLE()\n    ON_WM_SIZE()\nEND_MESSAGE_MAP()\n\n\n\n// CSpinEdit 消息处理程序\n\nvoid CSpinEdit::PreSubclassWindow()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n\n    // 要求文本左对齐，右侧会被spin控件覆盖\n    // WS_CLIPCHILDREN在绘制中排除子窗口区域，避免重叠的控件绘制闪烁\n    ModifyStyle(ES_CENTER | ES_RIGHT, ES_LEFT | WS_CLIPCHILDREN);\n    m_spin.Create(WS_CHILD | WS_VISIBLE | UDS_ARROWKEYS | UDS_HOTTRACK | UDS_SETBUDDYINT, CRect(), this, SPIN_ID);\n    // 获取spin控件宽度\n    CRect rect;\n    m_spin.GetWindowRect(&rect);\n    m_spin_width = rect.Width();\n    // 设置spin控件区域（作为CEdit的子控件，ClientRect区域外的部分会被裁剪）\n    GetClientRect(&rect);\n    rect.left = rect.right - m_spin_width;\n    m_spin.MoveWindow(&rect);\n    // 设置Edit控件为关联控件\n    m_spin.SetBuddy(this);\n    // 设置默认范围\n    m_spin.SetRange(0, 999);\n    CEdit::PreSubclassWindow();\n}\n\n\nBOOL CSpinEdit::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n\n    //如果m_mouse_wheel_enable为false，则不响应鼠标滚轮消息\n    if (pMsg->message == WM_MOUSEWHEEL && !m_mouse_wheel_enable)\n    {\n        //将鼠标滚轮消息发送给父窗口\n        CWnd* pParent = GetParent();\n        pParent->SendMessage(WM_MOUSEWHEEL, pMsg->wParam, pMsg->lParam);\n        return true;\n    }\n\n    return CEdit::PreTranslateMessage(pMsg);\n}\n\n\nafx_msg LRESULT CSpinEdit::OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam)\n{\n    return 0;\n}\n\n\nvoid CSpinEdit::OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult)\n{\n    //这里响应微调按钮（spin button）点击上下按钮时的事件\n    LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);\n\n    int value = GetValue();\n    value += pNMUpDown->iDelta * m_step;\n    value /= m_step;\n    value *= m_step;\n    SetValue(value);\n    pNMUpDown->iDelta = 0;\n    *pResult = 0;\n    CWnd* pParent = GetParent();\n    if (pParent != nullptr)\n        pParent->SendMessage(WM_SPIN_EDIT_POS_CHANGED, (WPARAM)this, (LPARAM)pNMUpDown);\n}\n\n\nvoid CSpinEdit::OnKillFocus(CWnd* pNewWnd)\n{\n    CEdit::OnKillFocus(pNewWnd);\n\n    // TODO: 在此处添加消息处理程序代码\n    CString str;\n    GetWindowTextW(str);\n    int value = _ttoi(str.GetString());\n    SetValue(value);    // m_spin会检查并限制值范围以及更新CEdit控件文本\n}\n\n\nvoid CSpinEdit::OnEnable(BOOL bEnable)\n{\n    CEdit::OnEnable(bEnable);\n    m_spin.EnableWindow(bEnable);\n}\n\n\nvoid CSpinEdit::OnSize(UINT nType, int cx, int cy)\n{\n    CEdit::OnSize(nType, cx, cy);\n    CRect rect;\n    GetClientRect(&rect);\n    rect.left = rect.right - m_spin_width;\n    m_spin.MoveWindow(&rect);\n}\n"
  },
  {
    "path": "TrafficMonitor/SpinEdit.h",
    "content": "﻿#pragma once\n// 这是一个带微调按钮的Edit控件，在CEdit右侧附加一个微调按钮，请预留空间\n// CSpinEdit\n\n//微调按钮点击消息。WPARAM: CSpinButtonCtrl的指针，LPARAM: LPNMUPDOWN\n#define WM_SPIN_EDIT_POS_CHANGED (WM_USER + 1010)\n\nclass CSpinEdit : public CEdit\n{\n    DECLARE_DYNAMIC(CSpinEdit)\n\npublic:\n    CSpinEdit();\n    virtual ~CSpinEdit();\n\n    void SetRange(short lower, short upper, short step = 1);        // 设置文本框中的数值范围\n    void SetValue(int value);                       //设置文本框中的数值\n    int GetValue();                                 //获取文本框中的数值\n    void SetMouseWheelEnable(bool enable);          //设置是否允许响应鼠标滚轮\n\nprotected:\n    CSpinButtonCtrl m_spin;                         //微调按钮控件\n    int m_step{ 1 };\n    int m_spin_width{};\n    bool m_mouse_wheel_enable{ true };\n\n    DECLARE_MESSAGE_MAP()\n    virtual void PreSubclassWindow();\npublic:\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\nprotected:\n    afx_msg LRESULT OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam);\npublic:\n    void OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult);\n    afx_msg void OnKillFocus(CWnd* pNewWnd);\n    afx_msg void OnEnable(BOOL bEnable);\n    afx_msg void OnSize(UINT nType, int cx, int cy);\n};\n\n\n"
  },
  {
    "path": "TrafficMonitor/StaticEx.cpp",
    "content": "#include \"stdafx.h\"\n#include \"StaticEx.h\"\n\n\nCStaticEx::CStaticEx()\n{\n}\n\n\nCStaticEx::~CStaticEx()\n{\n}\n\nvoid CStaticEx::SetWindowTextEx(LPCTSTR lpszString, Alignment align)\n{\n\tm_text = lpszString;\n\tm_align = align;\n\tm_color_text = true;\n\tInvalidate();\n}\n\nvoid CStaticEx::SetTextColor(COLORREF textColor)\n{\n\tm_text_color = textColor;\n\tInvalidate();\n}\n\nvoid CStaticEx::SetBackColor(COLORREF back_color)\n{\n\tm_back_color = back_color;\n\tm_draw_background_color = true;\n}\n\nCString CStaticEx::GetString() const\n{\n\treturn m_text;\n}\n\n\nLRESULT CStaticEx::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)\n{\n\t// TODO: ڴרô/û\n\tif (message == WM_SETTEXT)\n\t{\n\t\tCRect rect;\n\t\tCDC* pDC = GetDC();\n\t\tGetClientRect(rect);\n\t\tDrawThemeParentBackground(m_hWnd, pDC->GetSafeHdc(), &rect);\n\t\tReleaseDC(pDC);\n\t}\n\treturn CStatic::DefWindowProc(message, wParam, lParam);\n}\nBEGIN_MESSAGE_MAP(CStaticEx, CStatic)\n\tON_WM_PAINT()\nEND_MESSAGE_MAP()\n\n\n\nvoid CStaticEx::OnPaint()\n{\n\tCPaintDC dc(this); // device context for painting\n\t\t\t\t\t   // TODO: ڴ˴Ϣ\n\t\t\t\t\t   // ΪͼϢ CStatic::OnPaint()\n\tdc.SetTextColor(m_text_color);\n\tdc.SetBkMode(TRANSPARENT);\n\tdc.SelectObject(this->GetFont());\n\tCRect rect;\n\tthis->GetClientRect(&rect);\n\tif (m_draw_background_color)\n\t\tdc.FillSolidRect(rect, m_back_color);\n\telse\n\t\tDrawThemeParentBackground(m_hWnd, dc.GetSafeHdc(), &rect);\t//ػؼԽص\n\tCSize text_size = dc.GetTextExtent(m_text);\n\tUINT format{ DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX };\t\t//CDC::DrawText()ıʽ\n\tif (text_size.cx > rect.Width())\t\t//ıȳ˾Ŀȣ˾ʱ\n\t{\n\t\tif (m_align == Alignment::RIGHT)\n\t\t\tformat |= DT_RIGHT;\n\t}\n\telse\n\t{\n\t\tswitch (m_align)\n\t\t{\n\t\tcase Alignment::RIGHT: format |= DT_RIGHT; break;\n\t\tcase Alignment::CENTER: format |= DT_CENTER; break;\n\t\t}\n\t}\n\tdc.DrawText(m_text, rect, format);\n}\n\n\nvoid CStaticEx::PreSubclassWindow()\n{\n\t// TODO: ڴרô/û\n\tGetWindowText(m_text);\n\n\tCStatic::PreSubclassWindow();\n}\n"
  },
  {
    "path": "TrafficMonitor/StaticEx.h",
    "content": "/*\nCStatic࣬ɫıؼ\nSetTextColorıɫ\nҪʱSetWindowTextExÿؼı\n*/\n#pragma once\n#include \"afxwin.h\"\nclass CStaticEx :\n\tpublic CStatic\n{\npublic:\n\tCStaticEx();\n\t~CStaticEx();\n\n\t//뷽ʽ\n\tenum Alignment\n\t{\n\t\tLEFT,       //\n\t\tRIGHT,      //Ҷ\n\t\tCENTER,     //\n\t};\n\n\t//Staticؼɫıʱ\npublic:\n\tvoid SetWindowTextEx(LPCTSTR lpszString, Alignment align = Alignment::LEFT);\t//ΪؼɫıҪSetTextColorʹã\n\tvoid SetTextColor(COLORREF textColor);\t\t//ÿؼıɫ\n\tvoid SetBackColor(COLORREF back_color);\t\t//ÿؼɫ\n\tCString GetString() const;\t\t\t//ȡؼı\n\nprotected:\n\tbool m_color_text{ false };\n\tCOLORREF m_text_color;\t//ؼɫ\n\tCOLORREF m_back_color;\n\tCString m_text;\t\t\t//ؼϵı\n\tAlignment m_align{};\t\t//ıĶ뷽ʽ\n\tbool m_draw_background_color{ false };\t//ǷҪΪؼ䱳ɫ\n\nprotected:\n\tvirtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);\npublic:\n\tDECLARE_MESSAGE_MAP()\n\tafx_msg void OnPaint();\n\tvirtual void PreSubclassWindow();\n};\n\n"
  },
  {
    "path": "TrafficMonitor/StrTable.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"StrTable.h\"\n#include \"Common.h\"\n#include \"IniHelper.h\"\n#include \"TrafficMonitor.h\"\nCStrTable::CStrTable()\n{\n}\n\nCStrTable::~CStrTable()\n{\n}\n\nstatic void LanguageInfoFromIni(CStrTable::LanguageInfo& language_info, const CIniHelper& ini)\n{\n    language_info.display_name = ini.GetString(L\"general\", L\"DISPLAY_NAME\", L\"\");\n    language_info.bcp_47 = ini.GetString(L\"general\", L\"BCP_47\", L\"\");\n    language_info.default_font_name = ini.GetString(L\"general\", L\"DEFAULT_FONT\", L\"Microsoft Sans Serif\");\n    language_info.translator = ini.GetString(L\"general\", L\"TRANSLATOR\", L\"<Unknown>\");\n    language_info.translator_url = ini.GetString(L\"general\", L\"TRANSLATOR_URL\", L\"\");\n}\n\n// 回调函数，用于枚举资源语言\nstatic BOOL CALLBACK EnumResLangProc(HMODULE hModule, LPCTSTR lpType, LPCTSTR lpName, WORD wIDLanguage, LONG_PTR lParam)\n{\n    std::vector<CStrTable::LanguageInfo>* pLanguages = reinterpret_cast<std::vector<CStrTable::LanguageInfo>*>(lParam);\n\n    // 获取资源句柄\n    HRSRC hRes = FindResourceEx(hModule, lpType, lpName, wIDLanguage);\n    if (hRes != NULL)\n    {\n        // 加载资源\n        HGLOBAL hGlobal = LoadResource(hModule, hRes);\n        if (hGlobal != NULL)\n        {\n            // 锁定资源并获取数据指针\n            LPVOID pResourceData = LockResource(hGlobal);\n            if (pResourceData != NULL)\n            {\n                // 获取资源大小\n                DWORD resSize = SizeofResource(hModule, hRes);\n\n                // 将资源内容转换为字符串\n                std::string strData((const char*)pResourceData, resSize);\n                std::wstring resData = CCommon::StrToUnicode(strData.c_str(), true).c_str();\n\n                CIniHelper ini;\n                ini.FromDirectString(resData);\n                CStrTable::LanguageInfo lanugage_info;\n                LanguageInfoFromIni(lanugage_info, ini);\n                lanugage_info.language_id = wIDLanguage;\n                pLanguages->push_back(lanugage_info);\n            }\n        }\n    }\n\n    return TRUE; // 继续枚举\n}\n\n\nvoid CStrTable::Init()\n{\n    // 获取 IDR_LANGUAGE 资源的所有语言版本\n    EnumResourceLanguages(NULL, _T(\"TEXT\"), MAKEINTRESOURCE(IDR_LANGUAGE), EnumResLangProc, reinterpret_cast<LONG_PTR>(&m_language_list));\n    //按bcp47排序\n    std::sort(m_language_list.begin(), m_language_list.end(), [](const LanguageInfo& a, const LanguageInfo& b) {\n        return a.bcp_47 < b.bcp_47;\n    });\n\n    //先读取默认字符串资源，如果当前语言中没有对应字符串，则会使用默认的字符串资源\n    CIniHelper ini_default(IDR_LANGUAGE_DEFAULT);\n    ReadStringtableFronIni(ini_default);\n\n    //读取字符串资源\n    CIniHelper ini(IDR_LANGUAGE);\n    ReadStringtableFronIni(ini);\n    LanguageInfoFromIni(m_language_info, ini);\n\n    //从外部language文件夹获取语言文件\n    vector<wstring> files;\n    std::wstring language_dir;\n#ifdef _DEBUG\n    language_dir = L\".\\\\language\";\n#else\n    language_dir = theApp.m_module_dir + L\"language\";\n#endif\n    CCommon::GetFiles((language_dir + L\"\\\\*.ini\").c_str(), files);\n    for (const wstring& file_name : files)\n    {\n        std::wstring file_path{ language_dir + file_name };\n        CIniHelper ini_file(file_path, true);\n        LanguageInfo language_info;\n        LanguageInfoFromIni(language_info, ini_file);\n        language_info.language_id = LocaleNameToLCID(language_info.bcp_47.c_str(), 0);  //根据语言bcp-47代码获取语言id\n        WORD cur_language_id = GetThreadUILanguage();   //当前语言id\n        //从外部语言文件读取到当前语言，先从外部语言文件加载\n        if (language_info.language_id == cur_language_id)\n        {\n            m_language_info = language_info;\n            ReadStringtableFronIni(ini_file);\n        }\n\n        //如果语言不在m_language_list，添加到该列表\n        auto iter = std::find(m_language_list.begin(), m_language_list.end(), language_info);\n        if (iter == m_language_list.end())\n            m_language_list.push_back(language_info);\n    }\n}\n\nconst wstring& CStrTable::LoadText(const wstring& key) const\n{\n    const auto& text_string_table = GetTextStringTable();\n    return LoadText(key, text_string_table);\n}\n\nwstring CStrTable::LoadTextFormat(const wstring& key, const std::initializer_list<CVariant>& paras) const\n{\n    const auto& text_string_table = GetTextStringTable();\n    return LoadTextFormat(key, text_string_table, paras);\n}\n\nconst wstring& CStrTable::LoadMenuText(const wstring& key) const\n{\n    const auto& menu_string_table = GetMenuStringTable();\n    return LoadText(key, menu_string_table);\n}\n\nconst wstring& CStrTable::LoadText(const wstring& key, const wstring& section)\n{\n    auto iter = m_string_table.find(section);\n    if (iter != m_string_table.end())\n    {\n        return LoadText(key, iter->second);\n    }\n    static std::wstring str_empty;\n    return str_empty;\n}\n\nvoid CStrTable::ReadStringtableFronIni(const CIniHelper& ini)\n{\n    std::set<std::wstring> sections{ L\"general\", L\"text\", L\"menu\" };\n    auto section_list = ini.GetAllAppName(L\"\");\n    for (const auto& section : section_list)\n        sections.insert(section);\n\n    for (const auto& section : sections)\n    {\n        auto& value_map = m_string_table[section];\n        ini.GetAllKeyValues(section, value_map);\n    }\n}\n\nconst std::map<std::wstring, std::wstring>& CStrTable::GetTextStringTable() const\n{\n    auto iter = m_string_table.find(L\"text\");\n    if (iter != m_string_table.end())\n        return iter->second;\n    static std::map<std::wstring, std::wstring> empty_map;\n    return empty_map;\n}\n\nconst std::map<std::wstring, std::wstring>& CStrTable::GetMenuStringTable() const\n{\n    auto iter = m_string_table.find(L\"menu\");\n    if (iter != m_string_table.end())\n        return iter->second;\n    static std::map<std::wstring, std::wstring> empty_map;\n    return empty_map;\n}\n\nconst wstring& CStrTable::LoadText(const wstring& key, const std::map<std::wstring, std::wstring>& string_table)\n{\n    auto iter = string_table.find(key);\n    if (iter != string_table.end())\n        return iter->second;\n    ASSERT(false);\n    static std::wstring str_empty;\n    return str_empty;\n}\n\nwstring CStrTable::LoadTextFormat(const wstring& key, const std::map<std::wstring, std::wstring>& string_table, const std::initializer_list<CVariant>& paras)\n{\n    auto iter = string_table.find(key);\n    if (iter == string_table.end())\n    {\n        ASSERT(false);\n        return std::wstring();\n    }\n    wstring str{ iter->second };    // 复制以避免原始字符串修改\n    int index{ 1 };\n    for (const auto& para : paras)\n    {\n        wstring format_str{ L\"<%\" + std::to_wstring(index) + L\"%>\" };\n        CCommon::StringReplace(str, format_str, para.ToString().GetString());\n        ++index;\n    }\n    return str;\n}\n"
  },
  {
    "path": "TrafficMonitor/StrTable.h",
    "content": "﻿#pragma once\n#include \"CVariant.h\"\n#include <map>\nclass CIniHelper;\n\nclass CStrTable\n{\npublic:\n    CStrTable();\n    ~CStrTable();\n\n    struct LanguageInfo\n    {\n        wstring display_name;           // 在语言设置下拉菜单显示的字符串\n        wstring bcp_47;                 // BCP-47代码\n        wstring default_font_name;      // 默认字体\n        wstring translator;\n        wstring translator_url;\n        WORD language_id{};\n\n        bool operator==(const LanguageInfo& another) const\n        {\n            return bcp_47 == another.bcp_47;\n        }\n    };\n\n    void Init();\n\n    // 载入翻译字符串\n    const wstring& LoadText(const wstring& key) const;\n    // 载入翻译字符串，并将字符串中形如<%序号%>的字符串替换成可变参数列表中的参数\n    wstring LoadTextFormat(const wstring& key, const std::initializer_list<CVariant>& paras) const;\n\n    const wstring& LoadMenuText(const wstring& key) const;\n\n    const wstring& LoadText(const wstring& key, const wstring& section);\n\n    // 获取默认字体名称\n    const LanguageInfo& GetLanguageInfo() const { return m_language_info; }\n\n    // 获取所有支持语言\n    const std::vector<LanguageInfo>& GetLanguageList() const { return m_language_list; }\n\n    // 当前语言是否为简体中文（选择默认更新源以及更新信息语言）\n    bool IsSimplifiedChinese() const { return  m_language_info.bcp_47 == L\"zh-CN\"; };\n\nprotected:\n    void ReadStringtableFronIni(const CIniHelper& ini);\n    const std::map<std::wstring, std::wstring>& GetTextStringTable() const;\n    const std::map<std::wstring, std::wstring>& GetMenuStringTable() const;\n\n    static const wstring& LoadText(const wstring& key, const std::map<std::wstring, std::wstring>& string_table);\n    static wstring LoadTextFormat(const wstring& key, const std::map<std::wstring, std::wstring>& string_table, const std::initializer_list<CVariant>& paras);\n\n\nprivate:\n    std::map<std::wstring, std::map<std::wstring, std::wstring>> m_string_table;    //保存ini文件每个section的键值对\n    LanguageInfo m_language_info;                   //当前语言\n    std::vector<LanguageInfo> m_language_list;      //所有支持的语言\n};\n\n"
  },
  {
    "path": "TrafficMonitor/SupportedRenderEnums.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"SupportedRenderEnums.h\"\n#include \"TaskBarDlgDrawCommon.h\"\n\nCSupportedRenderEnums::CSupportedRenderEnums()\n{\n    if (CDCompositionSupport::CheckSupport() && CDxgi1Support2::CheckSupport())\n    {\n        m_enums[D2D1_WITH_DCOMPOSITION_INDEX] = true;\n    }\n    if (CTaskBarDlgDrawCommonSupport::CheckSupport())\n    {\n        m_enums[D2D1_INDEX] = true;\n    }\n}\n\nvoid CSupportedRenderEnums::EnableDefaultOnly() noexcept\n{\n    m_enums = decltype(m_enums){1};\n}\n\nvoid CSupportedRenderEnums::DisableD2D1() noexcept\n{\n    m_enums[D2D1_INDEX] = false;\n}\n\nauto CSupportedRenderEnums::GetAutoFitEnum() const noexcept\n    -> DrawCommonHelper::RenderType\n{\n    std::size_t i;\n    for (i = m_enums.size() - 1; i > 0; --i)\n    {\n        if (m_enums[i])\n        {\n            break;\n        }\n    }\n    switch (i)\n    {\n    case D2D1_INDEX:\n        return DrawCommonHelper::RenderType::D2D1;\n    case D2D1_WITH_DCOMPOSITION_INDEX:\n        return DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION;\n    case DEFAULT_INDEX:\n        return DrawCommonHelper::RenderType::DEFAULT;\n    default:\n        return DrawCommonHelper::RenderType::DEFAULT;\n    }\n}\n\nauto CSupportedRenderEnums::GetMaxSupportedRenderEnum() const noexcept\n    -> DrawCommonHelper::RenderType\n{\n    if (m_enums[D2D1_WITH_DCOMPOSITION_INDEX])\n    {\n        return DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION;\n    }\n    else if (m_enums[D2D1_INDEX])\n    {\n        return DrawCommonHelper::RenderType::D2D1;\n    }\n    else if (m_enums[DEFAULT_INDEX])\n    {\n        return DrawCommonHelper::RenderType::DEFAULT;\n    }\n    return DrawCommonHelper::RenderType::DEFAULT;\n}\n\nbool CSupportedRenderEnums::IsD2D1WithDCompositionEnabled() const noexcept\n{\n    return m_enums[D2D1_WITH_DCOMPOSITION_INDEX];\n}\n\nbool CSupportedRenderEnums::IsD2D1Enabled() const noexcept\n{\n    return m_enums[D2D1_INDEX];\n}"
  },
  {
    "path": "TrafficMonitor/SupportedRenderEnums.h",
    "content": "﻿#pragma once\n#include <bitset>\n#include \"IDrawCommon.h\"\n\nclass CSupportedRenderEnums\n{\nprivate:\n    std::bitset<3> m_enums{1};\n\npublic:\n    constexpr static std::size_t DEFAULT_INDEX = 0;\n    constexpr static std::size_t D2D1_WITH_DCOMPOSITION_INDEX = 1;\n    constexpr static std::size_t D2D1_INDEX = 2;\n\n    CSupportedRenderEnums();\n    ~CSupportedRenderEnums() = default;\n    void EnableDefaultOnly() noexcept;\n    void DisableD2D1() noexcept;\n    /**\n     * @brief 根据D2D1 > D2D1_WITH_DCOMPOSITION > DEFAULT的顺序返回枚举\n     *\n     * @return DrawCommonHelper::RenderType\n     */\n    auto GetAutoFitEnum() const noexcept\n        -> DrawCommonHelper::RenderType;\n    /**\n     * @brief （已弃用）\n        根据D2D1_WITH_DCOMPOSITION > D2D1 > DEFAULT的顺序返回枚举\n     *\n     * @return DrawCommonHelper::RenderType\n     */\n    [[deprecated(\"May no longer be needed.\")]]\n    auto GetMaxSupportedRenderEnum() const noexcept\n        -> DrawCommonHelper::RenderType;\n    bool IsD2D1WithDCompositionEnabled() const noexcept;\n    bool IsD2D1Enabled() const noexcept;\n};\n"
  },
  {
    "path": "TrafficMonitor/TabDlg.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"TabDlg.h\"\n#include \"TrafficMonitor.h\"\n\nIMPLEMENT_DYNAMIC(CTabDlg, CBaseDialog)\n\nCTabDlg::CTabDlg(UINT nIDTemplate, CWnd * pParent) : CBaseDialog(nIDTemplate, pParent)\n{\n    m_pParent = pParent;\n}\n\n\nCTabDlg::~CTabDlg()\n{\n}\n\n\nBOOL CTabDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //由于这是tab标签中的子对话框，因此用户按回车或ESC后不应该响应当前对话框的IDOK或IDCANCEL，\n    //而应该响应tab标签的父窗口的IDOK或IDCANCEL命令\n    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)\n    {\n        if (m_pParent != nullptr)\n            m_pParent->SendMessage(WM_COMMAND, IDCANCEL);\n        return TRUE;\n    }\n    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)\n    {\n        if (m_pParent != nullptr)\n            m_pParent->SendMessage(WM_COMMAND, IDOK);\n        return TRUE;\n    }\n\n    return CBaseDialog::PreTranslateMessage(pMsg);\n}\n\n\nBOOL CTabDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    //将窗口背景设置成白色\n    if (theApp.m_win_version.IsWindows11OrLater())\n        SetBackgroundColor(RGB(249, 249, 249));\n    else\n        SetBackgroundColor(RGB(255, 255, 255));\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\nCWnd* CTabDlg::GetParentWindow()\n{\n    CWnd* pParent = GetParent();\n    if (pParent != nullptr)\n    {\n        return pParent->GetParent();\n    }\n    return nullptr;\n}\n\nvoid CTabDlg::SetScrollbarInfo(int nPage, int nMax)\n{\n    // 获取滚动条状态\n    SCROLLINFO scrollinfo;\n    GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);\n    if (m_scroll_enable)\n        m_last_pos = scrollinfo.nPos - scrollinfo.nMin;     // 如果已启用滚动则记录当前滚动位置\n    else\n        m_scroll_enable = true;                             // 否则启用滚动\n    int reset_pos = m_last_pos;\n    // 父窗口OnSize后的新滚动状态边界检查\n    if (nMax < 0) nMax = 0;\n    if (m_last_pos > nMax - nPage) m_last_pos = nMax - nPage;\n    if (m_last_pos < 0) m_last_pos = 0;\n    // 设置滚动条状态\n    scrollinfo.nMin = 0;                // 设置滚动内容起点在窗口中的pos\n    scrollinfo.nMax = nMax;             // 设置滚动内容终点在窗口中的pos\n    scrollinfo.nPage = nPage;           // 设置实际显示内容区域高度\n    scrollinfo.nPos = m_last_pos;       // 设置当前实际显示内容区域顶端pos\n    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);\n    // 复位滚动\n    if (reset_pos != 0)\n        ScrollWindow(0, reset_pos);\n    // 代替框架做出OnSize的响应 (在SetScrollInfo决定并设置滚动条是否在新状态下显示之后)\n    CBaseDialog::ResizeDynamicLayout(); // 这个方法会无视滚动更新控件位置导致控件错位，在滚动为0时调用避开这个问题\n    // 执行滚动\n    if (m_last_pos != 0)\n        ScrollWindow(0, -m_last_pos);\n}\n\nvoid CTabDlg::ScrollWindowSimple(int step, bool absolute)\n{\n    SCROLLINFO scrollinfo;\n    GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);\n    if (step == INT_MAX)\n        step = scrollinfo.nPage;\n    if (step == INT_MIN)\n        step = -static_cast<int>(scrollinfo.nPage);\n    int offset_diff = scrollinfo.nMax - static_cast<int>(scrollinfo.nPage);\n    if (offset_diff < 0)    //nMax应该总是大于或等于nPage，当nMax等于nPage时没有滚动条\n        offset_diff = 0;\n    if (!absolute)\n        scrollinfo.nPos -= step;\n    else\n    {\n        if (step < 0)               // 绝对位置时step为-1表示滚动到底部\n            step = offset_diff;\n        scrollinfo.nPos = step;     // 此时的stpe为目标绝对位置\n        step = m_last_pos - step;   // 将参数的绝对位置转换为偏移量继续处理\n    }\n    if (scrollinfo.nPos < scrollinfo.nMin)                                          // 限制nPos不小于最小值nMin\n    {\n        step -= scrollinfo.nMin - scrollinfo.nPos;\n        scrollinfo.nPos = scrollinfo.nMin;\n    }\n    if (scrollinfo.nPos > offset_diff)     // 限制nPos不大于最大值nMax - nPage\n    {\n        step += scrollinfo.nPos - offset_diff;\n        scrollinfo.nPos = offset_diff;\n    }\n    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);\n    m_last_pos = scrollinfo.nPos;\n    ScrollWindow(0, step);\n}\n\nvoid CTabDlg::EnableDlgCtrl(UINT id, bool enable)\n{\n    CWnd* pCtrl = GetDlgItem(id);\n    if (pCtrl != nullptr)\n        pCtrl->EnableWindow(enable);\n}\n\nvoid CTabDlg::ShowDlgCtrl(UINT id, bool show)\n{\n    CWnd* pCtrl = GetDlgItem(id);\n    if (pCtrl != nullptr)\n        pCtrl->ShowWindow(show);\n}\n\nBEGIN_MESSAGE_MAP(CTabDlg, CBaseDialog)\n    ON_WM_VSCROLL()\n    ON_WM_MOUSEWHEEL()\n    ON_WM_SIZE()\nEND_MESSAGE_MAP()\n\n\nvoid CTabDlg::ResizeDynamicLayout()\n{\n    // m_pDynamicLayout->Adjust()会无视窗口滚动更新控件位置\n    // 之前在父窗口OnSize后重置不可靠（进入退出最大化和贴靠时没能正常工作），也没找到检出这两种特殊OnSize的方法\n    // 框架内部调用ResizeDynamicLayout太早，来不及先复位滚动，故覆写此虚方法介入\n\n    // 如果已启用滚动那么此处不调用基类使框架的处理无效，改为在父窗口的OnSize后自行调用\n    if (!m_scroll_enable)\n        CBaseDialog::ResizeDynamicLayout();\n}\n\nvoid CTabDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    //参考资料：https://www.cnblogs.com/ranjiewen/p/6013922.html\n\n    if (m_scroll_enable)\n    {\n        int step = theApp.DPI(16);\n        switch (nSBCode)\n        {\n        case SB_LINEUP:                         //Scroll one line up\n            ScrollWindowSimple(step);\n            break;\n        case SB_LINEDOWN:                       //Scroll one line down\n            ScrollWindowSimple(-step);\n            break;\n        case SB_PAGEUP:                         //Scroll one page up.\n            ScrollWindowSimple(INT_MAX);\n            break;\n        case SB_PAGEDOWN:                       //Scroll one page down\n            ScrollWindowSimple(INT_MIN);\n            break;\n        case SB_THUMBPOSITION:                  //Scroll to the absolute position. The current position is provided in nPos\n            break;\n        case SB_THUMBTRACK:                     //Drag scroll box to specified position. The current position is provided in nPos\n            ScrollWindowSimple(nPos, true);\n            break;\n        case SB_TOP:                            // 顶部\n            ScrollWindowSimple(0, true);\n            break;\n        case SB_BOTTOM:                         // 底部\n            ScrollWindowSimple(-1, true);\n            break;\n        case SB_ENDSCROLL:                      //End scroll\n            break;\n        default:\n            break;\n        }\n    }\n    CBaseDialog::OnVScroll(nSBCode, nPos, pScrollBar);\n}\n\n\nBOOL CTabDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    if (m_scroll_enable)\n    {\n        int step = theApp.DPI(64) * zDelta / 120;\n        ScrollWindowSimple(step);\n        SCROLLINFO scrollinfo;\n        GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);\n        m_last_pos = scrollinfo.nPos;\n    }\n\n    return CBaseDialog::OnMouseWheel(nFlags, zDelta, pt);\n}\n\n\nvoid CTabDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n\n    CBaseDialog::OnOK();\n}\n\n\nbool CTabDlg::IsScrollBarVisible()\n{\n    SCROLLINFO scrollinfo;\n    GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);\n    bool visible = scrollinfo.nPage < scrollinfo.nMax;\n    return visible;\n}\n\nvoid CTabDlg::OnSize(UINT nType, int cx, int cy)\n{\n    CBaseDialog::OnSize(nType, cx, cy);\n\n    // TODO: 在此处添加消息处理程序代码\n    SetControlMouseWheelEnable(!IsScrollBarVisible());      //如果显示了滚动条，则禁止控件响应鼠标滚轮，此时鼠标滚轮用于滚动窗口\n}\n"
  },
  {
    "path": "TrafficMonitor/TabDlg.h",
    "content": "﻿//这是用于Tab标签中的子对话框类\n#pragma once\n#include \"BaseDialog.h\"\n\nclass CTabDlg : public CBaseDialog\n{\n    DECLARE_DYNAMIC(CTabDlg)\npublic:\n    CTabDlg(UINT nIDTemplate, CWnd *pParent = NULL);\n    ~CTabDlg();\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    virtual BOOL OnInitDialog();\n    CWnd* GetParentWindow();\n    void SetScrollbarInfo(int nPage, int nMax);\n    virtual void OnTabEntered() {}      //当标签切换到当前窗口时被调用\n    virtual void OnOK();\n    void SetScrollEnable(bool enable) { m_scroll_enable = enable; }\n    virtual void SetControlMouseWheelEnable(bool enable) {}     //在派生类中重写此函数以设置控件是否允许响应鼠标滚轮\n    virtual void OnSettingsApplied() {}   //点击了“应用”按钮，应用完设置之后被调用\n\n    bool IsScrollBarVisible();    //滚动条是否可见\n\nprivate:\n    void ScrollWindowSimple(int step, bool absolute = false);\n\nprotected:\n    void EnableDlgCtrl(UINT id, bool enable);\n    void ShowDlgCtrl(UINT id, bool show);\n\nprotected:\n    CWnd* m_pParent;\n    bool m_scroll_enable{ false };\n    int m_last_pos{};\n\nprotected:\n    // CWnd的虚方法，声明在afxwin.h，实现在wincore.cpp，在WM_SIZE消息处理时被CWnd调用\n    // 内部在一些判断之后使用CWnd持有的CMFCDynamicLayout指针执行m_pDynamicLayout->Adjust()\n    virtual void ResizeDynamicLayout() override final;  // 这里重写是为了改变调用时机，从默认的窗口OnSize之前改为父窗口OnSize之后\n\npublic:\n    DECLARE_MESSAGE_MAP()\n    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);\n    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);\n    afx_msg void OnSize(UINT nType, int cx, int cy);\n};\n\n"
  },
  {
    "path": "TrafficMonitor/TaskBarDlg.cpp",
    "content": "﻿// TaskBarDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"TaskBarDlg.h\"\n#include \"afxdialogex.h\"\n#include \"TrafficMonitorDlg.h\"\n#include \"WindowsSettingHelper.h\"\n#include \"WIC.h\"\n#include \"Nullable.hpp\"\n#include \"DrawCommonFactory.h\"\n#include \"WindowsWebExperienceDetector.h\"\n#include \"TaskbarHelper.h\"\n\n#ifdef DEBUG\n// DX调试信息捕获\n#include \"dxgi1_3.h\"\n#include \"DXProgrammableCapture.h\"\n#endif\n\n// CTaskBarDlg 对话框\n\nIMPLEMENT_DYNAMIC(CTaskBarDlg, CDialogEx)\n\nCTaskBarDlg::CTaskBarDlg(CWnd* pParent /*=NULL*/)\n    : CDialogEx(IDD_TASK_BAR_DIALOG, pParent)\n{\n}\n\nCTaskBarDlg::~CTaskBarDlg()\n{\n    for (auto iter = m_map_history_data.begin(); iter != m_map_history_data.end(); ++iter)\n    {\n        iter->second.clear();\n    }\n}\n\nvoid CTaskBarDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CDialogEx::DoDataExchange(pDX);\n}\n\nBEGIN_MESSAGE_MAP(CTaskBarDlg, CDialogEx)\n    ON_WM_RBUTTONUP()\n    ON_WM_INITMENU()\n    ON_WM_MOUSEMOVE()\n    ON_WM_LBUTTONDBLCLK()\n    ON_WM_TIMER()\n    ON_WM_PAINT()\n    ON_WM_CLOSE()\n    ON_WM_LBUTTONUP()\n    ON_MESSAGE(WM_EXITMENULOOP, &CTaskBarDlg::OnExitmenuloop)\n    ON_MESSAGE(WM_TABLET_QUERYSYSTEMGESTURESTATUS, &CTaskBarDlg::OnTabletQuerysystemgesturestatus)\n    ON_WM_MOUSEWHEEL()\nEND_MESSAGE_MAP()\n\n// CTaskBarDlg 消息处理程序\n\nvoid CTaskBarDlg::ShowInfo(CDC* pDC)\n{\n    m_item_rects.clear();   //绘图前先清除所有项目的矩形区域\n    HWND current_hwnd = this->GetSafeHwnd();\n    if (current_hwnd == NULL || !IsWindow(this->GetSafeHwnd()))\n        return;\n    if (m_rect.IsRectEmpty() || m_rect.IsRectNull())\n        return;\n    if (m_supported_render_enums.IsD2D1Enabled())\n    {\n        auto last_update_layered_window_error =\n            theApp.m_taskbar_data.update_layered_window_error_code;\n        if (last_update_layered_window_error)\n        {\n            m_supported_render_enums.DisableD2D1();\n            if (!m_supported_render_enums.IsD2D1WithDCompositionEnabled())\n            {\n                m_supported_render_enums.EnableDefaultOnly();\n                LogWin32ApiErrorMessage(last_update_layered_window_error);\n                CString error_info{};\n                error_info.Format(\n                    _T(\"Call UpdateLayeredWindowIndirect failed. Use GDI render instead. Error code = %ld.\"),\n                    last_update_layered_window_error);\n                CCommon::WriteLog(error_info, theApp.m_log_path.c_str());\n                // 禁用D2D\n                theApp.m_taskbar_data.disable_d2d = true;\n                // 展示错误信息\n                ::MessageBox(NULL, CCommon::LoadText(IDS_UPDATE_TASKBARDLG_FAILED_TIP), NULL, MB_OK | MB_ICONWARNING);\n            }\n        }\n    }\n    auto render_type = m_supported_render_enums.GetAutoFitEnum();\n    CRect draw_rect{m_rect}; // 绘图的矩形区域\n    draw_rect.MoveToXY(0, 0);\n\n#ifdef DEBUG\n    Microsoft::WRL::ComPtr<IDXGraphicsAnalysis> p_dxgi_analysis{};\n#endif\n    // 初始化DrawBuffer和DrawCommon栈内存\n    AllInvolvedDrawCommonObjectsStorage all_involved_draw_common_objects{};\n    IDrawCommon* draw_common_interface{nullptr};\n    std::tie(std::ignore, draw_common_interface) =\n        GetInterfaceFromAllInvolvedDrawCommonObjects(\n            all_involved_draw_common_objects,\n            render_type,\n            {{DrawCommonHelper::RenderType::DEFAULT,\n              [&](IDrawBuffer* p_draw_buffer_interface, IDrawCommon* p_draw_common_interface)\n              {\n                  auto p_draw_buffer = static_cast<CDrawDoubleBuffer*>(p_draw_buffer_interface);\n                  auto p_draw_common = static_cast<CDrawCommon*>(p_draw_common_interface);\n\n                  // 必须先于绘图对象构造\n                  EmplaceAt(p_draw_buffer, pDC, draw_rect);\n                  // 这里构造绘图对象\n                  EmplaceAt(p_draw_common);\n                  p_draw_common->Create(p_draw_buffer->GetMemDC(), nullptr);\n                  p_draw_common->FillRect(draw_rect, theApp.m_taskbar_data.back_color); // 填充背景色\n                  p_draw_common->SetFont(&m_font);\n                  p_draw_common->SetBackColor(theApp.m_taskbar_data.back_color);\n              }},\n             {DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION,\n              [&](IDrawBuffer* p_draw_buffer_interface, IDrawCommon* p_draw_common_interface)\n              {\n                  auto p_draw_buffer = static_cast<CTaskBarDlgDrawBufferUseDComposition*>(p_draw_buffer_interface);\n                  auto p_draw_common = static_cast<CTaskBarDlgDrawCommon*>(p_draw_common_interface);\n\n                  auto& ref_d2d1_app_support = theApp.m_d2d_taskbar_draw_common_support.Get();\n                  m_d2d1_device_context_support.Get().SetWorkingDevice(\n                      ref_d2d1_app_support.GetDCompositionDevice(),\n                      ref_d2d1_app_support.GetD3D10Device1(),\n                      m_hWnd);\n                  // 这里与上面相反，是先构造DrawCommon再构造Buffer\n                  // 这里构造绘图对象\n                  EmplaceAt(p_draw_common);\n                  D2D1_SIZE_U d2d_size;\n                  d2d_size.width = draw_rect.Width();\n                  d2d_size.height = draw_rect.Height();\n                  p_draw_common->Create(\n                      this->m_taskbar_draw_common_window_support.Get(),\n                      this->m_d2d1_device_context_support.Get(),\n                      d2d_size);\n                  // 仅透明时，且UpdateLayeredWindowIndirect失败时，启用此渲染器，默认初始化为全黑，alpha=1\n                  p_draw_common->FillRect(draw_rect, 0x00000000, 1);\n                  p_draw_common->SetFont(&m_font);\n                  p_draw_common->SetBackColor(theApp.m_taskbar_data.back_color);\n                  // 构造buffer\n                  EmplaceAt(p_draw_buffer, this->m_d2d1_device_context_support.Get());\n              }},\n             {DrawCommonHelper::RenderType::D2D1,\n              [&](IDrawBuffer* p_draw_buffer_interface, IDrawCommon* p_draw_common_interface)\n              {\n                  auto p_draw_buffer = static_cast<CTaskBarDlgDrawBuffer*>(p_draw_buffer_interface);\n                  auto p_draw_common = static_cast<CTaskBarDlgDrawCommon*>(p_draw_common_interface);\n\n                  auto& ref_d2d1_app_support = theApp.m_d2d_taskbar_draw_common_support.Get();\n                  m_d2d1_device_context_support.Get().SetWorkingDevice(ref_d2d1_app_support.GetD3D10Device1());\n                  // 这里与上面相反，是先构造DrawCommon再构造Buffer\n                  // 这里构造绘图对象\n                  EmplaceAt(p_draw_common);\n                  D2D1_SIZE_U d2d_size;\n                  d2d_size.width = draw_rect.Width();\n                  d2d_size.height = draw_rect.Height();\n                  p_draw_common->Create(\n                      this->m_taskbar_draw_common_window_support.Get(),\n                      this->m_d2d1_device_context_support.Get(),\n                      d2d_size);\n                  // 仅透明时启用此渲染器，默认初始化为全黑，alpha=1\n                  p_draw_common->FillRect(draw_rect, 0x00000000, 1);\n                  p_draw_common->SetFont(&m_font);\n                  p_draw_common->SetBackColor(theApp.m_taskbar_data.back_color);\n                  // 构造buffer\n                  CSize draw_size{draw_rect.Width(), draw_rect.Height()};\n                  EmplaceAt(p_draw_buffer,\n                            this->m_taskbar_draw_common_window_support.Get(),\n                            this->m_d2d1_device_context_support.Get(),\n                            draw_size,\n                            current_hwnd);\n\n#ifdef DEBUG\n                  DXGIGetDebugInterface1(0, IID_PPV_ARGS(&p_dxgi_analysis));\n                  if (p_dxgi_analysis)\n                  {\n                      p_dxgi_analysis->BeginCapture();\n                  }\n#endif\n              }}});\n    IDrawCommon& draw = *draw_common_interface;\n    // 计算各部分的位置\n    int index = 0;\n    CRect item_rect{};\n    int item_count = static_cast<int>(m_item_widths.size()); //要显示的项目数量\n    auto last_iter = m_item_widths.begin();\n    for (auto iter = m_item_widths.begin(); iter != m_item_widths.end(); ++iter)\n    {\n        auto last_item_width = last_iter->item_width;\n        //任务栏在桌面顶部或底部\n        if (IsTasksbarOnTopOrBottom())\n        {\n            if (theApp.m_taskbar_data.horizontal_arrange) //水平排列\n            {\n                if (index > 0)\n                    item_rect.MoveToX(item_rect.right + DPI(theApp.m_taskbar_data.item_space));\n                item_rect.right = item_rect.left + iter->item_width.TotalWidth();\n                item_rect.bottom = item_rect.top + m_window_height;\n                if (iter->IsPlugin())\n                    DrawPluginItem(draw, iter->PluginItem(), item_rect, iter->item_width.label_width);\n                else\n                    DrawDisplayItem(draw, iter->ItemType(), item_rect, iter->item_width.label_width);\n            }\n            else //非水平排列时，每两个一组显示\n            {\n                //在index为奇数时同时绘制两个项目\n                if (index % 2 == 1)\n                {\n                    CRect item_rect_up;     //上面一个项目的矩形区域\n                    if (index > 0)\n                        item_rect_up.MoveToXY(item_rect.right + DPI(theApp.m_taskbar_data.item_space), -DPI(theApp.m_taskbar_data.vertical_margin));\n                    item_rect.left = item_rect_up.left;\n                    item_rect.top = (m_window_height - TASKBAR_WND_HEIGHT / 2);\n                    //确定窗口大小\n                    item_rect_up.bottom = item_rect.top - 1;\n                    item_rect.bottom = m_window_height + DPI(theApp.m_taskbar_data.vertical_margin);\n                    int width = max(iter->item_width.TotalWidth(), last_item_width.TotalWidth());\n                    item_rect.right = item_rect.left + width;\n                    item_rect_up.right = item_rect_up.left + width;\n                    //绘制信息\n                    if (last_iter->IsPlugin())\n                        DrawPluginItem(draw, last_iter->PluginItem(), item_rect_up, last_item_width.label_width);\n                    else\n                        DrawDisplayItem(draw, last_iter->ItemType(), item_rect_up, last_item_width.label_width);\n                    if (iter->IsPlugin())\n                        DrawPluginItem(draw, iter->PluginItem(), item_rect, iter->item_width.label_width);\n                    else\n                        DrawDisplayItem(draw, iter->ItemType(), item_rect, iter->item_width.label_width);\n                }\n                //要绘制的项目为奇数时绘制最后一个\n                else if (item_count % 2 == 1 && index == item_count - 1)\n                {\n                    item_rect.MoveToXY(item_rect.right + DPI(theApp.m_taskbar_data.item_space), 0);\n                    item_rect.bottom = TASKBAR_WND_HEIGHT;\n                    item_rect.right = item_rect.left + iter->item_width.MaxWidth();\n                    if (iter->IsPlugin())\n                        DrawPluginItem(draw, iter->PluginItem(), item_rect, iter->item_width.label_width, true);\n                    else\n                        DrawDisplayItem(draw, iter->ItemType(), item_rect, iter->item_width.label_width, true);\n                }\n            }\n        }\n        //任务栏在桌面两侧\n        else\n        {\n            if (index > 0)\n                item_rect.MoveToXY(0, item_rect.bottom + DPI(theApp.m_taskbar_data.item_space));\n            item_rect.bottom = item_rect.top + TASKBAR_WND_HEIGHT / 2;\n            item_rect.right = item_rect.left + min(m_window_width, m_rcTaskbar.Width() - DPI(theApp.m_taskbar_data.item_space));\n            if (iter->IsPlugin())\n                DrawPluginItem(draw, iter->PluginItem(), item_rect, iter->item_width.label_width);\n            else\n                DrawDisplayItem(draw, iter->ItemType(), item_rect, iter->item_width.label_width);\n        }\n        index++;\n        last_iter = iter;\n    }\n\n#ifdef DEBUG\n    if (p_dxgi_analysis)\n    {\n        p_dxgi_analysis->EndCapture();\n    }\n#endif\n}\n\nvoid CTaskBarDlg::DrawDisplayItem(IDrawCommon& drawer, DisplayItem type, CRect rect, int label_width, bool vertical)\n{\n    m_item_rects[type] = rect;\n    //设置要绘制的文本颜色\n    COLORREF label_color{};\n    COLORREF text_color{};\n    if (theApp.m_taskbar_data.specify_each_item_color)\n    {\n        label_color = theApp.m_taskbar_data.text_colors[type].label;\n        text_color = theApp.m_taskbar_data.text_colors[type].value;\n    }\n    else if (!theApp.m_taskbar_data.text_colors.empty())\n    {\n        label_color = theApp.m_taskbar_data.text_colors.begin()->second.label;\n        text_color = theApp.m_taskbar_data.text_colors.begin()->second.label;\n    }\n\n    //设置标签和数值的矩形区域\n    CRect rect_label{ rect };\n    CRect rect_value{ rect };\n    if (!vertical)\n    {\n        rect_label.right = rect_label.left + label_width;\n        rect_value.left = rect_label.right;\n    }\n    else if (label_width != 0)\n    {\n        rect_label.bottom = rect_label.top + (rect_label.Height() / 2);\n        rect_value.top = rect_label.bottom;\n    }\n\n    // 绘制状态条\n    if (type == TDI_CPU || type == TDI_MEMORY || type == TDI_GPU_USAGE || type == TDI_CPU_TEMP\n        || type == TDI_GPU_TEMP || type == TDI_HDD_TEMP || type == TDI_MAIN_BOARD_TEMP || type == TDI_HDD_USAGE\n        || type == TDI_UP || type == TDI_DOWN || type == TDI_TOTAL_SPEED/* ||type==TDI_CPU_FREQ*/)\n    {\n        int figure_value{};\n        switch (type)\n        {\n        case TDI_CPU:\n            figure_value = theApp.m_cpu_usage;\n            break;\n        case TDI_MEMORY:\n            figure_value = theApp.m_memory_usage;\n            break;\n        case TDI_GPU_USAGE:\n            figure_value = theApp.m_gpu_usage;\n            break;\n        case TDI_CPU_TEMP:\n            figure_value = theApp.m_cpu_temperature;\n            break;\n        case TDI_GPU_TEMP:\n            figure_value = theApp.m_gpu_temperature;\n            break;\n        case TDI_HDD_TEMP:\n            figure_value = theApp.m_hdd_temperature;\n            break;\n        case TDI_MAIN_BOARD_TEMP:\n            figure_value = theApp.m_main_board_temperature;\n            break;\n        case TDI_HDD_USAGE:\n            figure_value = theApp.m_hdd_usage;\n            break;\n        //case TDI_CPU_FREQ:\n        //    figure_value = theApp.m_cpu_freq;\n        //    break;\n        case TDI_UP:\n            figure_value = CalculateNetspeedPercent(theApp.m_out_speed);\n            break;\n        case TDI_DOWN:\n            figure_value = CalculateNetspeedPercent(theApp.m_in_speed);\n            break;\n        case TDI_TOTAL_SPEED:\n            figure_value = CalculateNetspeedPercent(theApp.m_in_speed + theApp.m_out_speed);\n            break;\n        default:\n            break;\n        }\n\n        if ((type != TDI_UP && type != TDI_DOWN && type != TDI_TOTAL_SPEED) && theApp.m_taskbar_data.show_status_bar\n            || (type == TDI_UP || type == TDI_DOWN || type == TDI_TOTAL_SPEED) && theApp.m_taskbar_data.show_netspeed_figure)\n        {\n            if (theApp.m_taskbar_data.cm_graph_type)\n            {\n                AddHisToList(type, figure_value);\n                TryDrawGraph(drawer, rect, type);\n            }\n            else\n            {\n                TryDrawStatusBar(drawer, rect, figure_value);\n            }\n        }\n    }\n\n    //绘制标签\n    if (label_width > 0)\n    {\n        wstring str_label = theApp.m_taskbar_data.disp_str.GetConst(type);\n        drawer.DrawWindowText(rect_label, str_label.c_str(), label_color, (vertical ? IDrawCommon::Alignment::CENTER : IDrawCommon::Alignment::LEFT));\n    }\n\n    //绘制数值\n    IDrawCommon::Alignment value_alignment{ theApp.m_taskbar_data.value_right_align ? IDrawCommon::Alignment::RIGHT : IDrawCommon::Alignment::LEFT };      //数值的对齐方式\n    if (vertical)\n        value_alignment = IDrawCommon::Alignment::CENTER;\n    CString str_value = CommonDisplayItem(type).GetItemValueText(false);\n    drawer.DrawWindowText(rect_value, str_value, text_color, value_alignment);\n}\n\nvoid CTaskBarDlg::DrawPluginItem(IDrawCommon& drawer, IPluginItem* item, CRect rect, int label_width, bool vertical)\n{\n    if (item == nullptr)\n        return;\n    m_item_rects[item] = rect;\n\n    //绘制资源占用图\n    ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(item);\n    if (theApp.m_taskbar_data.show_status_bar && plugin != nullptr && plugin->GetAPIVersion() >= 6)\n    {\n        if (item->IsDrawResourceUsageGraph())\n        {\n             int figure_value = item->GetResourceUsageGraphValue() * 100;\n            //横向滚动图\n            if (theApp.m_taskbar_data.cm_graph_type)\n            {\n                AddHisToList(item, figure_value);\n                TryDrawGraph(drawer, rect, item);\n            }\n            //柱状图\n            else\n            {\n                TryDrawStatusBar(drawer, rect, figure_value);\n            }\n        }\n    }\n\n    //设置要绘制的文本颜色\n    COLORREF label_text_color{};\n    COLORREF value_text_color{};\n    if (theApp.m_taskbar_data.specify_each_item_color)\n    {\n        label_text_color = theApp.m_taskbar_data.text_colors[item].label;\n        value_text_color = theApp.m_taskbar_data.text_colors[item].value;\n    }\n    else if (!theApp.m_taskbar_data.text_colors.empty())\n    {\n        label_text_color = theApp.m_taskbar_data.text_colors.begin()->second.label;\n        value_text_color = theApp.m_taskbar_data.text_colors.begin()->second.label;\n    }\n\n    if (plugin != nullptr && plugin->GetAPIVersion() >= 2)\n    {\n        plugin->OnExtenedInfo(ITMPlugin::EI_DRAW_TASKBAR_WND, L\"1\");\n    }\n    if (item->IsCustomDraw())\n    {\n        //根据背景色的亮度判断深色还是浅色模式\n        const COLORREF& bk{ theApp.m_taskbar_data.back_color };\n        int background_brightness{ (GetRValue(bk) + GetGValue(bk) + GetBValue(bk)) / 3 };\n        //由插件自绘\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 2)\n        {\n            plugin->OnExtenedInfo(ITMPlugin::EI_LABEL_TEXT_COLOR, std::to_wstring(label_text_color).c_str());\n            plugin->OnExtenedInfo(ITMPlugin::EI_VALUE_TEXT_COLOR, std::to_wstring(value_text_color).c_str());\n        }\n        drawer.SetTextColor(value_text_color);\n        //需要rtti\n        if (typeid(drawer) == typeid(CDrawCommon))\n        {\n            auto* p_dc = static_cast<CDrawCommon&>(drawer).GetDC();\n            item->DrawItem(p_dc->GetSafeHdc(), rect.left, rect.top, rect.Width(), rect.Height(), background_brightness < 128);\n            p_dc->SelectObject(&m_font);\n        }\n        else if (typeid(drawer) == typeid(CTaskBarDlgDrawCommon))\n        {\n            auto& ref_d2d1_drawer = static_cast<CTaskBarDlgDrawCommon&>(drawer);\n            ref_d2d1_drawer.ExecuteGdiOperation(rect,\n                                                [item, rect, background_brightness](HDC gdi_dc)\n                                                { item->DrawItem(gdi_dc,\n                                                                 rect.left,\n                                                                 rect.top,\n                                                                 rect.Width(),\n                                                                 rect.Height(),\n                                                                 background_brightness < 128); });\n        }\n    }\n    else\n    {\n        CRect rect_label, rect_value;\n        rect_label = rect_value = rect;\n        if (label_width > 0)\n        {\n            if (!vertical)\n            {\n                rect_label = rect_value = rect;\n                rect_label.right = rect_label.left + label_width;\n                rect_value.left = rect_label.right;\n            }\n            else\n            {\n                rect_label.bottom = rect_label.top + rect.Height() / 2;\n                rect_value.top = rect_label.bottom;\n            }\n        }\n        //画标签\n        CString lable_text = theApp.m_taskbar_data.disp_str.GetConst(item).c_str();\n        drawer.DrawWindowText(rect_label, lable_text, label_text_color, (vertical ? IDrawCommon::Alignment::CENTER : IDrawCommon::Alignment::LEFT));\n        //画数值\n        IDrawCommon::Alignment value_alignment{ theApp.m_taskbar_data.value_right_align ? IDrawCommon::Alignment::RIGHT : IDrawCommon::Alignment::LEFT };      //数值的对齐方式\n        if (vertical)\n            value_alignment = IDrawCommon::Alignment::CENTER;\n        drawer.DrawWindowText(rect_value, item->GetItemValueText(), value_text_color, value_alignment);\n    }\n}\n\nvoid CTaskBarDlg::MoveWindow(CRect rect)\n{\n    if (IsWindow(GetSafeHwnd()))\n    {\n        ::MoveWindow(GetSafeHwnd(), rect.left, rect.top, rect.Width(), rect.Height(), TRUE);\n    }\n}\n\nvoid CTaskBarDlg::DisableRenderFeatureIfNecessary(CSupportedRenderEnums& ref_supported_render_enums)\n{\n    bool is_transparent = theApp.m_taskbar_data.IsTaskbarTransparent();\n    // UpdateLayeredWindowIndirect失败则禁用D2D\n    if (theApp.m_taskbar_data.update_layered_window_error_code)\n    {\n        ref_supported_render_enums.DisableD2D1();\n    }\n    // 不符合条件则启用Default（MFC）\n    if (!is_transparent || theApp.m_taskbar_data.auto_set_background_color || theApp.m_taskbar_data.disable_d2d)\n    {\n        ref_supported_render_enums.EnableDefaultOnly();\n    }\n}\n\nvoid CTaskBarDlg::TryDrawStatusBar(IDrawCommon& drawer, const CRect& rect_bar, int usage_percent)\n{\n    //限制范围\n    if (usage_percent > 100)\n        usage_percent = 100;\n    if (usage_percent < 0)\n        usage_percent = 0;\n    COLORREF graph_color = theApp.m_taskbar_data.GetUsageGraphColor();\n    CSize fill_size = CSize(rect_bar.Width() * usage_percent / 100, rect_bar.Height());\n    CRect rect_fill(rect_bar.TopLeft(), fill_size);\n    if (theApp.m_taskbar_data.show_graph_dashed_box)\n        drawer.DrawRectOutLine(rect_bar, graph_color, 1, true);\n    drawer.FillRect(rect_fill, graph_color);\n}\n\nbool CTaskBarDlg::AdjustWindowPos(bool force_adjust)\n{\n    if (this->GetSafeHwnd() == NULL || !IsWindow(this->GetSafeHwnd()))\n        return false;\n\n    if (m_is_width_changed)\n        force_adjust = true;\n\n    if (force_adjust)\n        ResetTaskbarPos();\n\n    ::GetWindowRect(m_hTaskbar, m_rcTaskbar);   //获得任务栏的矩形区域\n\n    static bool last_taskbar_on_top_or_bottom;\n    CheckTaskbarOnTopOrBottom();\n    if (force_adjust || m_taskbar_on_top_or_bottom != last_taskbar_on_top_or_bottom)\n    {\n        CalculateWindowSize();\n        last_taskbar_on_top_or_bottom = m_taskbar_on_top_or_bottom;\n        force_adjust = true;\n    }\n\n    AdjustTaskbarWndPos(force_adjust);\n\n    //如果窗口没有被成功嵌入到任务栏，窗口移动到了基于屏幕左上角的绝对位置，则修正窗口的位置\n    if (m_connot_insert_to_task_bar)\n    {\n        CRect rc_parent;\n        ::GetWindowRect(GetParentHwnd(), rc_parent);\n        CRect rect{ m_rect };\n        rect.MoveToXY(rect.left + rc_parent.left, rect.top + rc_parent.top);\n        this->MoveWindow(rect);\n\n        if (::GetForegroundWindow() == m_hTaskbar)   //在窗口无法嵌入任务栏时，如果焦点设置在了任务栏上，则让窗口置顶\n        {\n            SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);         //设置置顶\n        }\n    }\n\n    m_is_width_changed = false;     //调整完窗口位置重置标志\n    return true;\n}\n\nvoid CTaskBarDlg::ApplyWindowTransparentColor()\n{\n#ifndef COMPILE_FOR_WINXP\n    if (theApp.IsWindows11Taskbar())      //Windows11下背景色不使用纯黑色，以解决深色模式下右键菜单无法弹出的问题\n    {\n        if (theApp.m_taskbar_data.transparent_color == 0 && theApp.m_taskbar_data.back_color == 0)\n        {\n            theApp.m_taskbar_data.transparent_color = 1;\n            theApp.m_taskbar_data.back_color = 1;\n        }\n    }\n    if ((theApp.m_taskbar_data.transparent_color != 0) && theApp.m_taksbar_transparent_color_enable)\n    {\n        auto render_type = m_supported_render_enums.GetAutoFitEnum();\n        switch (render_type)\n        {\n            using namespace DrawCommonHelper;\n        case RenderType::D2D1_WITH_DCOMPOSITION:\n            // D2D绘图并使用DComposition混合，不设置任何属性\n            break;\n        case RenderType::D2D1:\n            // D2D绘图直接使用alpha混合，只设置 WS_EX_LAYERED\n            SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);\n            break;\n        case RenderType::DEFAULT:\n            // GDI绘图使用色键抠像\n            // 仅在透明且不使用自动决定背景颜色时启动D2D渲染器\n            SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);\n            SetLayeredWindowAttributes(theApp.m_taskbar_data.transparent_color, 0, LWA_COLORKEY);\n        }\n    }\n    else\n    {\n        SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);\n    }\n#endif // !COMPILE_FOR_WINXP\n}\n\n//bool CTaskBarDlg::IsTaskbarChanged()\n//{\n//    bool is_scendary_display;\n//    static HWND last_taskbar_handle{};\n//    HWND taskbar_handle = FindTaskbarHandle(is_scendary_display);\n//    bool changed{ false };\n//    if (last_taskbar_handle != taskbar_handle)\n//    {\n//        changed = true;\n//        last_taskbar_handle = taskbar_handle;\n//    }\n//    return changed;\n//}\n\nvoid CTaskBarDlg::WidthChanged()\n{\n    m_is_width_changed = true;\n}\n\nconst CRect& CTaskBarDlg::GetRectForDpiCheck() const\n{\n    return m_rcTaskbar;\n}\n\nUINT CTaskBarDlg::GetDPI() const\n{\n    return m_taskbar_dpi;\n}\n\nvoid CTaskBarDlg::SetDPI(UINT dpi)\n{\n    m_taskbar_dpi = dpi;\n}\n\nUINT CTaskBarDlg::DPI(UINT pixel) const\n{\n    return m_taskbar_dpi * pixel / 96;\n}\n\nint CTaskBarDlg::DPI(int pixel) const\n{\n    return static_cast<int>(m_taskbar_dpi) * pixel / 96;\n}\n\nLONG CTaskBarDlg::DPI(LONG pixel) const\n{\n    return static_cast<LONG>(m_taskbar_dpi) * pixel / 96;\n}\n\nvoid CTaskBarDlg::DPI(CRect& rect) const\n{\n    rect.left = DPI(rect.left);\n    rect.right = DPI(rect.right);\n    rect.top = DPI(rect.top);\n    rect.bottom = DPI(rect.bottom);\n}\n\nCTaskBarDlg::ClassCheckWindowMonitorDPIAndHandle CTaskBarDlg::CheckWindowMonitorDPIAndHandle{};\n\nUINT CTaskBarDlg::ClassCheckWindowMonitorDPIAndHandle::buffered_dpi_x{0};\nUINT CTaskBarDlg::ClassCheckWindowMonitorDPIAndHandle::buffered_dpi_y{0};\nUINT CTaskBarDlg::ClassCheckWindowMonitorDPIAndHandle::dpi_x{0};\nUINT CTaskBarDlg::ClassCheckWindowMonitorDPIAndHandle::dpi_y{0};\n\nHWND CTaskBarDlg::FindTaskbarHandle(bool& is_scendary_display)\n{\n    is_scendary_display = false;\n    HWND hTaskbar = nullptr;\n    //显示在副显示器上\n    if (theApp.m_taskbar_data.show_taskbar_wnd_in_secondary_display && CWindowsSettingHelper::IsTaskbarShowingInAllDisplays())\n    {\n        //获取所有副显示器的任务栏\n        std::vector<HWND> secondary_taskbars;\n        CTaskbarHelper::GetAllSecondaryDisplayTaskbar(secondary_taskbars);\n        if (!secondary_taskbars.empty())\n        {\n            int index = theApp.m_taskbar_data.secondary_display_index;\n            if (index < 0)\n                index = 0;\n            if (index >= static_cast<int>(secondary_taskbars.size()))\n                index = static_cast<int>(secondary_taskbars.size()) - 1;\n            hTaskbar = secondary_taskbars[index];\n            if (hTaskbar != nullptr)\n                is_scendary_display = true;\n        }\n    }\n    if (hTaskbar == nullptr)\n        hTaskbar = ::FindWindow(_T(\"Shell_TrayWnd\"), NULL);\n\n    return hTaskbar;\n}\n\nCString CTaskBarDlg::GetMouseTipsInfo()\n{\n    CString tip_info;\n    CString temp;\n    temp.Format(_T(\"%s: %s\\r\\n (%s: %s/%s: %s)\"), CCommon::LoadText(IDS_TRAFFIC_USED_TODAY),\n        CCommon::KBytesToString((theApp.m_today_up_traffic + theApp.m_today_down_traffic) / 1024u),\n        CCommon::LoadText(IDS_UPLOAD), CCommon::KBytesToString(theApp.m_today_up_traffic / 1024u),\n        CCommon::LoadText(IDS_DOWNLOAD), CCommon::KBytesToString(theApp.m_today_down_traffic / 1024u)\n    );\n    tip_info += temp;\n    if (!IsItemShow(TDI_UP))\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/s\"), CCommon::LoadText(IDS_UPLOAD),\n            CCommon::DataSizeToString(theApp.m_out_speed, theApp.m_taskbar_data));\n        tip_info += temp;\n    }\n    if (!IsItemShow(TDI_DOWN))\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/s\"), CCommon::LoadText(IDS_DOWNLOAD),\n            CCommon::DataSizeToString(theApp.m_in_speed, theApp.m_taskbar_data));\n        tip_info += temp;\n    }\n    if (!IsItemShow(TDI_CPU))\n    {\n        temp.Format(_T(\"\\r\\n%s: %d %%\"), CCommon::LoadText(IDS_CPU_USAGE), theApp.m_cpu_usage);\n        tip_info += temp;\n    }\n    if (!IsShowCpuMemory())\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/%s\"),\n            CCommon::LoadText(IDS_MEMORY_USAGE),\n            CCommon::KBytesToString(theApp.m_used_memory), CCommon::KBytesToString(theApp.m_total_memory));\n    }\n    if (!IsItemShow(TDI_MEMORY))\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/%s (%d %%)\"), CCommon::LoadText(IDS_MEMORY_USAGE),\n            CCommon::KBytesToString(theApp.m_used_memory),\n            CCommon::KBytesToString(theApp.m_total_memory), theApp.m_memory_usage);\n        tip_info += temp;\n    }\n    else\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/%s\"), CCommon::LoadText(IDS_MEMORY_USAGE),\n            CCommon::KBytesToString(theApp.m_used_memory),\n            CCommon::KBytesToString(theApp.m_total_memory));\n        tip_info += temp;\n    }\n    if (!IsItemShow(TDI_CPU_FREQ) && theApp.m_cpu_freq > 0)\n    {\n        temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_CPU_FREQ), CCommon::FreqToString(theApp.m_cpu_freq, theApp.m_taskbar_data));\n        tip_info += temp;\n    }\n\n    if (!IsItemShow(TDI_GPU_USAGE) && theApp.m_gpu_usage >= 0)\n    {\n        temp.Format(_T(\"\\r\\n%s: %d %%\"), CCommon::LoadText(IDS_GPU_USAGE), theApp.m_gpu_usage);\n        tip_info += temp;\n    }\n\n#ifndef WITHOUT_TEMPERATURE\n    CTrafficMonitorDlg* pMainWnd = dynamic_cast<CTrafficMonitorDlg*>(theApp.m_pMainWnd);\n    if (pMainWnd->IsTemperatureNeeded())\n    {\n        if (!IsItemShow(TDI_CPU_TEMP) && theApp.m_cpu_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_CPU_TEMPERATURE), CCommon::TemperatureToString(theApp.m_cpu_temperature, theApp.m_taskbar_data));\n            tip_info += temp;\n        }\n        if (!IsItemShow(TDI_GPU_TEMP) && theApp.m_gpu_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_GPU_TEMPERATURE), CCommon::TemperatureToString(theApp.m_gpu_temperature, theApp.m_taskbar_data));\n            tip_info += temp;\n        }\n        if (!IsItemShow(TDI_HDD_TEMP) && theApp.m_hdd_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_HDD_TEMPERATURE), CCommon::TemperatureToString(theApp.m_hdd_temperature, theApp.m_taskbar_data));\n            tip_info += temp;\n        }\n        if (!IsItemShow(TDI_MAIN_BOARD_TEMP) && theApp.m_main_board_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_MAINBOARD_TEMPERATURE), CCommon::TemperatureToString(theApp.m_main_board_temperature, theApp.m_taskbar_data));\n            tip_info += temp;\n        }\n    }\n#endif\n    if (!IsItemShow(TDI_HDD_USAGE) && theApp.m_hdd_usage >= 0)\n    {\n        temp.Format(_T(\"\\r\\n%s: %d %%\"), CCommon::LoadText(IDS_HDD_USAGE), theApp.m_hdd_usage);\n        tip_info += temp;\n    }\n\n    //添加插件项目的鼠标提示\n    tip_info += theApp.GetPlauginTooltipInfo().c_str();\n\n    return tip_info;\n}\n\nvoid CTaskBarDlg::SetTextFont()\n{\n    //如果m_font已经关联了一个字体资源对象，则释放它\n    if (m_font.m_hObject)\n    {\n        m_font.DeleteObject();\n    }\n    //创建新的字体\n    theApp.m_taskbar_data.font.Create(m_font, GetDPI());\n}\n\nvoid CTaskBarDlg::ApplySettings()\n{\n    SetTextFont();\n    CalculateWindowSize();\n}\n\nvoid CTaskBarDlg::CalculateWindowSize()\n{\n    bool horizontal_arrange = theApp.m_taskbar_data.horizontal_arrange && m_taskbar_on_top_or_bottom;\n    if (theApp.m_taskbar_data.display_item.IsEmpty() && theApp.m_taskbar_data.plugin_display_item.data().empty())\n        theApp.m_taskbar_data.display_item.Add(TDI_UP);        //至少显示一项\n\n    m_item_widths.clear();\n    //显示项目的宽度\n    std::map<CommonDisplayItem, ItemWidth> item_widths;\n\n    m_pDC->SelectObject(&m_font);\n    //计算标签和数值的宽度\n    //const auto& item_map = theApp.m_taskbar_data.disp_str.GetAllItems();\n    for (auto iter = theApp.m_plugins.AllDisplayItemsWithPlugins().begin(); iter != theApp.m_plugins.AllDisplayItemsWithPlugins().end(); ++iter)\n    {\n        if (iter->IsPlugin())\n        {\n            auto plugin = iter->PluginItem();\n            if (plugin != nullptr && theApp.m_taskbar_data.plugin_display_item.Contains(plugin->GetItemId()))\n            {\n                //标签宽度\n                int& label_width{ item_widths[*iter].label_width };\n                //数值宽度\n                int& value_width{ item_widths[plugin].value_width };\n                if (plugin->IsCustomDraw())\n                {\n                    label_width = 0;\n                    value_width = theApp.m_plugins.GetItemWidth(plugin, m_pDC);\n                }\n                else\n                {\n                    CString lable_text = theApp.m_taskbar_data.disp_str.GetConst(plugin).c_str();\n                    label_width = m_pDC->GetTextExtent(lable_text).cx;\n                    value_width = m_pDC->GetTextExtent(plugin->GetItemValueSampleText()).cx;\n                }\n            }\n        }\n        else\n        {\n            //标签宽度\n            item_widths[*iter].label_width = m_pDC->GetTextExtent(theApp.m_taskbar_data.disp_str.GetConst(*iter).c_str()).cx;\n            //数值宽度\n            CString sample_str = iter->GetItemValueSampleText(false);\n            item_widths[*iter].value_width = m_pDC->GetTextExtent(sample_str).cx;\n        }\n    }\n\n    auto item_order{ theApp.m_taskbar_data.item_order.GetAllDisplayItemsWithOrder() };\n    for (const auto& item : item_order)\n    {\n        if (theApp.IsTaksbarItemDisplayed(item))\n        {\n            ItemWidthInfo width_info = item;\n            width_info.item_width = item_widths[item];\n            m_item_widths.push_back(width_info);\n        }\n    }\n\n    int item_count = static_cast<int>(m_item_widths.size());\n\n    //计算窗口总宽度\n    if (IsTasksbarOnTopOrBottom())  //任务栏在桌面的顶部或底部时\n    {\n        m_window_width = 0;\n        if (theApp.m_taskbar_data.horizontal_arrange)   //水平排列时\n        {\n            for (auto iter = m_item_widths.begin(); iter != m_item_widths.end(); ++iter)\n            {\n                m_window_width += iter->item_width.TotalWidth();\n            }\n            m_window_width += DPI(theApp.m_taskbar_data.item_space) * item_count;   //加上每个标签间的空隙\n        }\n        else        //非水平排列时，每两个一组排列\n        {\n            int index = 0;\n            int width0;\n            for (auto iter = m_item_widths.begin(); iter != m_item_widths.end(); ++iter)\n            {\n                if (index % 2 == 0)\n                {\n                    width0 = iter->item_width.TotalWidth();\n                }\n                else\n                {\n                    m_window_width += max(width0, iter->item_width.TotalWidth());\n                }\n                if (item_count % 2 == 1 && index == item_count - 1) //项目数为奇数时加上最后一个的宽度\n                {\n                    m_window_width += iter->item_width.MaxWidth();\n                }\n\n                index++;\n            }\n\n            m_window_width += DPI(theApp.m_taskbar_data.item_space) * ((item_count + 1) / 2 + 1);   //加上每个标签间的空隙\n        }\n    }\n    else        //任务栏在桌面两侧时\n    {\n        m_window_width = 0;\n        //所有标签中最大的宽度即为窗口宽度\n        for (auto iter = m_item_widths.begin(); iter != m_item_widths.end(); ++iter)\n        {\n            if (m_window_width < iter->item_width.TotalWidth())\n                m_window_width = iter->item_width.TotalWidth();\n        }\n    }\n\n    //计算窗口高度\n    if (IsTasksbarOnTopOrBottom())\n    {\n        if (!horizontal_arrange)\n            m_window_height = TASKBAR_WND_HEIGHT;\n        else\n            m_window_height = TASKBAR_WND_HEIGHT * 2 / 3;\n    }\n    else\n    {\n        m_window_height = TASKBAR_WND_HEIGHT / 2 * item_count;\n        m_window_height += (DPI(theApp.m_taskbar_data.item_space) * item_count);   //加上每个标签间的空隙\n    }\n    m_rect.right = m_rect.left + m_window_width;\n    m_rect.bottom = m_rect.top + m_window_height;\n\n}\n\nvoid CTaskBarDlg::SetToolTipsTopMost()\n{\n    m_tool_tips.SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);\n}\n\nvoid CTaskBarDlg::UpdateToolTips()\n{\n    if (theApp.m_taskbar_data.show_tool_tip && IsWindow(m_tool_tips.GetSafeHwnd()))\n    {\n        CString tip_info;\n        tip_info = GetMouseTipsInfo();\n        m_tool_tips.UpdateTipText(tip_info, this);\n    }\n}\n\nbool CTaskBarDlg::IsItemShow(DisplayItem item)\n{\n    return (theApp.m_taskbar_data.display_item.Contains(item));\n}\n\nbool CTaskBarDlg::IsShowCpuMemory()\n{\n    return (theApp.m_taskbar_data.display_item.Contains(TDI_CPU) || theApp.m_taskbar_data.display_item.Contains(TDI_MEMORY));\n}\n\nbool CTaskBarDlg::IsShowNetSpeed()\n{\n    return (theApp.m_taskbar_data.display_item.Contains(TDI_UP) || theApp.m_taskbar_data.display_item.Contains(TDI_DOWN));\n}\n\nbool CTaskBarDlg::IsTaskbarCloseToIconEnable(bool taskbar_wnd_on_left)\n{\n    //在Windows11中，当任务栏窗口显示在右侧时，如果勾选“任务栏窗口靠近图标而不是靠近任务栏窗口”会导致和图标重叠\n    //因为\"MSTaskSwWClass\"窗口的矩形区域不再是任务栏图标最小化按钮所在区域\n    return theApp.m_win_version.IsWindows11OrLater() &&\n        CWindowsSettingHelper::IsTaskbarCenterAlign() && taskbar_wnd_on_left;\n}\n\nBOOL CTaskBarDlg::OnInitDialog()\n{\n    CDialogEx::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n    SetWindowText(TASKBAR_WINDOW_NAME);\n    // 检测系统是否安装了 MicrosoftWindows.Client.WebExperience (aka Windows Web Experience Pack)\n    theApp.m_taskbar_data.is_windows_web_experience_detected =\n        WindowsWebExperienceDetector::IsDetected();\n    // 根据任务栏窗口的设置禁用必要的渲染选项，仅透明且支持D2D渲染时才会使用D2D渲染\n    DisableRenderFeatureIfNecessary(m_supported_render_enums);\n    //设置隐藏任务栏图标\n    ModifyStyleEx(0, WS_EX_TOOLWINDOW);\n\n    m_pDC = GetDC();\n\n    m_hTaskbar = FindTaskbarHandle(m_is_secondary_display); //查找任务栏的句柄\n    ::GetWindowRect(m_hTaskbar, m_rcTaskbar);   //获得任务栏的矩形区域\n\n    //设置窗口透明色\n    ApplyWindowTransparentColor();\n\n    InitTaskbarWnd();\n    m_connot_insert_to_task_bar = !(::SetParent(this->m_hWnd, GetParentHwnd())); //把程序窗口设置成任务栏的子窗口\n\n    //根据已经确定的任务栏最小化窗口区域得到屏幕并获得所在屏幕的DPI（Windows 8.1及其以上）\n    if (theApp.m_win_version.IsWindows8Point1OrLater())\n    {\n        UINT dpi_x, dpi_y;\n        if (theApp.DPIFromRect(GetRectForDpiCheck(), &dpi_x, &dpi_y))\n            SetDPI(dpi_x);\n        else\n            SetDPI(theApp.GetDpi());\n    }\n    else\n    {\n        SetDPI(theApp.GetDpi());\n    }\n\n    //设置字体\n    SetTextFont();\n    m_pDC->SelectObject(&m_font);\n\n    CheckTaskbarOnTopOrBottom();\n    CalculateWindowSize();\n    m_rect.SetRectEmpty();\n    m_rect.bottom = m_window_height;\n    m_rect.right = m_rect.left + m_window_width;\n    m_error_code = GetLastError();\n    AdjustWindowPos(true);\n\n    SetBackgroundColor(theApp.m_taskbar_data.back_color);\n\n    //初始化鼠标提示\n    if (IsWindow(GetSafeHwnd()) && m_tool_tips.Create(this, TTS_ALWAYSTIP) && IsWindow(m_tool_tips.GetSafeHwnd()))\n    {\n        m_tool_tips.SetMaxTipWidth(600);\n        m_tool_tips.AddTool(this, _T(\"\"));\n        SetToolTipsTopMost();       //设置提示信息总是置顶\n    }\n\n    SetTimer(TASKBAR_TIMER, 1000, NULL);\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\nvoid CTaskBarDlg::OnCancel()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //SaveConfig();\n\n    //关闭所有以任务栏窗口为父窗口的窗口\n    for (const auto& item : CBaseDialog::AllUniqueHandels())\n    {\n        HWND parent = ::GetParent(item.second);\n        if (parent == GetSafeHwnd())\n        {\n            ::SendMessage(item.second, WM_COMMAND, IDCANCEL, 0);\n        }\n    }\n\n    DestroyWindow();\n    ResetTaskbarPos();\n\n    //CDialogEx::OnCancel();\n}\n\nvoid CTaskBarDlg::OnRButtonUp(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    m_menu_popuped = true;\n    m_tool_tips.Pop();\n    ITMPlugin* plugin{};\n    bool is_plugin_item_clicked = (CheckClickedItem(point) && m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr);\n    if (is_plugin_item_clicked)\n    {\n        plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n        {\n            if (m_clicked_item.PluginItem()->OnMouseEvent(IPluginItem::MT_RCLICKED, point.x, point.y, (void*)GetSafeHwnd(), IPluginItem::MF_TASKBAR_WND) != 0)\n                return;\n        }\n    }\n\n    CPoint point1;  //定义一个用于确定光标位置的位置\n    GetCursorPos(&point1);  //获取当前光标的位置，以便使得菜单可以跟随光标\n    CMenu* pMenu = (is_plugin_item_clicked ? theApp.m_taskbar_menu_plugin.GetSubMenu(0) : theApp.m_taskbar_menu.GetSubMenu(0));\n    if (pMenu != nullptr)\n    {\n        if (plugin != nullptr)\n        {\n            //将右键菜单中插件菜单的显示文本改为插件名\n            const int PLUGIN_ITEM_INDEX = pMenu->GetMenuItemCount() - 1;    //插件项目为菜单中的最后一项\n            pMenu->ModifyMenu(PLUGIN_ITEM_INDEX, MF_BYPOSITION, PLUGIN_ITEM_INDEX, plugin->GetInfo(ITMPlugin::TMI_NAME));\n            //获取插件图标\n            HICON plugin_icon{};\n            if (plugin->GetAPIVersion() >= 5)\n                plugin_icon = (HICON)plugin->GetPluginIcon();\n            //设置插件图标\n            if (plugin_icon != nullptr)\n                CMenuIcon::AddIconToMenuItem(pMenu->GetSafeHmenu(), PLUGIN_ITEM_INDEX, TRUE, plugin_icon);\n        }\n        //更新插件子菜单\n        theApp.UpdatePluginMenu(&theApp.m_taskbar_menu_plugin_sub_menu, plugin, 2);\n        //弹出菜单\n        pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this);\n    }\n    CDialogEx::OnRButtonUp(nFlags, point1);\n}\n\nvoid CTaskBarDlg::OnInitMenu(CMenu* pMenu)\n{\n    CDialogEx::OnInitMenu(pMenu);\n\n    // TODO: 在此处添加消息处理程序代码\n    pMenu->CheckMenuItem(ID_SHOW_MAIN_WND, MF_BYCOMMAND | (!theApp.m_cfg_data.m_hide_main_window ? MF_CHECKED : MF_UNCHECKED));\n\n    pMenu->EnableMenuItem(ID_SELECT_ALL_CONNECTION, MF_BYCOMMAND | (theApp.m_general_data.show_all_interface ? MF_GRAYED : MF_ENABLED));\n    pMenu->EnableMenuItem(ID_CHECK_UPDATE, MF_BYCOMMAND | (theApp.IsCheckingForUpdate() ? MF_GRAYED : MF_ENABLED));\n\n    //pMenu->SetDefaultItem(ID_NETWORK_INFO);\n    //设置默认菜单项\n    switch (theApp.m_taskbar_data.double_click_action)\n    {\n    case DoubleClickAction::CONNECTION_INFO:\n        pMenu->SetDefaultItem(ID_NETWORK_INFO);\n        break;\n    case DoubleClickAction::HISTORY_TRAFFIC:\n        pMenu->SetDefaultItem(ID_TRAFFIC_HISTORY);\n        break;\n    case DoubleClickAction::SHOW_MORE_INFO:\n        pMenu->SetDefaultItem(ID_SHOW_CPU_MEMORY2);\n        break;\n    case DoubleClickAction::OPTIONS:\n        pMenu->SetDefaultItem(ID_OPTIONS2);\n        break;\n    case DoubleClickAction::TASK_MANAGER:\n        pMenu->SetDefaultItem(ID_OPEN_TASK_MANAGER);\n        break;\n    default:\n        pMenu->SetDefaultItem(-1);\n        break;\n    }\n\n    //设置插件命令的勾选状态\n    ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n    if (plugin != nullptr && plugin->GetAPIVersion() >= 5)\n    {\n        for (int i = ID_PLUGIN_COMMAND_START; i <= ID_PLUGIN_COMMAND_MAX; i++)\n        {\n            bool checked = (plugin->IsCommandChecked(i - ID_PLUGIN_COMMAND_START) != 0);\n            pMenu->CheckMenuItem(i, MF_BYCOMMAND | (checked ? MF_CHECKED : MF_UNCHECKED));\n        }\n    }\n\n    ::SendMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_TASKBAR_MENU_POPED_UP, 0, 0); //通知主窗口菜单已弹出\n}\n\nBOOL CTaskBarDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //屏蔽按回车键和ESC键退出\n    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) return TRUE;\n    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) return TRUE;\n\n    if (theApp.m_taskbar_data.show_tool_tip && !m_menu_popuped && IsWindow(m_tool_tips.GetSafeHwnd()) && (pMsg->message == WM_LBUTTONDOWN ||\n        pMsg->message == WM_LBUTTONUP ||\n        pMsg->message == WM_MOUSEMOVE))\n    {\n        m_tool_tips.RelayEvent(pMsg);\n    }\n\n    if (pMsg->message == WM_KEYDOWN)\n    {\n        bool ctrl = (GetKeyState(VK_CONTROL) & 0x80);\n        bool shift = (GetKeyState(VK_SHIFT) & 0x8000);\n        bool alt = (GetKeyState(VK_MENU) & 0x8000);\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 4)\n        {\n            if (m_clicked_item.PluginItem()->OnKeboardEvent(pMsg->wParam, ctrl, shift, alt, (void*)GetSafeHwnd(), IPluginItem::KF_TASKBAR_WND) != 0)\n                return TRUE;\n        }\n    }\n\n    return CDialogEx::PreTranslateMessage(pMsg);\n}\n\nvoid CTaskBarDlg::OnMouseMove(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n\n    CDialogEx::OnMouseMove(nFlags, point);\n}\n\nvoid CTaskBarDlg::OnLButtonDblClk(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    if (CheckClickedItem(point) && m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr)\n    {\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n        {\n            if (m_clicked_item.PluginItem()->OnMouseEvent(IPluginItem::MT_DBCLICKED, point.x, point.y, (void*)GetSafeHwnd(), IPluginItem::MF_TASKBAR_WND) != 0)\n                return;\n        }\n    }\n    switch (theApp.m_taskbar_data.double_click_action)\n    {\n    case DoubleClickAction::CONNECTION_INFO:\n        SendMessage(WM_COMMAND, ID_NETWORK_INFO);        //双击后弹出“连接详情”对话框\n        break;\n    case DoubleClickAction::HISTORY_TRAFFIC:\n        SendMessage(WM_COMMAND, ID_TRAFFIC_HISTORY);        //双击后弹出“历史流量统计”对话框\n        break;\n    case DoubleClickAction::SHOW_MORE_INFO:\n        PostMessage(WM_COMMAND, ID_SHOW_CPU_MEMORY2);       //切换显示CPU和内存利用率\n        break;\n    case DoubleClickAction::OPTIONS:\n        SendMessage(WM_COMMAND, ID_OPTIONS2);       //双击后弹出“选项设置”对话框\n        break;\n    case DoubleClickAction::TASK_MANAGER:\n        ShellExecuteW(NULL, _T(\"open\"), (theApp.m_system_dir + L\"\\\\Taskmgr.exe\").c_str(), NULL, NULL, SW_NORMAL);       //打开任务管理器\n        break;\n    case DoubleClickAction::SEPCIFIC_APP:\n        ShellExecuteW(NULL, _T(\"open\"), (theApp.m_taskbar_data.double_click_exe).c_str(), NULL, NULL, SW_NORMAL);   //打开指定程序，默认任务管理器\n        break;\n    default:\n        break;\n    }\n    //CDialogEx::OnLButtonDblClk(nFlags, point);\n}\n\nvoid CTaskBarDlg::OnTimer(UINT_PTR nIDEvent)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    if (nIDEvent == TASKBAR_TIMER)\n    {\n        if (m_menu_popuped)     //显示了右键菜单时，不显示鼠标提示\n        {\n            m_tool_tips.Pop();\n        }\n        \n        //每秒钟重新计算窗口的宽度，如果发生变化，则重新调整任务栏窗口位置\n        static int last_window_width = m_window_width;\n        static int last_window_height = m_window_height;\n        CalculateWindowSize();\n        if (last_window_width != m_window_width || last_window_height != m_window_height)\n        {\n            WidthChanged();\n            last_window_width = m_window_width;\n            last_window_height = m_window_height;\n        }\n    }\n\n    CDialogEx::OnTimer(nIDEvent);\n}\n\nBOOL CTaskBarDlg::OnCommand(WPARAM wParam, LPARAM lParam)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    UINT uMsg = LOWORD(wParam);\n    if (uMsg == ID_SELECT_ALL_CONNECTION || uMsg == ID_SELETE_CONNECTION\n        || (uMsg > ID_SELECT_ALL_CONNECTION && uMsg <= ID_SELETE_CONNECTION_MAX))\n    {\n        ::SendMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_COMMAND, wParam, lParam);    //如果点击了“选择网络连接”子菜单项，将消息转发到主窗口\n        return TRUE;\n    }\n\n    //选择了“显示项目”中的插件项目\n    if (uMsg >= ID_SHOW_PLUGIN_ITEM_START && uMsg <= ID_SHOW_PLUGIN_ITEM_MAX)\n    {\n        IPluginItem* item = theApp.m_plugins.GetItemByIndex(uMsg - ID_SHOW_PLUGIN_ITEM_START);\n        if (item != nullptr)\n        {\n            bool displayed = theApp.m_taskbar_data.plugin_display_item.Contains(item->GetItemId());\n            theApp.m_taskbar_data.plugin_display_item.SetStrContained(item->GetItemId(), !displayed);\n            ::PostMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_REOPEN_TASKBAR_WND, 0, 0);\n        }\n    }\n    //选择了插件命令\n    if (uMsg >= ID_PLUGIN_COMMAND_START && uMsg <= ID_PLUGIN_COMMAND_MAX)\n    {\n        int index = uMsg - ID_PLUGIN_COMMAND_START;\n        if (m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr)\n        {\n            ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n            if (plugin != nullptr && plugin->GetAPIVersion() >= 5)\n            {\n                plugin->OnPluginCommand(index, (void*)GetSafeHwnd(), nullptr);\n            }\n        }\n    }\n\n    return CDialogEx::OnCommand(wParam, lParam);\n}\n\nvoid CTaskBarDlg::OnPaint()\n{\n    CPaintDC dc(this); // device context for painting\n                       // TODO: 在此处添加消息处理程序代码\n                       // 不为绘图消息调用 CDialogEx::OnPaint()\n\n    try\n    {\n        ShowInfo(&dc);\n    }\n    catch (CD3D10Exception1& ex)\n    {\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler{ex}(\n            [p_window_support_wrapper = &this->m_taskbar_draw_common_window_support](CHResultException& ex)\n            {\n                return DrawCommonHelper::HandleIfNeedRecreate(\n                    ex,\n                    [p_window_support_wrapper]()\n                    { p_window_support_wrapper->Get().RequestD3D10Device1Recreate(); });\n            });\n    }\n    catch (CD2D1Exception& ex)\n    {\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler{ex}(\n            [p_device_context_support_wrapper = &this->m_d2d1_device_context_support](CHResultException& ex)\n            {\n                return DrawCommonHelper::HandleIfD2D1DeviceNeedRecreate(\n                    ex,\n                    [&]()\n                    { p_device_context_support_wrapper->Get().RequestD2D1DeviceRecreate(ex.GetHResult()); });\n            });\n    }\n    catch (CDCompositionException& ex)\n    {\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler{ex}(\n            [p_device_context_support_wrapper = &this->m_d2d1_device_context_support](CHResultException& ex)\n            {\n                p_device_context_support_wrapper->Get().RequestDCompositionDeviceRecreate(ex.GetHResult());\n                return true;\n            });\n    }\n    catch (CHResultException& ex)\n    {\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler{ex}();\n    }\n    catch (std::runtime_error& ex)\n    {\n        auto* log = ex.what();\n        CCommon::WriteLog(log, theApp.m_log_path.c_str());\n        // 目前只有它会主动抛异常，所有异常全部算它头上\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::IncreaseErrorCountManually();\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::HandleErrorCountIncrement();\n    }\n\n}\n\nvoid CTaskBarDlg::AddHisToList(CommonDisplayItem item_type, int current_usage_percent)\n{\n    int& data_count{ m_history_data_count[item_type] };\n    std::list<int>& list = m_map_history_data[item_type];\n    //将数累加到加链表的头部，直到添加的数据数量达到TASKBAR_GRAPH_STEP的倍数时计算平均数\n    if (data_count % TASKBAR_GRAPH_STEP == 0)\n    {\n        //计算前面累加的TASKBAR_GRAPH_STEP个数据的平均数\n        if (!list.empty())\n            list.front() /= TASKBAR_GRAPH_STEP;\n        //将新的数据添加到末尾\n        list.push_front(current_usage_percent);\n    }\n    else\n    {\n        //数累加到加链表的头部\n        list.front() += current_usage_percent;\n    }\n    size_t graph_max_length = m_item_rects[item_type].Width();\n    //判断是否超过最大长度，如果超过，将链表尾部数据移除\n    if (list.size() > graph_max_length)\n    {\n        list.pop_back();\n    }\n    data_count++;\n}\n\nint CTaskBarDlg::CalculateNetspeedPercent(unsigned __int64 net_speed)\n{\n    int percet = 0;\n    unsigned __int64 max_value{ theApp.m_taskbar_data.GetNetspeedFigureMaxValueInBytes() };\n\n    if (net_speed >= max_value)\n        percet = 100;\n    else if (max_value > 0)\n        percet = net_speed * 100 / max_value;\n    return percet;\n}\n\nbool CTaskBarDlg::CheckClickedItem(CPoint point)\n{\n    for (const auto& item : m_item_rects)\n    {\n        if (item.second.PtInRect(point))\n        {\n            m_clicked_item = item.first;\n            return true;\n        }\n    }\n    m_clicked_item = TDI_UP;\n    return false;\n}\n\nvoid CTaskBarDlg::TryDrawGraph(IDrawCommon& drawer, const CRect& value_rect, CommonDisplayItem item_type)\n{\n    std::list<int>& list = m_map_history_data[item_type];\n    COLORREF graph_color = theApp.m_taskbar_data.GetUsageGraphColor();\n    if (theApp.m_taskbar_data.show_graph_dashed_box)\n        drawer.DrawRectOutLine(value_rect, graph_color, 1, true);\n    int i{ -1 };\n    for (int value : list)\n    {\n        i++;\n        if (i == 0)     //不绘制链表头部的数据，因为在累加中，还未取平均数\n            continue;\n        if (i >= value_rect.Width())\n            break;\n        //限制范围\n        if (value > 100)\n            value = 100;\n        if (value < 0)\n            value = 0;\n        //从右往左画线\n        CPoint start_point = CPoint(value_rect.right - i, value_rect.bottom);\n        int height = value * value_rect.Height() / 100;\n        drawer.DrawLine(start_point, height, graph_color);\n    }\n}\n\nvoid CTaskBarDlg::OnClose()\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    ::SendMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_TASKBAR_WND_CLOSED, 0, 0);\n\n    CDialogEx::OnClose();\n}\n\nvoid CTaskBarDlg::OnLButtonUp(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    if (CheckClickedItem(point) && m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr)\n    {\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n        {\n            if (m_clicked_item.PluginItem()->OnMouseEvent(IPluginItem::MT_LCLICKED, point.x, point.y, (void*)GetSafeHwnd(), IPluginItem::MF_TASKBAR_WND) != 0)\n                return;\n        }\n    }\n\n    CDialogEx::OnLButtonUp(nFlags, point);\n}\n\nafx_msg LRESULT CTaskBarDlg::OnExitmenuloop(WPARAM wParam, LPARAM lParam)\n{\n    m_menu_popuped = false;\n    return 0;\n}\n\n\nafx_msg LRESULT CTaskBarDlg::OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam)\n{\n    return 0;\n}\n\n\nBOOL CTaskBarDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)\n{\n    if (zDelta >= 120 || zDelta <= -120)\n    {\n        CPoint point = pt;\n        ScreenToClient(&point);\n        ITMPlugin* plugin{};\n        bool is_plugin_item_clicked = (CheckClickedItem(point) && m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr);\n        if (is_plugin_item_clicked)\n        {\n            plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n            if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n            {\n                IPluginItem::MouseEventType type;\n                if (zDelta > 0)\n                    type = IPluginItem::MT_WHEEL_UP;\n                else\n                    type = IPluginItem::MT_WHEEL_DOWN;\n                if (m_clicked_item.PluginItem()->OnMouseEvent(type, point.x, point.y, (void*)GetSafeHwnd(), IPluginItem::MF_TASKBAR_WND) != 0)\n                    return TRUE;\n            }\n        }\n    }\n\n    return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);\n}\n"
  },
  {
    "path": "TrafficMonitor/TaskBarDlg.h",
    "content": "﻿#pragma once\n#include \"Common.h\"\n#include \"afxwin.h\"\n#include \"DrawCommon.h\"\n#include \"TaskBarDlgDrawCommon.h\"\n#include \"TrafficMonitor.h\"\n#include \"IniHelper.h\"\n#include \"CommonData.h\"\n#include \"TaskbarItemOrderHelper.h\"\n#include \"SupportedRenderEnums.h\"\n#include <list>\n\n// CTaskBarDlg 对话框\n#define TASKBAR_WND_HEIGHT DPI(32)\t\t\t\t//任务栏窗口的高度\n#define WM_TASKBAR_MENU_POPED_UP (WM_USER + 1004)\t\t//定义任务栏窗口右键菜单弹出时发出的消息\n//#define TASKBAR_GRAPH_MAX_LEN 600\t\t\t\t\t\t//历史数据存储最大长度\n#define TASKBAR_GRAPH_STEP 5\t\t\t\t\t\t\t//几秒钟画一条线\n\nclass CTaskBarDlg : public CDialogEx\n{\n    DECLARE_DYNAMIC(CTaskBarDlg)\n\npublic:\n    CTaskBarDlg(CWnd* pParent = NULL);   // 标准构造函数\n    virtual ~CTaskBarDlg();\n\n    CToolTipCtrl m_tool_tips;\n\n    void ShowInfo(CDC* pDC); \t//将信息绘制到控件上\n    void TryDrawStatusBar(IDrawCommon& drawer, const CRect& rect_bar, int usage_percent); //绘制CPU/内存状态条\n\n    void TryDrawGraph(IDrawCommon& drawer, const CRect& value_rect, CommonDisplayItem item_type);\t\t// 绘制CPU/内存动态图\n\n    bool AdjustWindowPos(bool force_adjust = false);\t//设置窗口在任务栏中的位置（如果force_adjust为true，则会强制调整一次任务栏窗口的位置）\n    void ApplyWindowTransparentColor();\n\n    //bool IsTaskbarChanged();\n\n    void WidthChanged();    //调用此函数通知任务栏窗口宽度改变以强制调整一次任务栏窗口位置\n\n    //获取用于检查DPI的矩形区域\n    const CRect& GetRectForDpiCheck() const;\n\n    UINT GetDPI() const;\n    void SetDPI(UINT dpi);\n    UINT DPI(UINT pixel) const;\n    int DPI(int pixel) const;\n    LONG DPI(LONG pixel) const;\n    void DPI(CRect& rect) const;\n\n    //下面的类定义可以看做函数定义，避免模板函数不同实例化导致静态变量不同。\n    // 近似函数声明\n    // template <class HanlderFunc>\n    // CheckWindowMonitorDPIAndHandle(CTaskBarDlg& ref_taskbar_window, HanlderFunc handler)\n    static class ClassCheckWindowMonitorDPIAndHandle\n    {\n    public:\n        template <class HandlerFunc>\n        void operator()(CTaskBarDlg& ref_taskbar_window, HandlerFunc handler)\n        {\n            bool rtn = theApp.DPIFromRect(ref_taskbar_window.GetRectForDpiCheck(), &dpi_x, &dpi_y);\n            //只取dpi_x作为程序dpi\n            if (rtn && (dpi_x != buffered_dpi_x || dpi_y != buffered_dpi_y))\n            {\n                //更新缓存的数据\n                buffered_dpi_x = dpi_x;\n                buffered_dpi_y = dpi_y;\n                //调用用户自定义处理方法\n                handler(dpi_x, dpi_y);\n            }\n        }\n\n    private:\n        static UINT buffered_dpi_x, buffered_dpi_y;\n        static UINT dpi_x, dpi_y;\n    } CheckWindowMonitorDPIAndHandle;\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_TASK_BAR_DIALOG };\n#endif\n\nprotected:\n    virtual void InitTaskbarWnd() = 0;\n    virtual void AdjustTaskbarWndPos(bool force_adjust) = 0;\n    virtual void ResetTaskbarPos() = 0;\n    virtual void CheckTaskbarOnTopOrBottom() = 0;\t\t//检查任务栏是否在屏幕的顶部或底部，并将结果保存在m_taskbar_on_top_or_bottom中\n    virtual HWND GetParentHwnd() = 0;\n\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n    HWND m_hTaskbar;\t//任务栏窗口句柄\n    CRect m_rcTaskbar;  //任务栏的矩形区域\n    CRect m_rect;\t\t//当前窗口的矩形区域\n    int m_window_width{};   //保存计算得到的窗口宽度\n    int m_window_height{};  //保存计算得到的宽度高度\n    CSupportedRenderEnums m_supported_render_enums{};\n    DefaultCLazyConstructableWithInitializer<\n        CTaskBarDlgDrawCommonWindowSupport,\n        CTaskBarDlgDrawCommonSupport&>\n        m_taskbar_draw_common_window_support{[]() -> std::tuple<CTaskBarDlgDrawCommonSupport&>\n                                             { return {theApp.m_d2d_taskbar_draw_common_support.Get()}; }}; //提供D2D1绘图支持\n    DefaultCLazyConstructableWithInitializer<\n        CD2D1DeviceContextWindowSupport,\n        CTaskBarDlgDrawCommonSupport&>\n        m_d2d1_device_context_support{[]() -> std::tuple<CTaskBarDlgDrawCommonSupport&>\n                                      { return {theApp.m_d2d_taskbar_draw_common_support.Get()}; }};\n\n    //任务栏各个部分的宽度\n    struct ItemWidth\n    {\n        int label_width{};      //标签部分宽度\n        int value_width{};      //数值部分宽度\n\n        int TotalWidth() const  //总宽度\n        {\n            return label_width + value_width;\n        }\n\n        int MaxWidth() const\t//最大宽度\n        {\n            return max(label_width, value_width);\n        }\n    };\n\n    struct ItemWidthInfo : public CommonDisplayItem\n    {\n        ItemWidth item_width;\n\n        ItemWidthInfo()\n        {}\n\n        ItemWidthInfo(const CommonDisplayItem& item)\n            : CommonDisplayItem(item)\n        {}\n    };\n\n    std::vector<ItemWidthInfo> m_item_widths;   //任务栏窗口每个部分的宽度\n    std::map<CommonDisplayItem, CRect> m_item_rects;    //任务栏窗口每个部分的矩形区域\n    CommonDisplayItem m_clicked_item;           //鼠标点击的任务栏项目\n\n    std::map<CommonDisplayItem, std::list<int>> m_map_history_data;  //保存各项数据历史数据的链表，链表保存按照时间顺序，越靠近头部数据越新\n    std::map<CommonDisplayItem, int> m_history_data_count;            //统计添加到历史数据链表的次数\n\n    bool m_connot_insert_to_task_bar{ false };\t//如果窗口无法嵌入任务栏，则为true\n    bool m_taskbar_on_top_or_bottom{ true };\t\t//如果任务栏在屏幕顶部或底部，则为ture\n    int m_error_code{};\n    bool m_menu_popuped{ false };               //指示当前是否有菜单处于弹出状态\n    bool m_is_secondary_display{ false };       //是否显示在副显示器中\n    bool m_is_width_changed{ false };\n\n    UINT m_taskbar_dpi{};//TaskBarDlg自身专用dpi\n\n    CFont m_font;\t\t\t//字体\n\n    CDC* m_pDC{};\t\t//窗口的DC，用来计算窗口的宽度\n\n    //查找任务栏的句柄\n    //is_scendary_display：找到的是否为副显示器的任务栏\n    HWND FindTaskbarHandle(bool& is_scendary_display);\n    CString GetMouseTipsInfo();\t\t//获取鼠标提示\n\n    void AddHisToList(CommonDisplayItem item_type, int current_usage_percent);\t\t//将当前利用率数值添加进链表\n\n    int CalculateNetspeedPercent(unsigned __int64 net_speed);     //计算网速占网速占用图的最大值的百分比\n\n    //判断一个点在哪个显示项目的区域内，并保存到m_clicked_item。如果返回false，则该点不在任何一个项目的区域内，否则返回true\n    bool CheckClickedItem(CPoint point);\n\n    //绘制任务栏窗口中的一个显示项目\n    //  drawer: 绘图类的对象\n    //  type: 项目的类型\n    //  rect: 绘制矩形区域\n    //  label_width: 标签区域的宽度\n    //  vertical: 如果为true，则标签和数值上下显示\n    void DrawDisplayItem(IDrawCommon& drawer, DisplayItem type, CRect rect, int label_width, bool vertical = false);\n\n    //绘制任务栏窗口中的一个插件项目\n   //  drawer: 绘图类的对象\n   //  item: 插件显示项目的指针\n   //  rect: 绘制矩形区域\n   //  label_width: 标签区域的宽度\n   //  vertical: 如果为true，则标签和数值上下显示\n    void DrawPluginItem(IDrawCommon& drawer, IPluginItem* item, CRect rect, int label_width, bool vertical = false);\n\n    void MoveWindow(CRect rect);\n\npublic:\n    static void DisableRenderFeatureIfNecessary(CSupportedRenderEnums& ref_supported_render_enums);\n    void SetTextFont();\n    void ApplySettings();\n    void CalculateWindowSize();\t\t//计算窗口每部分的大小，及各个部分的宽度。窗口大小保存到m_window_width和m_window_height中，各部分宽度保存到m_item_widths中\n\n    void SetToolTipsTopMost();\t\t\t//设置鼠标提示置顶\n    void UpdateToolTips();\n\n    bool GetCannotInsertToTaskBar() const { return m_connot_insert_to_task_bar; }\n    int GetErrorCode() const { return m_error_code; }\n    bool IsTasksbarOnTopOrBottom() const { return m_taskbar_on_top_or_bottom; }\n\n    static bool IsItemShow(DisplayItem item);\n    static bool IsShowCpuMemory();\n    static bool IsShowNetSpeed();\n\n    CommonDisplayItem GetClickedItem() const { return m_clicked_item; }\n\n    //是否允许“任务栏窗口靠近图标而不是任务栏的两侧”选项\n    //taskbar_wnd_on_left: 任务栏窗口是否在任务栏左侧\n    static bool IsTaskbarCloseToIconEnable(bool taskbar_wnd_on_left);\n\n    DECLARE_MESSAGE_MAP()\n\npublic:\n    virtual BOOL OnInitDialog();\n    virtual void OnCancel();\n    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);\n    //afx_msg void OnSetBackgroundColor();\n    //afx_msg void OnSetTextColor();\n    afx_msg void OnInitMenu(CMenu* pMenu);\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    //afx_msg void OnSetFont();\n    afx_msg void OnMouseMove(UINT nFlags, CPoint point);\n    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);\n    afx_msg void OnTimer(UINT_PTR nIDEvent);\n    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);\n    afx_msg void OnPaint();\n    afx_msg void OnClose();\n    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);\nprotected:\n    afx_msg LRESULT OnExitmenuloop(WPARAM wParam, LPARAM lParam);\n    afx_msg LRESULT OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);\n};\n"
  },
  {
    "path": "TrafficMonitor/TaskBarDlgDrawCommon.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include <unordered_map>\n#include \"TaskBarDlgDrawCommon.h\"\n#include \"D2D1Support.h\"\n#include \"TrafficMonitor.h\"\n#include \"DrawCommon.h\"\n#include \"WIC.h\"\n\n#undef min\n\nusing Microsoft::WRL::ComPtr;\n\n// 其实可以把Verify方法作为构造函数\ntemplate <class T, T FAILED_VALUE>\nstruct ReturnValueVerifier\n{\n    static bool Verify(T value) noexcept\n    {\n        if (value != FAILED_VALUE)\n        {\n            return true;\n        }\n        else\n        {\n            return false;\n        }\n    }\n    template <class Cleaner>\n    static bool Verify(T value, Cleaner&& cleaner) noexcept(noexcept(cleaner))\n    {\n        if (value != FAILED_VALUE)\n        {\n            return true;\n        }\n        else\n        {\n            cleaner();\n            return false;\n        }\n    }\n    template <class Cleaner, class Func>\n    static bool Verify(T value, Cleaner&& cleaner, Func&& do_before_clean)\n    {\n        if (value != FAILED_VALUE)\n        {\n            return true;\n        }\n        else\n        {\n            do_before_clean();\n            cleaner();\n            return false;\n        }\n    }\n};\nusing Win32BOOLVerifier = ReturnValueVerifier<BOOL, 0>;\nusing Win32IntVerifier = ReturnValueVerifier<int, 0>;\nusing Win32COLORREFVerifier = ReturnValueVerifier<COLORREF, CLR_INVALID>;\nusing Win32HBITMAPVerifier = ReturnValueVerifier<HBITMAP, nullptr>;\nusing Win32HDCVerifier = ReturnValueVerifier<HDC, nullptr>;\nusing Win32HFONTVerifier = ReturnValueVerifier<HFONT, nullptr>;\nusing Win32HGDIOBJVerifier = ReturnValueVerifier<HGDIOBJ, nullptr>;\n\nvoid LogWin32ApiErrorMessage(DWORD error_code) noexcept\n{\n    // 写入系统格式化后的错误信息\n    if (error_code != 0)\n    {\n        LPTSTR fomat_error = nullptr;\n        ::FormatMessage(\n            FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,\n            NULL,\n            error_code,\n            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n            reinterpret_cast<decltype(fomat_error)>(&fomat_error),\n            0,\n            NULL);\n        if (fomat_error != nullptr)\n        {\n            CCommon::WriteLog(fomat_error, theApp.m_log_path.c_str());\n            ::LocalFree(fomat_error);\n        }\n    }\n}\n\nstd::uint32_t DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::m_error_count = 0;\n\n#define TRAFFICMONITOR_ENUM_AND_EXPLANATION(enumeration, explanation) \\\n    enumeration, \"Handling device loss. HResult = \" #enumeration \": \" explanation\n\nvoid DrawCommonHelper::LogDeviceRecreateReason(HRESULT hr)\n{\n    const static std::unordered_map<HRESULT, const char*> removed_reason{\n        {TRAFFICMONITOR_ENUM_AND_EXPLANATION(\n            DXGI_ERROR_DEVICE_HUNG,\n            \"The graphics driver stopped responding because of an invalid combination of graphics commands sent by the app. If you get this error repeatedly, it is a likely indication that your app caused the device to hang and needs to be debugged.\")},\n        {TRAFFICMONITOR_ENUM_AND_EXPLANATION(\n            DXGI_ERROR_DEVICE_REMOVED,\n            \"The graphics device has been physically removed, turned off, or a driver upgrade has occurred. \")},\n        {TRAFFICMONITOR_ENUM_AND_EXPLANATION(\n            DXGI_ERROR_DEVICE_RESET,\n            \"The graphics device failed because of a badly formed command. If you get this error repeatedly, it may mean that your code is sending invalid drawing commands.\")},\n        {TRAFFICMONITOR_ENUM_AND_EXPLANATION(\n            DXGI_ERROR_DRIVER_INTERNAL_ERROR,\n            \"The graphics driver encountered an error and reset the device.\")},\n        {TRAFFICMONITOR_ENUM_AND_EXPLANATION(\n            DXGI_ERROR_INVALID_CALL,\n            \"The application provided invalid parameter data. If you get this error even once, it means that your code caused the device removed condition and must be debugged.\")},\n        {TRAFFICMONITOR_ENUM_AND_EXPLANATION(\n            S_OK,\n            \"Returned when a graphics device was enabled, disabled, or reset without invalidating the current graphics device. For example, this error code can be returned if an app is using WARP and a hardware adapter becomes available.\")}};\n\n    auto it = removed_reason.find(hr);\n    if (it != removed_reason.end())\n    {\n        CCommon::WriteLog(it->second, theApp.m_log_path.c_str());\n    }\n    else\n    {\n        constexpr static auto unknown_reason{\"Recreate the device for an unknown reason.\"};\n        CCommon::WriteLog(unknown_reason, theApp.m_log_path.c_str());\n        auto str_hr = std::string{\"The reason reports HResult = \"} + std::to_string(hr);\n        CCommon::WriteLog(str_hr.c_str(), theApp.m_log_path.c_str());\n    }\n}\n\nDrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::DefaultD2DDrawCommonExceptionHandler(CHResultException& ex) noexcept\n    : m_ref_ex(ex)\n{\n    ++m_error_count;\n}\n\nvoid DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::ResetErrorCount()\n{\n    m_error_count = 0;\n}\n\nvoid DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::HandleErrorCountIncrement()\n{\n    if (m_error_count > DrawCommonHelper::MAX_D2D1_RENDER_ERROR_COUNT)\n    {\n        m_error_count = 0;\n        // 禁用D2D绘图\n        theApp.m_taskbar_data.disable_d2d = true;\n        ::MessageBox(NULL, CCommon::LoadText(IDS_D2DDRAWCOMMON_ERROR_TIP), NULL, MB_OK | MB_ICONWARNING);\n    }\n}\n\nvoid DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::IncreaseErrorCountManually()\n{\n    ++m_error_count;\n}\n\nHDC DrawCommonHelper::Get1x1AlphaEqual1DC()\n{\n    const static auto result = MakeStaticVariableWrapper<std::tuple<HDC, HGDIOBJ>>(\n        [](auto* p_content)\n        {\n            auto& ref_dc = std::get<0>(*p_content);\n            auto& ref_old_hbitmap = std::get<1>(*p_content);\n\n            ref_dc = ::CreateCompatibleDC(NULL);\n            auto bitmap_info = TaskBarDlgUser32DrawTextHook::Details::GetArgb32BitmapInfo(1, 1);\n            void* p_data{};\n            auto current_hbitmap = ::CreateDIBSection(\n                ref_dc,\n                &bitmap_info,\n                DIB_RGB_COLORS,\n                &p_data,\n                NULL,\n                0);\n            if (!Win32HBITMAPVerifier::Verify(current_hbitmap))\n            {\n                throw std::runtime_error{\n                    TRAFFICMONITOR_ERROR_STR(\"Create ARGB32 DIB (size = 1x1, alpha = 1) failed.\")};\n            }\n            ref_old_hbitmap = ::SelectObject(ref_dc, current_hbitmap);\n            ::GdiFlush();\n            auto p_pixel_data = reinterpret_cast<BYTE*>(p_data);\n            ::memset(p_data, 0, 3);\n            p_pixel_data[3] = DrawCommonHelper::GDI_NO_MODIFIED_FLAG;\n        },\n        [](auto* p_content)\n        {\n            auto& ref_dc = std::get<0>(*p_content);\n            auto& ref_old_hbitmap = std::get<1>(*p_content);\n\n            auto previously_used_hbitmap = ::SelectObject(ref_dc, ref_old_hbitmap);\n            ::DeleteObject(previously_used_hbitmap);\n            ::DeleteDC(ref_dc);\n        });\n    return std::get<0>(result.Get());\n}\n\nbool CTaskBarDlgDrawCommonSupport::IsAllDevicesRecreatedByThisFunction()\n{\n    auto p_d3d10_device1 = m_d3d10_device1.Get();\n    auto hr = p_d3d10_device1->GetDeviceRemovedReason();\n    if (hr != S_OK)\n    {\n        CCommon::WriteLog(\"Notice: D3D10.1 device is invalid. All devices will be recreated. This message is sent by \"\n                          \"the function on the next line:\",\n                          theApp.m_log_path.c_str());\n        CCommon::WriteLog(__FUNCSIG__, theApp.m_log_path.c_str());\n        RecreateAll();\n        return true;\n    }\n    return false;\n}\n\nvoid CTaskBarDlgDrawCommonSupport::InternalRecreateD3D10Device1()\n{\n    auto &&default_adapter1 = CD3D10Support1::GetDeviceList(true).front();\n    m_d3d10_device1.Recreate(default_adapter1);\n}\n\nCTaskBarDlgDrawCommonSupport::CTaskBarDlgDrawCommonSupport()\n{\n    D2D1_STROKE_STYLE_PROPERTIES d2d1_stroke_style_properties{\n        D2D1_CAP_STYLE_FLAT,\n        D2D1_CAP_STYLE_FLAT,\n        D2D1_CAP_STYLE_FLAT,\n        D2D1_LINE_JOIN_MITER,\n        10.0f,\n        D2D1_DASH_STYLE_DASH,\n        1.0f};\n    ThrowIfFailed<CD2D1Exception>(\n        CD2D1Support1::GetFactory()->CreateStrokeStyle(\n            d2d1_stroke_style_properties,\n            NULL,\n            0,\n            &m_p_ps_dot_like_style),\n        TRAFFICMONITOR_ERROR_STR(\"Create GDI PS_DOT like stroke style failed.\"));\n\n    UINT flag = D3D10_CREATE_DEVICE_BGRA_SUPPORT;\n#ifdef DEBUG\n    flag |= D3D10_CREATE_DEVICE_DEBUG;\n#endif\n    m_d3d10_device1.SetFlags(flag);\n    RecreateAll();\n}\n\nauto CTaskBarDlgDrawCommonSupport::GetD3D10Device1() noexcept\n    -> CD3D10Device1&\n{\n    return m_d3d10_device1;\n}\n\nauto CTaskBarDlgDrawCommonSupport::GetD2D1Device() noexcept\n    -> CD2D1Device&\n{\n    return m_d2d1_device;\n}\n\nauto CTaskBarDlgDrawCommonSupport::GetDCompositionDevice() noexcept\n    -> CDCompositionDevice&\n{\n    return m_dcomposition_device;\n}\n\nauto CTaskBarDlgDrawCommonSupport::GetPsDotLikeStyle() noexcept\n    -> Microsoft::WRL::ComPtr<ID2D1StrokeStyle>\n{\n    return m_p_ps_dot_like_style;\n}\n\nvoid CTaskBarDlgDrawCommonSupport::RecreateAll()\n{\n    CCommon::WriteLog(\"Notice: All devices will be recreated. This message is sent by the function on the next line:\",\n                      theApp.m_log_path.c_str());\n    CCommon::WriteLog(__FUNCSIG__, theApp.m_log_path.c_str());\n    InternalRecreateD3D10Device1();\n    RecreateD2D1Device();\n    RecreateDCompositionDevice();\n}\n\nvoid CTaskBarDlgDrawCommonSupport::RecreateD3D10Device1(const HRESULT recreate_reason)\n{\n    if (recreate_reason != S_OK)\n    {\n        DrawCommonHelper::LogDeviceRecreateReason(recreate_reason);\n        CCommon::WriteLog(\"Notice: D3D10.1 device is invalid. All devices will be recreated. This message is sent by \"\n                          \"the function on the next line:\",\n                          theApp.m_log_path.c_str());\n        CCommon::WriteLog(__FUNCSIG__, theApp.m_log_path.c_str());\n    }\n    RecreateAll();\n}\n\nvoid CTaskBarDlgDrawCommonSupport::RecreateD2D1Device(const HRESULT recreate_reason)\n{\n    if (recreate_reason != S_OK)\n    {\n        DrawCommonHelper::LogDeviceRecreateReason(recreate_reason);\n        CCommon::WriteLog(\n            \"Notice: The D2D1 device will be recreated. This message is sent by the function on the next line:\",\n            theApp.m_log_path.c_str());\n        CCommon::WriteLog(__FUNCSIG__, theApp.m_log_path.c_str());\n    }\n    if (IsAllDevicesRecreatedByThisFunction())\n    {\n        return;\n    }\n    Microsoft::WRL::ComPtr<IDXGIDevice> p_dxgi_device{};\n    ThrowIfFailed<CD3D10Exception1>(\n        m_d3d10_device1.Get()->QueryInterface(IID_PPV_ARGS(&p_dxgi_device)),\n        \"Get IDXGIDevice form ID3D10Device1 failed.\");\n    m_d2d1_device.Recreate(p_dxgi_device);\n}\n\nvoid CTaskBarDlgDrawCommonSupport::RecreateDCompositionDevice(const HRESULT recreate_reason)\n{\n    if (recreate_reason != S_OK)\n    {\n        DrawCommonHelper::LogDeviceRecreateReason(recreate_reason);\n        CCommon::WriteLog(\"Notice: The DirectComposition device will be recreated. This message is sent by the function on the next line:\",\n            theApp.m_log_path.c_str());\n        CCommon::WriteLog(__FUNCSIG__, theApp.m_log_path.c_str());\n    }\n    if (IsAllDevicesRecreatedByThisFunction())\n    {\n        return;\n    }\n    auto p_d3d10_device1 = m_d3d10_device1.Get();\n    if (p_d3d10_device1)\n    {\n        ComPtr<IDXGIDevice> p_dxgi_device{};\n        ThrowIfFailed<CD3D10Exception1>(\n            p_d3d10_device1.As(&p_dxgi_device),\n            TRAFFICMONITOR_ERROR_STR(\"Get dxgi device from d3d10 device1 failed.\"));\n        m_dcomposition_device.Recreate(p_dxgi_device);\n        return;\n    }\n    throw std::runtime_error{TRAFFICMONITOR_ERROR_STR(\"D3D10 device not available.\")};\n}\n\nbool CTaskBarDlgDrawCommonSupport::CheckSupport() noexcept\n{\n    return CD2D1Support1::CheckSupport() && CDWriteSupport::CheckSupport();\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::CD3DGdiInteropHelper::CreateDefaultTexture(ComPtr<ID3D10Device1> p_device1, D2D1_SIZE_U size)\n    -> Microsoft::WRL::ComPtr<ID3D10Texture2D>\n{\n    D3D10_TEXTURE2D_DESC description = {};\n    description.ArraySize = 1;\n    description.Format = PIXEL_FORMAT;\n    description.Width = size.width;\n    description.Height = size.height;\n    description.MipLevels = 1;\n    description.SampleDesc.Count = 1;\n    description.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;\n    description.CPUAccessFlags = 0;\n    description.Usage = D3D10_USAGE_DEFAULT;\n\n    ComPtr<ID3D10Texture2D> result{};\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateTexture2D(\n            &description,\n            NULL,\n            &result),\n        TRAFFICMONITOR_ERROR_STR(\"Create default 2D texture failed.\"));\n\n    return result;\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::CD3DGdiInteropHelper::CreateCpuWriteableTexture(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1, const D2D1_SIZE_U size)\n    -> Microsoft::WRL::ComPtr<ID3D10Texture2D>\n{\n    D3D10_TEXTURE2D_DESC description = {};\n    description.ArraySize = 1;\n    description.Format = PIXEL_FORMAT;\n    description.Width = size.width;\n    description.Height = size.height;\n    description.MipLevels = 1;\n    description.SampleDesc.Count = 1;\n    description.BindFlags = D3D10_BIND_SHADER_RESOURCE;\n    description.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;\n    description.Usage = D3D10_USAGE_DYNAMIC;\n\n    ComPtr<ID3D10Texture2D> result{};\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateTexture2D(\n            &description,\n            NULL,\n            &result),\n        TRAFFICMONITOR_ERROR_STR(\"Create CPU writeable 2D texture failed.\"));\n\n    return result;\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::CD3DGdiInteropHelper::GetPsAlphaValueReducer() noexcept\n    -> Microsoft::WRL::ComPtr<ID3D10Blob>\n{\n    const static auto result = MakeStaticVariableWrapper<CShader>(\n        [](CShader* p_content)\n        {\n            p_content->SetCode(\n                         CIMAGE2DEFFECT_SHADER_VS_OUTPUT_DECLARATION\n                         R\"(\nSamplerState input_sampler : register(s0);\nTexture2D input_texture : register(t0);\n\nfloat4 PS(VsOutput ps_in) : SV_TARGET\n{\n    float4 color = input_texture.Sample(input_sampler, ps_in.texcoord);\n    [flatten] if (color.w > )\" TRAFFICMONITOR_ONE_IN_255_FLOOR \" && color.w < \" TRAFFICMONITOR_ONE_IN_255_CEIL \")\"\n                         R\"(\n    {\n        color.w = 0.0;\n        return color;\n    }\n    [flatten] if (color.w == 0)\n    {\n        color.w = 1.0;\n        return color;\n    }\n    return color;\n}\n)\")\n                .SetEntryPoint(\"PS\")\n                .SetName(\"PsGdiTexturePostprocessor\")\n                .SetTarget(\"ps_4_1\")\n                .SetFlags1(D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_WARNINGS_ARE_ERRORS);\n        });\n    return result.Get().Compile();\n}\n\nCTaskBarDlgDrawCommonWindowSupport::CD3DGdiInteropHelper::CD3DGdiInteropHelper(CD3D10Device1& ref_device)\n    : Base{ref_device.GetStorage()}, m_p_device1{ref_device.Get()}, m_alpha_value_effect{ref_device.Get()}\n{\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::CD3DGdiInteropHelper::OnDeviceRecreate(DeviceType p_new_device) noexcept\n{\n    m_p_device1 = p_new_device;\n    m_is_p_device1_recreated = true;\n}\n\nbool CTaskBarDlgDrawCommonWindowSupport::CD3DGdiInteropHelper::HandleDeviceRecreationIfNecessary()\n{\n    if (m_is_p_device1_recreated)\n    {\n        m_alpha_value_effect.RebindDevice1(m_p_device1);\n        return std::exchange(m_is_p_device1_recreated, false);\n    }\n    return false;\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::CD3DGdiInteropHelper::Resize(D2D1_SIZE_U size)\n{\n    m_p_gdi_initial_texture = CreateCpuWriteableTexture(m_p_device1, size);\n    ThrowIfFailed<CD3D10Exception1>(\n        m_p_gdi_initial_texture->QueryInterface(IID_PPV_ARGS(&m_p_gdi_initial_surface)),\n        TRAFFICMONITOR_ERROR_STR(\"Get IDXGISurface1 from D2D gdi_initial_texture failed.\"));\n\n    m_p_gdi_final_texture = CreateDefaultTexture(m_p_device1, size);\n    ThrowIfFailed<CD3D10Exception1>(\n        m_p_gdi_final_texture->QueryInterface(IID_PPV_ARGS(&m_p_gdi_final_surface)),\n        TRAFFICMONITOR_ERROR_STR(\"Get IDXGISurface1 from D2D gdi_final_texture failed.\"));\n\n    m_alpha_value_effect\n        .SetOutputSize(size.width, size.height)\n        .SetPsByteCode(GetPsAlphaValueReducer());\n}\n\nCTaskBarDlgDrawCommonWindowSupport::CTaskBarDlgDrawCommonWindowSupport(CTaskBarDlgDrawCommonSupport& ref_taskbdlg_draw_common_support)\n    : m_d3d_gdi_interop_helper{ref_taskbdlg_draw_common_support.GetD3D10Device1()},\n      m_ref_taskbardlg_draw_common_support{ref_taskbdlg_draw_common_support}\n{\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::Resize(const D2D1_SIZE_U size)\n{\n    auto force_refresh = m_d3d_gdi_interop_helper.HandleDeviceRecreationIfNecessary();\n    if (size.width != m_size.width || size.height != m_size.height || force_refresh)\n    {\n        m_size = size;\n        m_is_size_updated = true;\n    }\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::ResizeGdiInteropPart()\n{\n    if (m_is_size_updated)\n    {\n        m_d3d_gdi_interop_helper.Resize(m_size);\n        m_is_size_updated = false;\n    }\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::SetGdiInteropTexture(void* p_data, D2D1_SIZE_U size)\n{\n    constexpr auto RGBA_SIZE = 4;\n\n    D3D10_MAPPED_TEXTURE2D mapped_texture{};\n    ThrowIfFailed<CD3D10Exception1>(\n        m_d3d_gdi_interop_helper.m_p_gdi_initial_texture->Map(\n            0,\n            D3D10_MAP_WRITE_DISCARD,\n            0,\n            &mapped_texture),\n        TRAFFICMONITOR_ERROR_STR(\"Map m_p_gdi_initial_texture failed.\"));\n\n    auto p_gpu_data = mapped_texture.pData;\n    auto input_pitch = size.width * RGBA_SIZE;\n    if (mapped_texture.RowPitch == input_pitch)\n    {\n        std::size_t data_size = input_pitch * size.height;\n        std::memcpy(p_gpu_data, p_data, data_size);\n    }\n    else\n    {\n        auto p_from = static_cast<BYTE*>(p_data);\n        auto p_to = static_cast<BYTE*>(p_gpu_data);\n        for (auto i = 0u; i < size.height; ++i)\n        {\n            std::memcpy(p_to, p_from, input_pitch);\n            std::advance(p_from, input_pitch);\n            std::advance(p_to, mapped_texture.RowPitch);\n        }\n    }\n\n    m_d3d_gdi_interop_helper.m_p_gdi_initial_texture->Unmap(0);\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::SetFont(HFONT h_font)\n{\n    m_dwrite_helper.SetFont(h_font);\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::GetTextFormat() noexcept\n    -> Microsoft::WRL::ComPtr<IDWriteTextFormat>\n{\n    return m_dwrite_helper.GetTextFormat();\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::GetRawPsDotLikeStyle() noexcept -> ID2D1StrokeStyle*\n{\n    return m_ref_taskbardlg_draw_common_support.GetPsDotLikeStyle().Get();\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::GetGdiInitalTextureSurface() noexcept\n    -> Microsoft::WRL::ComPtr<IDXGISurface1>\n{\n    return m_d3d_gdi_interop_helper.m_p_gdi_initial_surface;\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::GetGdiFinalTextureSurface() noexcept\n    -> Microsoft::WRL::ComPtr<IDXGISurface1>\n{\n    return m_d3d_gdi_interop_helper.m_p_gdi_final_surface;\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::GetSize() const noexcept\n    -> D2D1_SIZE_U\n{\n    return m_size;\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::GetFont() noexcept\n    -> HFONT\n{\n    return m_dwrite_helper.GetFont();\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::DrawAlphaValueReduceEffect() noexcept\n    -> CD3D10DrawCallWaiter\n{\n    constexpr std::array<FLOAT, 4> transparent_black{.0f, .0f, .0f, .0f};\n\n    m_d3d_gdi_interop_helper.m_alpha_value_effect\n        .SetOutputTexture(m_d3d_gdi_interop_helper.m_p_gdi_final_texture)\n        .ClearOnly(transparent_black);\n    return m_d3d_gdi_interop_helper.m_alpha_value_effect\n        .SetInputTexture(m_d3d_gdi_interop_helper.m_p_gdi_initial_texture)\n        .ApplyPipelineConfig()\n        .Draw();\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::RequestD3D10Device1Recreate()\n{\n    auto hr = m_d3d_gdi_interop_helper.m_p_device1->GetDeviceRemovedReason();\n    m_ref_taskbardlg_draw_common_support.RecreateD3D10Device1(hr);\n}\n\nvoid CTaskBarDlgDrawCommonWindowSupport::CDWriteHelper::SetFont(HFONT h_font)\n{\n    if (m_h_last_font != h_font)\n    {\n        ::GetObject(h_font, sizeof(m_last_font), &m_last_font);\n\n        auto abs_font_height_f =\n            static_cast<float>(std::abs(m_last_font.lfHeight));\n        auto dwrite_font_weight =\n            static_cast<DWRITE_FONT_WEIGHT>(m_last_font.lfWeight);\n        auto dwrite_font_style =\n            m_last_font.lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;\n        ThrowIfFailed<CDWriteException>(\n            CDWriteSupport::GetFactory()->CreateTextFormat(\n                theApp.m_taskbar_data.font.name,\n                NULL,\n                dwrite_font_weight,\n                dwrite_font_style,\n                DWRITE_FONT_STRETCH_NORMAL,\n                abs_font_height_f,\n                L\"\",\n                &m_p_text_format),\n            TRAFFICMONITOR_ERROR_STR(\"Create D2D1 Text Format failed.\"));\n\n        m_h_last_font = h_font;\n    }\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::CDWriteHelper::GetFont() noexcept\n    -> HFONT\n{\n    return m_h_last_font;\n}\n\nauto CTaskBarDlgDrawCommonWindowSupport::CDWriteHelper::GetTextFormat() noexcept\n    -> ComPtr<IDWriteTextFormat>\n{\n    return m_p_text_format;\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::Reinitialize()\n{\n    constexpr static D2D1_DEVICE_CONTEXT_OPTIONS options = D2D1_DEVICE_CONTEXT_OPTIONS_NONE;\n\n    ThrowIfFailed<CD2D1Exception>(\n        m_p_device->CreateDeviceContext(\n            options,\n            &m_p_device_context),\n        TRAFFICMONITOR_ERROR_STR(\"Create D2D1 device context failed.\"));\n    ThrowIfFailed<CD2D1Exception>(\n        m_p_device_context->CreateSolidColorBrush(\n            m_foreground_color,\n            &m_p_foreground_color_brush),\n        TRAFFICMONITOR_ERROR_STR(\"Create foreground solid color brush failed.\"));\n    ThrowIfFailed<CD2D1Exception>(\n        m_p_device_context->CreateSolidColorBrush(\n            m_background_color,\n            &m_p_background_color_brush),\n        TRAFFICMONITOR_ERROR_STR(\"Create background solid color brush failed.\"));\n\n    auto sp_bitmap_cache = m_wp_bitmap_cache.lock();\n    if (sp_bitmap_cache)\n    {\n        sp_bitmap_cache->RebindRenderTarget(m_p_device_context);\n    }\n}\n\nCD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::CD2D1DeviceContextHelper(CD2D1Device& ref_device)\n    : Base{ref_device.GetStorage()}, m_p_device{ref_device.Get()}\n{\n}\n\nbool CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::HandleDeviceRecreationIfNecessary()\n{\n    if (m_need_recreate)\n    {\n        Reinitialize();\n        return std::exchange(m_need_recreate, false);\n    }\n    return false;\n}\n\nauto CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::GetRawForeSolidColorBruch() noexcept\n    -> ID2D1SolidColorBrush*\n{\n    return m_p_foreground_color_brush.Get();\n}\n\nauto CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::GetRawBackSolidColorBruch() noexcept\n    -> ID2D1SolidColorBrush*\n{\n    return m_p_background_color_brush.Get();\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::SetBackColor(COLORREF color, BYTE alpha) noexcept\n{\n    auto new_d2d1_color = CRenderTarget::COLORREF_TO_D2DCOLOR(color, alpha);\n    if (!IsBitwiseEquality(new_d2d1_color, m_background_color))\n    {\n        m_p_background_color_brush->SetColor(new_d2d1_color);\n        m_background_color = new_d2d1_color;\n    };\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::SetForeColor(COLORREF color, BYTE alpha) noexcept\n{\n    auto new_d2d1_color = CRenderTarget::COLORREF_TO_D2DCOLOR(color, alpha);\n    if (!IsBitwiseEquality(new_d2d1_color, m_foreground_color))\n    {\n        m_p_foreground_color_brush->SetColor(new_d2d1_color);\n        m_foreground_color = new_d2d1_color;\n    };\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::OnDeviceRecreate(DeviceType p_new_device) noexcept\n{\n    m_p_device = p_new_device;\n    m_need_recreate = true;\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::RebindD2D1BitmapCache(std::weak_ptr<class CD2D1BitmapCache> wp_cache)\n{\n    m_wp_bitmap_cache = wp_cache;\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::RebindRenderTargetSurface(Microsoft::WRL::ComPtr<IDXGISurface> p_surface)\n{\n    const D2D1_BITMAP_PROPERTIES1 bitmap_properties = D2D1::BitmapProperties1(\n        D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,\n        D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),\n        96.f,\n        96.f);\n\n    if (!m_p_device_context)\n    {\n        Reinitialize();\n    }\n    ThrowIfFailed<CD2D1Exception>(\n        m_p_device_context->CreateBitmapFromDxgiSurface(\n            p_surface.Get(),\n            &bitmap_properties,\n            &m_p_d2d_render_target_bitmap),\n        TRAFFICMONITOR_ERROR_STR(\"Create ID2D1Bitmap1 from dxgi surface failed.\"));\n    m_p_device_context->SetTarget(m_p_d2d_render_target_bitmap.Get());\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::Reset()\n{\n    m_p_device_context.Reset();\n    m_p_d2d_render_target_bitmap.Reset();\n    m_p_foreground_color_brush.Reset();\n    m_p_background_color_brush.Reset();\n}\n\nauto CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::GetCachedBitmap(HBITMAP hbitmap) const\n    -> Microsoft::WRL::ComPtr<ID2D1Bitmap>\n{\n    auto sp_cache = m_wp_bitmap_cache.lock();\n    if (sp_cache)\n    {\n        auto result = sp_cache->GetCachedBitmap(hbitmap);\n        return result;\n    }\n    return {};\n}\n\nauto CD2D1DeviceContextWindowSupport::CD2D1DeviceContextHelper::GetDeviceContext() const\n    -> Microsoft::WRL::ComPtr<ID2D1DeviceContext>\n{\n    return m_p_device_context;\n}\n\nvoid CD2D1DeviceContextWindowSupport::CDCompositionHelper::InitializeSwapChain(const D2D1_SIZE_U size)\n{\n    DXGI_SWAP_CHAIN_DESC1 dxgi_swap_chain_desc1;\n    ::memset(&dxgi_swap_chain_desc1, 0, sizeof(dxgi_swap_chain_desc1));\n    dxgi_swap_chain_desc1.Width = size.width;\n    dxgi_swap_chain_desc1.Height = size.height;\n    dxgi_swap_chain_desc1.Format = CTaskBarDlgDrawCommonWindowSupport::PIXEL_FORMAT;\n    dxgi_swap_chain_desc1.SampleDesc.Count = 1;\n    dxgi_swap_chain_desc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;\n    dxgi_swap_chain_desc1.BufferCount = 2;\n    dxgi_swap_chain_desc1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;\n    dxgi_swap_chain_desc1.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;\n\n    ThrowIfFailed<CDxgiException>(\n        CDxgi1Support2::GetFactory()->CreateSwapChainForComposition(\n            m_p_d3d10_device1.Get(),\n            &dxgi_swap_chain_desc1,\n            nullptr,\n            &m_p_swap_chain1),\n        TRAFFICMONITOR_ERROR_STR(\"Create swap chain for composition failed.\"));\n}\n\nvoid CD2D1DeviceContextWindowSupport::CDCompositionHelper::RebindSwapChain(Microsoft::WRL::ComPtr<IDXGISwapChain1> p_swap_chain1)\n{\n    m_p_visual->SetContent(p_swap_chain1.Get());\n    m_p_target->SetRoot(m_p_visual.Get());\n}\n\nvoid CD2D1DeviceContextWindowSupport::CDCompositionHelper::ReinitializeDCompositionPart()\n{\n    bool topmost = ::GetWindowLong(m_hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST;\n    ThrowIfFailed<CDCompositionException>(\n        m_p_composition_device->CreateTargetForHwnd(\n            m_hwnd,\n            topmost,\n            &m_p_target),\n        TRAFFICMONITOR_ERROR_STR(\"Create dcomposition target for hwnd failed.\"));\n\n    ThrowIfFailed<CDCompositionException>(\n        m_p_composition_device->CreateVisual(&m_p_visual),\n        TRAFFICMONITOR_ERROR_STR(\"Create dcomposition visual failed.\"));\n}\n\nvoid CD2D1DeviceContextWindowSupport::CDCompositionHelper::ReinitializeD3D10Device1Part()\n{\n    InitializeSwapChain(m_size);\n}\n\nCD2D1DeviceContextWindowSupport::CDCompositionHelper::CDCompositionHelper(CDCompositionDevice& ref_dcomposition_device, CD3D10Device1& ref_d3d10_device1, HWND hwnd)\n    : CDCompositionResourceBase{ref_dcomposition_device.GetStorage()}, CD3D10Device1ResourceBase{ref_d3d10_device1.GetStorage()},\n      m_p_composition_device{ref_dcomposition_device.Get()}, m_p_d3d10_device1{ref_d3d10_device1.Get()}, m_hwnd{hwnd}\n{\n    ReinitializeDCompositionPart();\n}\n\nvoid CD2D1DeviceContextWindowSupport::CDCompositionHelper::OnDeviceRecreate(CDCompositionDeviceType p_new_composition_device) noexcept\n{\n    m_p_composition_device = p_new_composition_device;\n    m_need_recreate_dcomposition_device = true;\n}\n\nvoid CD2D1DeviceContextWindowSupport::CDCompositionHelper::OnDeviceRecreate(CD3D10Device1Type p_new_d3d10_device1) noexcept\n{\n    m_p_d3d10_device1 = p_new_d3d10_device1;\n    m_need_recreate_d3d10_device1 = true;\n}\n\nbool CD2D1DeviceContextWindowSupport::CDCompositionHelper::HandleDeviceRecreationIfNecessary()\n{\n    auto result = false;\n    if (m_need_recreate_dcomposition_device)\n    {\n        ReinitializeDCompositionPart();\n        result |= std::exchange(m_need_recreate_dcomposition_device, false);\n    }\n    if (m_need_recreate_d3d10_device1)\n    {\n        ReinitializeD3D10Device1Part();\n        result |= std::exchange(m_need_recreate_d3d10_device1, false);\n    }\n    return result;\n}\n\nauto CD2D1DeviceContextWindowSupport::CDCompositionHelper::Resize(const D2D1_SIZE_U size)\n    -> Microsoft::WRL::ComPtr<IDXGISurface>\n{\n    if (!m_p_swap_chain1 || m_size.height == 0 || m_size.width == 0)\n    {\n        InitializeSwapChain(size);\n    }\n    else\n    {\n        ThrowIfFailed<CDxgiException>(\n            m_p_swap_chain1->ResizeBuffers(\n                0,\n                size.width,\n                size.height,\n                DXGI_FORMAT_UNKNOWN,\n                0),\n            TRAFFICMONITOR_ERROR_STR(\"Resize composition swap chain failed.\"));\n    }\n\n    RebindSwapChain(m_p_swap_chain1);\n\n    ComPtr<IDXGISurface> result{};\n    ThrowIfFailed<CDxgiException>(\n        m_p_swap_chain1->GetBuffer(\n            0,\n            IID_PPV_ARGS(&result)),\n        TRAFFICMONITOR_ERROR_STR(\"Get buffer from composition swap chain failed.\"));\n    m_size = size;\n    return result;\n}\n\nvoid CD2D1DeviceContextWindowSupport::CDCompositionHelper::Present()\n{\n    if (m_need_recreate_d3d10_device1 || m_need_recreate_dcomposition_device)\n    {\n        return;\n    }\n    ThrowIfFailed<CDxgiException>(\n        m_p_swap_chain1->Present(1, 0),\n        TRAFFICMONITOR_ERROR_STR(\"Call IDXGISwapChain::Present(1, 0) failed.\"));\n    ThrowIfFailed<CDCompositionException>(\n        m_p_composition_device->Commit(),\n        TRAFFICMONITOR_ERROR_STR(\"Commit dcomposition draw call failed.\"));\n}\n\nauto CD2D1DeviceContextWindowSupport::CDCompositionHelper::GetD3D10Device1()\n    -> Microsoft::WRL::ComPtr<ID3D10Device1>\n{\n    return m_p_d3d10_device1;\n}\n\nbool CD2D1DeviceContextWindowSupport::CDCompositionHelper::IsInvalid() const\n{\n    BOOL result{FALSE};\n    ThrowIfFailed<CDCompositionException>(\n        m_p_composition_device->CheckDeviceState(&result),\n        TRAFFICMONITOR_ERROR_STR(\"Check dcomposition device state failed.\"));\n    return result == FALSE;\n}\n\nauto CD2D1DeviceContextWindowSupport::CD3DHelper::CreateGdiCompatibleTexture(ComPtr<ID3D10Device1> p_device1, const D2D1_SIZE_U size)\n    -> Microsoft::WRL::ComPtr<ID3D10Texture2D>\n{\n    D3D10_TEXTURE2D_DESC description = {};\n    description.ArraySize = 1;\n    description.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;\n    description.Format = CTaskBarDlgDrawCommonWindowSupport::PIXEL_FORMAT;\n    description.Width = size.width;\n    description.Height = size.height;\n    description.MipLevels = 1;\n    description.SampleDesc.Count = 1;\n    description.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;\n\n    Microsoft::WRL::ComPtr<ID3D10Texture2D> result{};\n    ThrowIfFailed<CD3D10Exception1>(\n        p_device1->CreateTexture2D(\n            &description,\n            NULL,\n            &result),\n        TRAFFICMONITOR_ERROR_STR(\"CD2D1DeviceContextWindowSupport create texture2D failed.\"));\n\n    return result;\n}\n\nCD2D1DeviceContextWindowSupport::CD3DHelper::CD3DHelper(CD3D10Device1& ref_device)\n    : Base{ref_device.GetStorage()}, m_p_device1{ref_device.Get()}\n{\n}\n\nauto CD2D1DeviceContextWindowSupport::CD3DHelper::Resize(const D2D1_SIZE_U size)\n    -> Microsoft::WRL::ComPtr<IDXGISurface>\n{\n    m_p_render_target_texture = CreateGdiCompatibleTexture(m_p_device1, size);\n    ThrowIfFailed<CD3D10Exception1>(\n        m_p_render_target_texture.As(&m_p_render_target_surface),\n        TRAFFICMONITOR_ERROR_STR(\"Get IDXGISurface1 from D2D render target texture failed.\"));\n    return m_p_render_target_surface;\n}\n\nbool CD2D1DeviceContextWindowSupport::CD3DHelper::HandleDeviceRecreationIfNecessary()\n{\n    if (m_need_recreate)\n    {\n        return std::exchange(m_need_recreate, false);\n    }\n    return true;\n}\n\nvoid CD2D1DeviceContextWindowSupport::CD3DHelper::OnDeviceRecreate(DeviceType p_new_device) noexcept\n{\n    m_p_device1 = p_new_device;\n    m_need_recreate = true;\n}\n\nauto CD2D1DeviceContextWindowSupport::CD3DHelper::GetRenderTargetSurface()\n    -> Microsoft::WRL::ComPtr<IDXGISurface1>\n{\n    return m_p_render_target_surface;\n}\n\nauto CD2D1DeviceContextWindowSupport::CD3DHelper::GetD3D10Device1()\n    -> Microsoft::WRL::ComPtr<ID3D10Device1>\n{\n    return m_p_device1;\n}\n\nauto CD2D1DeviceContextWindowSupport::GetNullableDCompositionHelper()\n    -> CNullable<CDCompositionHelper>&\n{\n    return GetStorageAs<CNullable<CDCompositionHelper>>();\n}\n\nauto CD2D1DeviceContextWindowSupport::GetNullableD3DHelper()\n    -> CNullable<CD3DHelper>&\n{\n    return GetStorageAs<CNullable<CD3DHelper>>();\n}\n\nvoid CD2D1DeviceContextWindowSupport::DestroyStorage()\n{\n    m_size = {};\n    Dispatch(\n        {{DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION,\n          [this]()\n          { Destroy(&GetNullableDCompositionHelper()); }},\n         {DrawCommonHelper::RenderType::D2D1,\n          [this]()\n          { Destroy(&GetNullableD3DHelper()); }}});\n}\n\nCD2D1DeviceContextWindowSupport::CD2D1DeviceContextWindowSupport(CTaskBarDlgDrawCommonSupport& ref_task_bar_dlg_draw_common_support)\n    : m_ref_task_bar_dlg_draw_common_support{ref_task_bar_dlg_draw_common_support},\n      m_d2d1_device_context_helper{ref_task_bar_dlg_draw_common_support.GetD2D1Device()}\n{\n    EmplaceAt(&GetNullableDCompositionHelper());\n}\n\nCD2D1DeviceContextWindowSupport::~CD2D1DeviceContextWindowSupport()\n{\n    DestroyStorage();\n}\n\nauto CD2D1DeviceContextWindowSupport::SetWorkingDevice(CDCompositionDevice& ref_dcomposition_device, CD3D10Device1& ref_d3d10_device1, HWND hwnd)\n    -> CDCompositionHelper&\n{\n    auto& ref_nullable_dcomposition_helper = GetNullableDCompositionHelper();\n    if (m_render_type == DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION && m_is_initialized)\n    {\n        auto& result = ref_nullable_dcomposition_helper.GetUnsafe();\n        if (result.IsInvalid())\n        {\n            throw CDCompositionException(\n                S_FALSE,\n                TRAFFICMONITOR_ERROR_STR(\"DComposition device is invalid.\\nNote: The HRESULT value is not set by Direct Composition API. Please ignore it.\"));\n        }\n        return result;\n    }\n    DestroyStorage();\n    EmplaceAt(&ref_nullable_dcomposition_helper);\n    m_render_type = DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION;\n    ref_nullable_dcomposition_helper.Construct(ref_dcomposition_device, ref_d3d10_device1, hwnd);\n    m_is_initialized = true;\n    return ref_nullable_dcomposition_helper.GetUnsafe();\n}\n\nauto CD2D1DeviceContextWindowSupport::SetWorkingDevice(CD3D10Device1& ref_device1)\n    -> CD3DHelper&\n{\n    auto& ref_nullable_d3d_helper = GetNullableD3DHelper();\n\n    if (m_render_type == DrawCommonHelper::RenderType::D2D1 && m_is_initialized)\n    {\n        return ref_nullable_d3d_helper.GetUnsafe();\n    }\n    DestroyStorage();\n    EmplaceAt(&ref_nullable_d3d_helper);\n    m_render_type = DrawCommonHelper::RenderType::D2D1;\n    ref_nullable_d3d_helper.Construct(ref_device1);\n    m_is_initialized = true;\n    return ref_nullable_d3d_helper.GetUnsafe();\n}\n\nauto CD2D1DeviceContextWindowSupport::Resize(const D2D1_SIZE_U size)\n    -> Microsoft::WRL::ComPtr<ID2D1DeviceContext>\n{\n    auto force_refresh = m_d2d1_device_context_helper.HandleDeviceRecreationIfNecessary();\n    auto nullable_force_refresh = Dispatch<bool>(\n        {{DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION,\n          [this]()\n          { return GetNullableDCompositionHelper().GetUnsafe().HandleDeviceRecreationIfNecessary(); }},\n         {DrawCommonHelper::RenderType::D2D1,\n          [this]()\n          { return GetNullableD3DHelper().GetUnsafe().HandleDeviceRecreationIfNecessary(); }}});\n    force_refresh |= nullable_force_refresh.GetUnsafe();\n\n    if (m_size.width != size.width || m_size.height != size.height || force_refresh)\n    {\n        m_d2d1_device_context_helper.Reset();\n        auto nullable_p_render_target_surface =\n            Dispatch<Microsoft::WRL::ComPtr<IDXGISurface>>(\n                {{DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION,\n                  [this, size]()\n                  { return GetNullableDCompositionHelper().GetUnsafe().Resize(size); }},\n                 {DrawCommonHelper::RenderType::D2D1,\n                  [this, size]()\n                  { return GetNullableD3DHelper().GetUnsafe().Resize(size); }}});\n        m_d2d1_device_context_helper.RebindRenderTargetSurface(nullable_p_render_target_surface.GetUnsafe());\n        m_size = size;\n    }\n    return m_d2d1_device_context_helper.GetDeviceContext();\n}\n\nvoid CD2D1DeviceContextWindowSupport::PresentWhenUseDComposition()\n{\n    Dispatch({{DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION,\n               [this]()\n               { GetNullableDCompositionHelper().GetUnsafe().Present(); }}});\n}\n\nauto CD2D1DeviceContextWindowSupport::GetRenderTargetSurfaceWhenUseDefault()\n    -> Microsoft::WRL::ComPtr<IDXGISurface1>\n{\n    if (m_render_type == DrawCommonHelper::RenderType::D2D1)\n    {\n        return GetNullableD3DHelper().GetUnsafe().GetRenderTargetSurface();\n    }\n    return {};\n}\n\nvoid CD2D1DeviceContextWindowSupport::RebindD2D1BitmapCache(std::weak_ptr<class CD2D1BitmapCache> wp_cache)\n{\n    m_d2d1_device_context_helper.RebindD2D1BitmapCache(wp_cache);\n}\n\nvoid CD2D1DeviceContextWindowSupport::SetBackColor(COLORREF color, BYTE alpha) noexcept\n{\n    m_d2d1_device_context_helper.SetBackColor(color, alpha);\n}\n\nauto CD2D1DeviceContextWindowSupport::GetRawBackSolidColorBruch() noexcept\n    -> ID2D1SolidColorBrush*\n{\n    return m_d2d1_device_context_helper.GetRawBackSolidColorBruch();\n}\n\nauto CD2D1DeviceContextWindowSupport::SetForeColor(COLORREF color, BYTE alpha) noexcept\n    -> CD2D1DeviceContextWindowSupport*\n{\n    m_d2d1_device_context_helper.SetForeColor(color, alpha);\n    return this;\n}\n\nauto CD2D1DeviceContextWindowSupport::GetRawForeSolidColorBruch() noexcept\n    -> ID2D1SolidColorBrush*\n{\n    return m_d2d1_device_context_helper.GetRawForeSolidColorBruch();\n}\n\nauto CD2D1DeviceContextWindowSupport::GetCachedBitmap(HBITMAP hbitmap)\n    -> Microsoft::WRL::ComPtr<ID2D1Bitmap>\n{\n    return m_d2d1_device_context_helper.GetCachedBitmap(hbitmap);\n}\n\nvoid CD2D1DeviceContextWindowSupport::RequestD3D10Device1Recreate()\n{\n    auto nullable_p_d3d10_device1 = Dispatch<Microsoft::WRL::ComPtr<ID3D10Device1>>(\n        {{DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION,\n          [this]()\n          { return GetNullableDCompositionHelper().GetUnsafe().GetD3D10Device1(); }},\n         {DrawCommonHelper::RenderType::D2D1,\n          [this]()\n          { return GetNullableD3DHelper().GetUnsafe().GetD3D10Device1(); }}});\n    auto p_d3d10_device1 = nullable_p_d3d10_device1.GetUnsafe();\n    auto recreate_reason = p_d3d10_device1->GetDeviceRemovedReason();\n    m_ref_task_bar_dlg_draw_common_support.RecreateD3D10Device1(recreate_reason);\n}\n\nvoid CD2D1DeviceContextWindowSupport::RequestD2D1DeviceRecreate(const HRESULT recreate_reason)\n{\n    m_ref_task_bar_dlg_draw_common_support.RecreateD2D1Device(recreate_reason);\n}\n\nvoid CD2D1DeviceContextWindowSupport::RequestDCompositionDeviceRecreate(const HRESULT recreate_reason)\n{\n    m_ref_task_bar_dlg_draw_common_support.RecreateDCompositionDevice(recreate_reason);\n}\n\nnamespace TaskBarDlgUser32DrawTextHook\n{\n    namespace Details\n    {\n        auto GetArgb32BitmapInfo(CRect rect) noexcept\n            -> ::BITMAPINFO\n        {\n            LONG width = std::abs(rect.Width());\n            LONG height = std::abs(rect.Height());\n            return GetArgb32BitmapInfo(width, height);\n        }\n\n        auto GetArgb32BitmapInfo(LONG width, LONG height) noexcept\n            -> ::BITMAPINFO\n        {\n            ::BITMAPINFO result;\n            memset(&result, 0, sizeof(BITMAPINFO));\n            result.bmiHeader.biSize = sizeof(result.bmiHeader);\n            // 保证是自上而下\n            result.bmiHeader.biWidth = static_cast<LONG>(width);\n            result.bmiHeader.biHeight = -static_cast<LONG>(height);\n            result.bmiHeader.biPlanes = 1;\n            result.bmiHeader.biBitCount = 32;\n            result.bmiHeader.biCompression = BI_RGB;\n            return result;\n        }\n\n        template <class DrawTextFunctionNamespace, class... DrawTextArgs>\n        int ReplacedDrawTextCommon(const CDrawTextReplacedFunction<DrawTextFunctionNamespace>& ref_this, DrawTextArgs&&... draw_text_args)\n        {\n            constexpr std::size_t hdc_index = 0;\n            constexpr std::size_t lpchText_index = 1;\n            constexpr std::size_t cchText_index = 2;\n            constexpr std::size_t lprc_index = 3;\n            constexpr std::size_t format_index = 4;\n\n            auto p_original_function = DrawTextFunctionNamespace::GetOriginalFunction();\n            auto args_tuple = std::forward_as_tuple(draw_text_args...);\n            auto input_hdc = std::get<hdc_index>(args_tuple);\n            auto input_format = std::get<format_index>(args_tuple);\n            bool is_only_calculate_size = input_format & DT_CALCRECT;\n            if (ref_this.m_state.m_on_draw_text_call_matched_hdc != input_hdc || is_only_calculate_size)\n            {\n                return (*p_original_function)(std::forward<DrawTextArgs>(draw_text_args)...);\n            }\n            auto text_length = std::get<cchText_index>(args_tuple);\n            if (text_length == 0)\n            {\n                return User32DrawTextManager::CUSTOM_SUCCESS;\n            }\n            // https://stackoverflow.com/questions/42221322/how-to-draw-text-with-transparency-using-gdi\n            if (p_original_function)\n            {\n                HDC text_dc{NULL};\n                text_dc = ::CreateCompatibleDC(NULL);\n                if (!Win32HDCVerifier::Verify(text_dc))\n                {\n                    return 0;\n                }\n                auto clean_after_creating_dc = [&text_dc]() noexcept\n                {\n                    ::DeleteDC(text_dc);\n                };\n\n                auto& ref_input_rect = std::get<lprc_index>(args_tuple);\n                auto bitmap_info = GetArgb32BitmapInfo(ref_input_rect);\n                void* p_data;\n                auto text_hbitmap = ::CreateDIBSection(\n                    text_dc,\n                    &bitmap_info,\n                    DIB_RGB_COLORS,\n                    &p_data,\n                    NULL,\n                    0);\n                if (!Win32HBITMAPVerifier::Verify(text_hbitmap))\n                {\n                    clean_after_creating_dc();\n                    return 0;\n                }\n                auto clean_after_creating_text_hbitmap =\n                    [&text_hbitmap, &clean_after_creating_dc]() noexcept\n                {\n                    ::DeleteObject(text_hbitmap);\n                    clean_after_creating_dc();\n                };\n\n                HGDIOBJ old_hbitmap = ::SelectObject(text_dc, text_hbitmap);\n                auto clean_after_selecting_text_hbitmap =\n                    [&text_dc, &old_hbitmap, &clean_after_creating_text_hbitmap]() noexcept\n                {\n                    ::SelectObject(text_dc, old_hbitmap);\n                    clean_after_creating_text_hbitmap();\n                };\n\n                auto hfont = ::GetCurrentObject(input_hdc, OBJ_FONT);\n                if (!Win32HGDIOBJVerifier::Verify(\n                        hfont,\n                        clean_after_selecting_text_hbitmap))\n                {\n                    return 0;\n                }\n                HGDIOBJ old_hfont = ::SelectObject(text_dc, hfont);\n                auto clean_after_selecting_text_hfont =\n                    [&text_dc, &old_hfont, &clean_after_selecting_text_hbitmap]() noexcept\n                {\n                    ::SelectObject(text_dc, old_hfont);\n                    clean_after_selecting_text_hbitmap();\n                };\n\n                if (!Win32COLORREFVerifier::Verify(\n                        ::SetTextColor(text_dc, 0x00FFFFFF),\n                        clean_after_selecting_text_hfont))\n                {\n                    return 0;\n                }\n                if (!Win32COLORREFVerifier::Verify(\n                        ::SetBkColor(text_dc, 0x00000000),\n                        clean_after_selecting_text_hfont))\n                {\n                    return 0;\n                }\n                if (!Win32IntVerifier::Verify(\n                        ::SetBkMode(text_dc, OPAQUE),\n                        clean_after_selecting_text_hfont))\n                {\n                    return 0;\n                }\n                CRect modified_rect = ref_input_rect;\n                modified_rect.MoveToXY(0, 0);\n                auto&& replaced_dc_and_text_rect = std::make_tuple(\n                    text_dc,\n                    std::get<lpchText_index>(args_tuple),\n                    std::get<cchText_index>(args_tuple),\n                    modified_rect);\n                if (!Win32IntVerifier::Verify(\n                        ReplaceNthConsecutiveArgumentAndApply<hdc_index>(\n                            std::move(replaced_dc_and_text_rect), p_original_function,\n                            std::forward<DrawTextArgs>(draw_text_args)...),\n                        clean_after_selecting_text_hfont))\n                {\n                    return 0;\n                }\n                std::size_t width = modified_rect.right;\n                std::size_t height = modified_rect.bottom;\n                auto p_pixel_data = reinterpret_cast<BYTE*>(p_data);\n                auto color = ::GetTextColor(input_hdc);\n                if (!Win32COLORREFVerifier::Verify(\n                        color,\n                        clean_after_selecting_text_hfont))\n                {\n                    return 0;\n                }\n                BYTE r = GetRValue(color);\n                BYTE g = GetGValue(color);\n                BYTE b = GetBValue(color);\n                if (!Win32BOOLVerifier::Verify(\n                        ::GdiFlush(),\n                        clean_after_selecting_text_hfont))\n                {\n                    return 0;\n                }\n                // 切换显示器时可能引发越界访问（未证实）\n                // __try\n                for (std::size_t y = 0; y < height; ++y)\n                {\n                    for (std::size_t x = 0; x < width; ++x)\n                    {\n                        std::uint16_t rgb_sum;\n                        rgb_sum = p_pixel_data[0] + p_pixel_data[1] + p_pixel_data[2];\n                        if (rgb_sum == 0)\n                        {\n                            std::advance(p_pixel_data, 4);\n                        }\n                        else\n                        {\n                            *p_pixel_data++ = b;\n                            *p_pixel_data++ = g;\n                            *p_pixel_data++ = r;\n                            auto a = static_cast<BYTE>(rgb_sum * 0.334f);\n                            *p_pixel_data++ = a;\n                        }\n                    }\n                }\n                // __except(EXCEPTION_EXECUTE_HANDLER)\n                LPRECT p_input_rect = std::get<lprc_index>(args_tuple);\n                ::BLENDFUNCTION blend_function{\n                    AC_SRC_OVER,\n                    0,\n                    0xFF,\n                    AC_SRC_ALPHA};\n                auto width_i32 = static_cast<std::int32_t>(width);\n                auto height_i32 = static_cast<std::int32_t>(height);\n                if (!Win32IntVerifier::Verify(\n                        ::AlphaBlend(\n                            input_hdc,\n                            p_input_rect->left, p_input_rect->top,\n                            width_i32, height_i32,\n                            text_dc,\n                            0, 0,\n                            width_i32, height_i32,\n                            blend_function),\n                        clean_after_selecting_text_hfont))\n                {\n                    return 0;\n                }\n\n                clean_after_selecting_text_hfont();\n                return User32DrawTextManager::CUSTOM_SUCCESS;\n            }\n            return 0;\n        }\n\n        const CDrawTextReplacedFunction<User32DrawTextManager::A> on_draw_text_a_call{\n            [p_this = &on_draw_text_a_call](HDC hdc, LPCSTR lpchText, int cchText, LPRECT lprc, UINT format)\n            { return ReplacedDrawTextCommon(*p_this, hdc, lpchText, cchText, lprc, format); }};\n        const CDrawTextReplacedFunction<User32DrawTextManager::W> on_draw_text_w_call{\n            [p_this = &on_draw_text_w_call](HDC hdc, LPCWSTR lpchText, int cchText, LPRECT lprc, UINT format)\n            { return ReplacedDrawTextCommon(*p_this, hdc, lpchText, cchText, lprc, format); }};\n        const CDrawTextReplacedFunction<User32DrawTextManager::ExA> on_draw_text_exa_call{\n            [p_this = &on_draw_text_exa_call](HDC hdc, LPSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp)\n            { return ReplacedDrawTextCommon(*p_this, hdc, lpchText, cchText, lprc, format, lpdtp); }};\n        const CDrawTextReplacedFunction<User32DrawTextManager::ExW> on_draw_text_exw_call{\n            [p_this = &on_draw_text_exw_call](HDC hdc, LPWSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp)\n            { return ReplacedDrawTextCommon(*p_this, hdc, lpchText, cchText, lprc, format, lpdtp); }};\n    }\n\n    EnableAllReplaceFunctionGuard::~EnableAllReplaceFunctionGuard()\n    {\n        Details::on_draw_text_a_call.Disable();\n        Details::on_draw_text_w_call.Disable();\n        Details::on_draw_text_exa_call.Disable();\n        Details::on_draw_text_exw_call.Disable();\n\n        Details::on_draw_text_a_call.Reset();\n        Details::on_draw_text_w_call.Reset();\n        Details::on_draw_text_exa_call.Reset();\n        Details::on_draw_text_exw_call.Reset();\n    }\n\n    auto EnableAllReplaceFunction(Details::DrawTextReplacedFunctionState& ref_state) noexcept\n        -> class EnableAllReplaceFunctionGuard\n    {\n        Details::on_draw_text_a_call.Enable(ref_state);\n        Details::on_draw_text_w_call.Enable(ref_state);\n        Details::on_draw_text_exa_call.Enable(ref_state);\n        Details::on_draw_text_exw_call.Enable(ref_state);\n\n        return {};\n    }\n}\n\nvoid CD2D1BitmapCache::Cache::Update(Microsoft::WRL::ComPtr<ID2D1RenderTarget> p_render_target, HBITMAP hbitmap)\n{\n    auto p_updated_cache = m_cache_initializer(p_render_target, hbitmap);\n    m_cache = p_updated_cache;\n    m_init_timestamp = std::chrono::steady_clock::now();\n}\n\nbool CD2D1BitmapCache::HeapData::IsCacheExpire(const Cache& cache, std::chrono::steady_clock::time_point now)\n{\n    auto survival_time = std::chrono::duration_cast<std::chrono::seconds>(\n        now - cache.m_init_timestamp);\n    if (survival_time > m_cache_expire_interval)\n    {\n        return true;\n    }\n    return false;\n}\n\nCD2D1BitmapCache::CD2D1BitmapCache(ComPtr<ID2D1RenderTarget> p_render_target)\n    : m_p_render_target{p_render_target}\n{\n}\n\nCD2D1BitmapCache::~CD2D1BitmapCache()\n{\n    m_gc_thread.detach();\n}\n\nvoid CD2D1BitmapCache::RebindRenderTarget(ComPtr<ID2D1RenderTarget> p_render_target)\n{\n    m_p_render_target = p_render_target;\n    RecreateAllHBitmaps();\n}\n\nvoid CD2D1BitmapCache::AddHBitmap(HBITMAP hbitmap, CacheInitializer initializer)\n{\n    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_CACHE_MAP_AND_EXPIRE_INTERVAL(m_sp_data);\n    if (IsHBitmapExist(hbitmap))\n    {\n        return;\n    }\n    try\n    {\n        auto p_d2d1_bitmap = initializer(m_p_render_target, hbitmap);\n        m_sp_data->m_cache_map[hbitmap] = {\n            p_d2d1_bitmap,\n            std::chrono::steady_clock::now(),\n            initializer};\n    }\n    catch (CWICException& ex)\n    {\n        LogHResultException(ex);\n    }\n}\n\nvoid CD2D1BitmapCache::AddHBitmap(HBITMAP hbitmap)\n{\n    AddHBitmap(hbitmap, CD2D1BitmapCache::CreateD2D1BitmapFromHBitmap);\n}\n\nvoid CD2D1BitmapCache::RemoveHBitmap(HBITMAP hbitmap)\n{\n    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_CACHE_MAP_AND_EXPIRE_INTERVAL(m_sp_data);\n    auto it = m_sp_data->m_cache_map.find(hbitmap);\n    if (it != m_sp_data->m_cache_map.end())\n    {\n        m_sp_data->m_cache_map.erase(it);\n    }\n}\n\nvoid CD2D1BitmapCache::RecreateAllHBitmaps()\n{\n    CNullable<CD2D1Exception> nullable_d2d1exception{};\n\n    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_CACHE_MAP_AND_EXPIRE_INTERVAL(m_sp_data);\n    for (auto& cache : m_sp_data->m_cache_map)\n    {\n        auto hbitmap = cache.first;\n\n        try\n        {\n            cache.second.Update(m_p_render_target, cache.first);\n        }\n        catch (CWICException& ex)\n        {\n            // 一般是HBITMAP失效导致的问题，直接忽略\n            (void)ex;\n        }\n        catch (CD2D1Exception& ex)\n        {\n            // 只会保存最后一次异常\n            nullable_d2d1exception.Construct(std::move(ex));\n        }\n    }\n    if (nullable_d2d1exception)\n    {\n        throw nullable_d2d1exception.GetUnsafe();\n    }\n}\n\nauto CD2D1BitmapCache::CreateD2D1BitmapFromHBitmap(ComPtr<ID2D1RenderTarget> p_render_target, HBITMAP hbitmap)\n    -> ComPtr<ID2D1Bitmap>\n{\n    ComPtr<IWICBitmap> p_wic_bitmap{};\n    ThrowIfFailed<CWICException>(\n        CWICFactory::GetWIC()->CreateBitmapFromHBITMAP(\n            hbitmap,\n            NULL,\n            WICBitmapUsePremultipliedAlpha,\n            &p_wic_bitmap),\n        TRAFFICMONITOR_ERROR_STR(\"Call IWICImagingFactory::CreateBitmapFromHBITMAP failed.\"));\n\n    ComPtr<ID2D1Bitmap> result{};\n    ThrowIfFailed<CD2D1Exception>(\n        p_render_target->CreateBitmapFromWicBitmap(\n            p_wic_bitmap.Get(),\n            &result),\n        TRAFFICMONITOR_ERROR_STR(\"Call ID2D1RenderTarget::CreateBitmapFromWicBitmap failed.\"));\n\n    return result;\n}\n\nvoid CD2D1BitmapCache::GC()\n{\n    GCImpl(m_sp_data);\n}\n\nvoid CD2D1BitmapCache::SetGCInterval(const std::chrono::seconds interval)\n{\n    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_GC_INTERVAL(m_sp_data);\n    m_sp_data->m_gc_interval = interval;\n}\n\nvoid CD2D1BitmapCache::SetExpireInterval(const std::chrono::seconds interval)\n{\n    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_CACHE_MAP_AND_EXPIRE_INTERVAL(m_sp_data);\n    m_sp_data->m_cache_expire_interval = interval;\n}\n\nauto CD2D1BitmapCache::GetCachedBitmap(HBITMAP hbitmap)\n    -> ComPtr<ID2D1Bitmap>\n{\n    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_CACHE_MAP_AND_EXPIRE_INTERVAL(m_sp_data);\n    auto it = m_sp_data->m_cache_map.find(hbitmap);\n    if (it != m_sp_data->m_cache_map.end())\n    {\n        if (m_sp_data->IsCacheExpire(it->second))\n        {\n            it->second.Update(m_p_render_target, it->first);\n        }\n        return it->second.m_cache;\n    }\n    else\n    {\n        AddHBitmap(hbitmap);\n        return m_sp_data->m_cache_map[hbitmap].m_cache;\n    }\n}\n\nbool CD2D1BitmapCache::IsHBitmapExist(HBITMAP hbitmap) const\n{\n    auto existing_it = m_sp_data->m_cache_map.find(hbitmap);\n    if (existing_it == m_sp_data->m_cache_map.end())\n    {\n        return true;\n    }\n    return false;\n}\n\nvoid CD2D1BitmapCache::GCImpl(std::shared_ptr<HeapData> sp_data)\n{\n    auto now = std::chrono::steady_clock::now();\n    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_CACHE_MAP_AND_EXPIRE_INTERVAL(sp_data);\n    auto& ref_cache_map = sp_data->m_cache_map;\n    for (auto it = ref_cache_map.begin(); it != ref_cache_map.end();)\n    {\n        if (sp_data->IsCacheExpire(it->second, now))\n        {\n            it = ref_cache_map.erase(it);\n        }\n        else\n        {\n            ++it;\n        }\n    }\n}\n\nvoid CTaskBarDlgDrawCommon::ResetClippedStateIfSet()\n{\n    if (m_is_clipped)\n    {\n        m_p_device_context->PopAxisAlignedClip();\n    }\n}\n\nvoid CTaskBarDlgDrawCommon::Create(\n    CTaskBarDlgDrawCommonWindowSupport& taskbar_dlg_draw_common_window_support,\n    CD2D1DeviceContextWindowSupport& ref_d2d1_device_window_support,\n    const D2D1_SIZE_U size)\n{\n    const static auto transparent_black =\n        CRenderTarget::COLORREF_TO_D2DCOLOR(RGB(0, 0, 0), 0);\n    const static auto gdi_back_color =\n        CRenderTarget::COLORREF_TO_D2DCOLOR(RGB(0, 0, 0), DEFAULT_GDI_OP_TEXTURE_ALPHA);\n\n    m_p_window_support = &taskbar_dlg_draw_common_window_support;\n    m_p_window_support->Resize(size);\n    m_p_d2d1_device_context_support = &ref_d2d1_device_window_support;\n    m_p_device_context = m_p_d2d1_device_context_support->Resize(size);\n\n    m_p_device_context->BeginDraw();\n    m_p_device_context->SetTransform(D2D1::Matrix3x2F::Identity());\n    m_p_device_context->Clear(transparent_black);\n}\n\nauto CTaskBarDlgDrawCommon::GetD3D10Device1RecreateRequester()\n    -> std::function<bool(CHResultException& ex)>\n{\n    return [p_window_support = m_p_window_support](CHResultException& ex)\n    {\n        return DrawCommonHelper::HandleIfNeedRecreate(\n            ex,\n            [p_window_support]()\n            { p_window_support->RequestD3D10Device1Recreate(); });\n    };\n}\n\nauto CTaskBarDlgDrawCommon::GetD2D1DeviceRecreateRequester()\n    -> std::function<bool(CHResultException& ex)>\n{\n    return [p_d2d1_device_context_support = m_p_d2d1_device_context_support](CHResultException& ex)\n    {\n        return DrawCommonHelper::HandleIfD2D1DeviceNeedRecreate(\n            ex,\n            [&]()\n            { p_d2d1_device_context_support->RequestD2D1DeviceRecreate(ex.GetHResult()); });\n    };\n}\n\nauto CTaskBarDlgDrawCommon::GetDCompositionDeviceRecreateRequester()\n    -> std::function<bool(CHResultException& ex)>\n{\n    return [p_d2d1_device_context_support = m_p_d2d1_device_context_support](CHResultException& ex)\n    {\n        return DrawCommonHelper::HandleIfNeedRecreate(\n            ex,\n            [&]()\n            { p_d2d1_device_context_support->RequestDCompositionDeviceRecreate(ex.GetHResult()); });\n    };\n}\n\nauto CTaskBarDlgDrawCommon::Convert(CPoint point) noexcept\n    -> D2D1_POINT_2F\n{\n    D2D1_POINT_2F result{\n        static_cast<float>(point.x),\n        static_cast<float>(point.y)};\n    return result;\n}\n\nauto CTaskBarDlgDrawCommon::Convert(CRect rect) noexcept\n    -> D2D1_RECT_F\n{\n    D2D1_RECT_F result{\n        static_cast<float>(rect.left),\n        static_cast<float>(rect.top),\n        static_cast<float>(rect.right),\n        static_cast<float>(rect.bottom)};\n\n    return result;\n}\n\nCTaskBarDlgDrawCommon::~CTaskBarDlgDrawCommon()\n{\n    // Create的时候抛异常了\n    if (!m_p_window_support)\n    {\n        return;\n    }\n\n    ResetClippedStateIfSet();\n    try\n    {\n        if (m_gdi_interop_object.HasValue())\n        {\n            auto texture_size = m_p_window_support->GetSize();\n            auto data_size = texture_size.height * texture_size.width * 4;\n            auto& ref_gdi_interop_object = m_gdi_interop_object.Get();\n            m_p_window_support->ResizeGdiInteropPart();\n            ::GdiFlush();\n            m_p_window_support->SetGdiInteropTexture(\n                ref_gdi_interop_object.m_p_gdi_interop_hbitmap_data, texture_size);\n            auto waiter = m_p_window_support->DrawAlphaValueReduceEffect();\n\n            ThrowIfFailed<CD2D1Exception>(\n                m_p_device_context->Flush(),\n                TRAFFICMONITOR_ERROR_STR(\"Call ID2D1RenderTarget::Flush() failed.\"));\n\n            ThrowIfFailed<CD3D10Exception1>(\n                waiter.Wait(),\n                TRAFFICMONITOR_ERROR_STR(\"Draw call failed.\"));\n\n            D2D1_BITMAP_PROPERTIES d2d1_bitmap_properties{};\n            d2d1_bitmap_properties.pixelFormat.format = CTaskBarDlgDrawCommonWindowSupport::PIXEL_FORMAT;\n            d2d1_bitmap_properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;\n            d2d1_bitmap_properties.dpiX = CTaskBarDlgDrawCommonWindowSupport::DEFAULT_DPI;\n            d2d1_bitmap_properties.dpiY = CTaskBarDlgDrawCommonWindowSupport::DEFAULT_DPI;\n            auto p_gdi_interop_surface1 = m_p_window_support->GetGdiFinalTextureSurface();\n            ComPtr<ID2D1Bitmap> p_gdi_interop_bitmap{};\n            ThrowIfFailed<CD2D1Exception>(\n                m_p_device_context->CreateSharedBitmap(\n                    __uuidof(IDXGISurface1),\n                    p_gdi_interop_surface1.Get(),\n                    &d2d1_bitmap_properties,\n                    &p_gdi_interop_bitmap),\n                TRAFFICMONITOR_ERROR_STR(\"Create ID2D1Bitmap from IDXGISurface1 failed.\"));\n            m_p_device_context->DrawBitmap(p_gdi_interop_bitmap.Get());\n        }\n        // ! 注意：保证正常时EndDraw在不起用插件时仍然可以被调用，否则会导致D2D Begin/End调用不匹配，已经是第二次出错了。\n        ThrowIfFailed<CD2D1Exception>(\n            m_p_device_context->EndDraw(),\n            TRAFFICMONITOR_ERROR_STR(\"Call ID2D1RenderTarget::EndDraw() failed.\"));\n    }\n    catch (CHResultException& ex)\n    {\n        LogHResultException(ex);\n    }\n}\n\nvoid CTaskBarDlgDrawCommon::SetBackColor(COLORREF back_color, BYTE alpha)\n{\n    m_p_d2d1_device_context_support->SetBackColor(back_color, alpha);\n}\n\nvoid CTaskBarDlgDrawCommon::SetFont(CFont* pfont)\n{\n    m_p_window_support->SetFont(*pfont);\n}\n\nvoid CTaskBarDlgDrawCommon::DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align, bool draw_back_ground, bool multi_line, BYTE alpha)\n{\n    auto length = ::wcslen(lpszString);\n    auto length_u = static_cast<UINT>(length);\n    auto p_text_format = m_p_window_support->GetTextFormat();\n    // 备份状态\n    auto old_vertical_align = p_text_format->GetParagraphAlignment();\n    auto old_horizontal_align = p_text_format->GetTextAlignment();\n    auto old_word_warpping = p_text_format->GetWordWrapping();\n    // GDI版本的DrawWindowText文字对齐处理没看明白\n    if (multi_line)\n    {\n        // DT_EDITCONTROL | DT_WORDBREAK | DT_NOPREFIX\n        p_text_format->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP);\n    }\n    else\n    {\n        // DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX\n        p_text_format->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);            // DT_SINGLELINE\n        p_text_format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); // 此处仅设置竖直方向的中间对齐\n    }\n    switch (align)\n    {\n    case Alignment::LEFT:\n    {\n        p_text_format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);\n        break;\n    }\n    case Alignment::CENTER:\n    {\n        p_text_format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);\n        break;\n    }\n    case Alignment::RIGHT:\n    {\n        p_text_format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING);\n        break;\n    }\n    };\n\n    auto layout_rect = Convert(rect);\n    ComPtr<IDWriteTextLayout> p_text_layout{};\n    ThrowIfFailed<CDWriteException>(\n        CDWriteSupport::GetFactory()->CreateTextLayout(\n            lpszString,\n            length_u,\n            p_text_format.Get(),\n            layout_rect.right - layout_rect.left,\n            layout_rect.bottom - layout_rect.top,\n            &p_text_layout),\n        TRAFFICMONITOR_ERROR_STR(\"Function CreateTextLayout failed.\"));\n    DWRITE_OVERHANG_METRICS delta_size;\n    p_text_layout->GetOverhangMetrics(&delta_size);\n    D2D1_RECT_F rect_f{\n        delta_size.left > 0 ? delta_size.left + layout_rect.left : layout_rect.left,\n        delta_size.top > 0 ? delta_size.top + layout_rect.top : layout_rect.top,\n        delta_size.right > 0 ? delta_size.right + layout_rect.right : layout_rect.right,\n        delta_size.bottom > 0 ? delta_size.bottom + layout_rect.bottom : layout_rect.bottom};\n    if (draw_back_ground)\n    {\n        m_p_device_context->FillRectangle(rect_f, m_p_d2d1_device_context_support->GetRawBackSolidColorBruch());\n    }\n\n    m_p_d2d1_device_context_support->SetForeColor(color, alpha);\n    D2D1_DRAW_TEXT_OPTIONS options = D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_CLIP; // 不允许文字超出边界\n    if (theApp.m_taskbar_data.enable_colorful_emoji)\n        options |= D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT;\n    m_p_device_context->DrawTextLayout(\n        {layout_rect.left, layout_rect.top},\n        p_text_layout.Get(),\n        m_p_d2d1_device_context_support->GetRawForeSolidColorBruch(),\n        options);\n    // 恢复状态\n    p_text_format->SetParagraphAlignment(old_vertical_align);\n    p_text_format->SetTextAlignment(old_horizontal_align);\n    p_text_format->SetWordWrapping(old_word_warpping);\n}\n\nvoid CTaskBarDlgDrawCommon::SetDrawRect(CRect rect)\n{\n    ResetClippedStateIfSet();\n    D2D1_RECT_F d2d1_clip_rect;\n    d2d1_clip_rect.left = static_cast<float>(rect.left);\n    d2d1_clip_rect.top = static_cast<float>(rect.top);\n    d2d1_clip_rect.right = static_cast<float>(rect.right);\n    d2d1_clip_rect.bottom = static_cast<float>(rect.bottom);\n    m_p_device_context->PushAxisAlignedClip(d2d1_clip_rect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);\n    m_is_clipped = true;\n}\n\nvoid CTaskBarDlgDrawCommon::FillRect(CRect rect, COLORREF color, BYTE alpha)\n{\n    auto rect_f = Convert(rect);\n    m_p_d2d1_device_context_support->SetForeColor(color, alpha);\n    m_p_device_context->FillRectangle(rect_f, m_p_d2d1_device_context_support->GetRawForeSolidColorBruch());\n}\n\nvoid CTaskBarDlgDrawCommon::DrawRectOutLine(CRect rect, COLORREF color, int width, bool dot_line, BYTE alpha)\n{\n    rect.DeflateRect(width / 2, width / 2);\n    auto rect_f = Convert(rect);\n    m_p_d2d1_device_context_support->SetForeColor(color, alpha);\n    auto width_f = static_cast<float>(width);\n    if (dot_line)\n    {\n        m_p_device_context\n            ->DrawRectangle(\n                rect_f,\n                m_p_d2d1_device_context_support->GetRawForeSolidColorBruch(),\n                width_f,\n                m_p_window_support->GetRawPsDotLikeStyle());\n    }\n    else\n    {\n        m_p_device_context\n            ->DrawRectangle(\n                rect_f,\n                m_p_d2d1_device_context_support->GetRawForeSolidColorBruch(),\n                width_f);\n    }\n}\n\nvoid CTaskBarDlgDrawCommon::DrawLine(CPoint start_point, int height, COLORREF color, BYTE alpha)\n{\n    auto d2d1_start_point = Convert(start_point);\n    D2D1_POINT_2F d2d1_end_point{d2d1_start_point.x, d2d1_start_point.y - height};\n    m_p_d2d1_device_context_support->SetForeColor(color, alpha);\n    m_p_device_context->DrawLine(\n        d2d1_start_point,\n        d2d1_end_point,\n        m_p_d2d1_device_context_support->GetRawForeSolidColorBruch());\n}\n\nvoid CTaskBarDlgDrawCommon::SetTextColor(const COLORREF color, BYTE alpha)\n{\n    m_text_color = color;\n    m_p_d2d1_device_context_support->SetForeColor(color, alpha);\n}\n\nvoid CTaskBarDlgDrawCommon::DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode, BYTE alpha)\n{\n    auto p_d2d1_bitmap = m_p_d2d1_device_context_support->GetCachedBitmap(hbitmap);\n    if (!p_d2d1_bitmap)\n    {\n        CD2D1BitmapCache::CreateD2D1BitmapFromHBitmap(m_p_device_context, hbitmap);\n    }\n\n    float opacity = static_cast<float>(alpha) / 255.f;\n    D2D1_RECT_F draw_rect_f;\n    if (size.cx == 0 || size.cy == 0)\n    {\n        auto bitmap_size = p_d2d1_bitmap->GetSize();\n        draw_rect_f.left = static_cast<float>(start_point.x);\n        draw_rect_f.top = static_cast<float>(start_point.y);\n        draw_rect_f.right = static_cast<float>(start_point.x) + bitmap_size.width;\n        draw_rect_f.bottom = static_cast<float>(start_point.y) + bitmap_size.height;\n        m_p_device_context->DrawBitmap(p_d2d1_bitmap.Get(), draw_rect_f, opacity);\n        return;\n    }\n    switch (stretch_mode)\n    {\n    case StretchMode::STRETCH:\n    {\n        draw_rect_f.left = static_cast<float>(start_point.x);\n        draw_rect_f.top = static_cast<float>(start_point.y);\n        draw_rect_f.right = static_cast<float>(start_point.x + size.cx);\n        draw_rect_f.bottom = static_cast<float>(start_point.y + size.cy);\n        m_p_device_context->DrawBitmap(p_d2d1_bitmap.Get(), draw_rect_f, opacity);\n        return;\n    }\n    case StretchMode::FILL:\n    {\n        auto draw_size = size;\n        SetDrawRect(CRect(start_point, draw_size));\n\n        auto bitmap_size = p_d2d1_bitmap->GetPixelSize();\n        float bitmap_aspect_ratio, draw_rect_acpect_ratio; // 图像的宽高比、绘制大小的宽高比\n        bitmap_aspect_ratio = static_cast<float>(bitmap_size.width) / static_cast<float>(bitmap_size.height);\n        draw_rect_acpect_ratio = static_cast<float>(size.cx) / size.cy;\n        if (bitmap_aspect_ratio > draw_rect_acpect_ratio) // 如果图像的宽高比大于绘制区域的宽高比，则需要裁剪两边的图像\n        {\n            int image_width; // 按比例缩放后的宽度\n            image_width = bitmap_size.width * draw_size.cy / bitmap_size.height;\n            start_point.x -= ((image_width - draw_size.cx) / 2);\n            draw_size.cx = image_width;\n        }\n        else\n        {\n            int image_height; // 按比例缩放后的高度\n            image_height = bitmap_size.height * draw_size.cx / bitmap_size.width;\n            start_point.y -= ((image_height - draw_size.cy) / 2);\n            draw_size.cy = image_height;\n        }\n        break;\n    }\n    case StretchMode::FIT:\n    {\n        auto draw_size = p_d2d1_bitmap->GetPixelSize();\n        // 图像宽高比\n        float bitmap_aspect_ratio = static_cast<float>(draw_size.width) / static_cast<float>(draw_size.height);\n        float draw_rect_acpect_ratio = static_cast<float>(size.cx) / static_cast<float>(size.cy);\n        if (bitmap_aspect_ratio > draw_rect_acpect_ratio) // 如果图像的宽高比大于绘制区域的宽高比\n        {\n            draw_size.height = draw_size.height * size.cx / draw_size.width;\n            draw_size.width = size.cx;\n            start_point.y += ((size.cy - draw_size.height) / 2);\n        }\n        else\n        {\n            draw_size.width = draw_size.width * size.cy / draw_size.height;\n            draw_size.height = size.cy;\n            start_point.x += ((size.cx - draw_size.width) / 2);\n        }\n        break;\n    }\n    default:\n        break;\n    }\n    draw_rect_f.left = static_cast<float>(start_point.x);\n    draw_rect_f.top = static_cast<float>(start_point.y);\n    draw_rect_f.right = draw_rect_f.left + size.cx;\n    draw_rect_f.bottom = draw_rect_f.top + size.cy;\n    m_p_device_context->DrawBitmap(p_d2d1_bitmap.Get(), draw_rect_f, opacity);\n}\n\nCTaskBarDlgDrawBuffer::CTaskBarDlgDrawBuffer(\n    CTaskBarDlgDrawCommonWindowSupport& taskbar_dlg_draw_common_window_support,\n    CD2D1DeviceContextWindowSupport& ref_d2d1_device_context_support,\n    CSize size,\n    HWND hwnd)\n    : m_p_gdi_surface{ref_d2d1_device_context_support.GetRenderTargetSurfaceWhenUseDefault()},\n      m_size{size}, m_target_hwnd{hwnd}, m_ref_window_support{taskbar_dlg_draw_common_window_support}\n{\n}\n\nCTaskBarDlgDrawBuffer::~CTaskBarDlgDrawBuffer()\n{\n    // 类在初始化之前就被抛异常了\n    if (!m_p_gdi_surface)\n    {\n        return;\n    }\n\n    POINT start_location{0, 0};\n    HDC gdi_dc{NULL};\n    try\n    {\n        ThrowIfFailed<CD3D10Exception1>(\n            m_p_gdi_surface->GetDC(FALSE, &gdi_dc),\n            TRAFFICMONITOR_ERROR_STR(\"Get DC from IDXGISurface1 failed.\"));\n\n        UPDATELAYEREDWINDOWINFO update_window_info;\n        ::memset(&update_window_info, 0, sizeof(update_window_info));\n        update_window_info.cbSize = sizeof(update_window_info);\n        // update_window_info.hdcDst = NULL;\n        // update_window_info.pptDst = NULL; 不更新窗口位置\n        update_window_info.psize = &m_size;\n        update_window_info.hdcSrc = gdi_dc;\n        update_window_info.pptSrc = &start_location;\n        // update_window_info.crKey = 0;\n        update_window_info.pblend = GetDefaultBlendFunctionPointer();\n        update_window_info.dwFlags = ULW_ALPHA;\n        // m_update_window_info.prcDirty = NULL;\n        auto state = ::UpdateLayeredWindowIndirect(m_target_hwnd, &update_window_info);\n        if (state == 0)\n        {\n            auto error_code = ::GetLastError();\n            theApp.m_taskbar_data.update_layered_window_error_code = error_code;\n        }\n        RECT empty_rect{};\n        m_p_gdi_surface->ReleaseDC(&empty_rect);\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::ResetErrorCount();\n    }\n    catch (CD3D10Exception1& ex)\n    {\n        LogHResultException(ex);\n    }\n}\n\nauto CTaskBarDlgDrawBuffer::GetDefaultBlendFunctionPointer() noexcept\n    -> const ::PBLENDFUNCTION\n{\n    static ::BLENDFUNCTION result{\n        AC_SRC_OVER,\n        0,\n        0xFF,\n        AC_SRC_ALPHA};\n    return &result;\n}\n\nCTaskBarDlgDrawCommon::CGdiInteropObject::CGdiInteropObject(D2D1_SIZE_U size)\n{\n    m_gdi_interop_cdc.CreateCompatibleDC(NULL);\n    auto bitmap_info = TaskBarDlgUser32DrawTextHook::Details::GetArgb32BitmapInfo(size.width, size.height);\n    m_gdi_interop_hbitmap = ::CreateDIBSection(\n        m_gdi_interop_cdc,\n        &bitmap_info,\n        DIB_RGB_COLORS,\n        &m_p_gdi_interop_hbitmap_data,\n        NULL,\n        0);\n    m_gdi_interop_old_hbitmap = m_gdi_interop_cdc.SelectObject(m_gdi_interop_hbitmap);\n    ::SetBkColor(m_gdi_interop_cdc, TRANSPARENT);\n    auto gdi_no_modified_alpha_dc = DrawCommonHelper::Get1x1AlphaEqual1DC();\n    ::BLENDFUNCTION blend_function{\n        AC_SRC_OVER,\n        0,\n        0xFF,\n        AC_SRC_ALPHA};\n    ::AlphaBlend(\n        m_gdi_interop_cdc,\n        0, 0,\n        size.width, size.height,\n        gdi_no_modified_alpha_dc,\n        0, 0,\n        1, 1,\n        blend_function);\n}\n\nCTaskBarDlgDrawCommon::CGdiInteropObject::~CGdiInteropObject()\n{\n    m_gdi_interop_cdc.SelectObject(m_gdi_interop_old_hbitmap);\n    ::DeleteObject(m_gdi_interop_hbitmap);\n}\n\nCTaskBarDlgDrawBufferUseDComposition::CTaskBarDlgDrawBufferUseDComposition(CD2D1DeviceContextWindowSupport& ref_d2d1_device_context_support)\n{\n    m_p_d2d1_device_context_support = &ref_d2d1_device_context_support;\n}\n\nCTaskBarDlgDrawBufferUseDComposition::~CTaskBarDlgDrawBufferUseDComposition()\n{\n    if (!m_p_d2d1_device_context_support)\n    {\n        return;\n    }\n    try\n    {\n        m_p_d2d1_device_context_support->PresentWhenUseDComposition();\n        DrawCommonHelper::DefaultD2DDrawCommonExceptionHandler::ResetErrorCount();\n    }\n    catch (CHResultException& ex)\n    {\n        LogHResultException(ex);\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/TaskBarDlgDrawCommon.h",
    "content": "﻿#pragma once\n#include <tuple>\n#include <unordered_map>\n#include <chrono>\n#include <mutex>\n#include <thread>\n#include <type_traits>\n#include <initializer_list>\n#include \"IDrawCommon.h\"\n#include \"Common.h\"\n#include \"D3D10Support1.h\"\n#include \"D2D1Support.h\"\n#include \"DCompositionSupport.h\"\n#include \"Dxgi1Support2.h\"\n#include \"Image2DEffect.h\"\n#include \"Nullable.hpp\"\n#include \"DrawTextManager.h\"\n\nvoid LogWin32ApiErrorMessage(DWORD error_code) noexcept;\n\nnamespace DrawCommonHelper\n{\n    void LogDeviceRecreateReason(HRESULT hr);\n\n    namespace Details\n    {\n        template <typename T, T First>\n        constexpr bool CompareEqOr(const T input)\n        {\n            return input == First;\n        }\n        template <typename T, T First, T... Others, typename... PlaceHolder>\n        constexpr auto CompareEqOr(const T input, PlaceHolder...)\n            -> std::enable_if_t<sizeof...(PlaceHolder) == 0, bool>\n        {\n            return input == First || CompareEqOr<T, Others...>(input);\n        }\n    } // namespace Details\n\n    template <HRESULT... HRESULTs>\n    struct hresult_sequence\n    {\n        constexpr static bool CompareEqOr(const HRESULT input)\n        {\n            return Details::CompareEqOr<HRESULT, HRESULTs...>(input);\n        }\n    };\n    template <class T>\n    struct is_hresult_sequence : public std::false_type\n    {\n    };\n    template <HRESULT... HRESULTs>\n    struct is_hresult_sequence<hresult_sequence<HRESULTs...>> : public std::true_type\n    {\n    };\n    template <class HResultSequence, class Func, class = std::enable_if_t<is_hresult_sequence<HResultSequence>{}>>\n    bool HandleIfNeedRecreate(CHResultException& ref_ex, Func handler)\n    {\n        auto hr = ref_ex.GetHResult();\n        if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET || HResultSequence::CompareEqOr(hr))\n        {\n            handler();\n            return true;\n        }\n        return false;\n    }\n    template <class Func>\n    bool HandleIfNeedRecreate(CHResultException& ref_ex, Func handler)\n    {\n        auto hr = ref_ex.GetHResult();\n        if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)\n        {\n            handler();\n            return true;\n        }\n        return false;\n    }\n\n    constexpr std::uint32_t MAX_D2D1_RENDER_ERROR_COUNT = 77;\n    template <class Func>\n    bool HandleIfD2D1DeviceNeedRecreate(CHResultException& ref_ex, Func handler)\n    {\n        return HandleIfNeedRecreate<hresult_sequence<D2DERR_RECREATE_TARGET, D2DERR_WRONG_STATE>>(ref_ex, handler);\n    }\n    class DefaultD2DDrawCommonExceptionHandler\n    {\n    private:\n        CHResultException& m_ref_ex;\n        static std::uint32_t m_error_count;\n\n    public:\n        DefaultD2DDrawCommonExceptionHandler(CHResultException& ex) noexcept;\n        DefaultD2DDrawCommonExceptionHandler(const DefaultD2DDrawCommonExceptionHandler&) = delete;\n        DefaultD2DDrawCommonExceptionHandler& operator=(const DefaultD2DDrawCommonExceptionHandler&) = delete;\n        DefaultD2DDrawCommonExceptionHandler* operator&() = delete;\n\n        static void ResetErrorCount();\n        static void HandleErrorCountIncrement();\n        static void IncreaseErrorCountManually();\n        /**\n         * @brief 使用自定义处理函数在LogHResultException(m_ref_ex)语句后接受m_ref_ex进行处理\n         *\n         * @tparam Func 形如bool (CHResultException&)的可调用类型\n         * @param handler 自定义处理函数，接受CHResultException&，返回true代表不增加D2D渲染的错误计数，返回false代表含义则相反。\n         例如，在发现需要重新初始化设备后，请求重新初始化设备并返回true\n         */\n        template <class Func>\n        void operator()(Func handler)\n        {\n            LogHResultException(m_ref_ex);\n            if (handler(m_ref_ex))\n            {\n                return;\n            }\n            HandleErrorCountIncrement();\n        }\n        void operator()()\n        {\n            LogHResultException(m_ref_ex);\n            HandleErrorCountIncrement();\n        }\n    };\n    HDC Get1x1AlphaEqual1DC();\n}\n\nclass CTaskBarDlgDrawCommonSupport\n{\nprivate:\n    CD3D10Device1 m_d3d10_device1{};\n    CD2D1Device m_d2d1_device{};\n    CDCompositionDevice m_dcomposition_device{};\n    Microsoft::WRL::ComPtr<ID2D1StrokeStyle> m_p_ps_dot_like_style{};\n\n    bool IsAllDevicesRecreatedByThisFunction();\n    void InternalRecreateD3D10Device1();\n\npublic:\n    CTaskBarDlgDrawCommonSupport();\n    ~CTaskBarDlgDrawCommonSupport() = default;\n\n    auto GetD3D10Device1() noexcept\n        -> CD3D10Device1&;\n    auto GetD2D1Device() noexcept\n        -> CD2D1Device&;\n    auto GetDCompositionDevice() noexcept\n        -> CDCompositionDevice&;\n    auto GetPsDotLikeStyle() noexcept\n        -> Microsoft::WRL::ComPtr<ID2D1StrokeStyle>;\n    void RecreateAll();\n    void RecreateD3D10Device1(const HRESULT recreate_reason = S_OK);\n    void RecreateD2D1Device(const HRESULT recreate_reason = S_OK);\n    void RecreateDCompositionDevice(const HRESULT recreate_reason = S_OK);\n    static bool CheckSupport() noexcept;\n};\n\ntemplate <class T>\nbool IsBitwiseEquality(T& lhs, T& rhs) noexcept\n{\n    auto p_lhs = std::addressof(lhs);\n    auto p_rhs = std::addressof(rhs);\n    constexpr auto size = sizeof(T);\n\n    return ::memcmp(p_lhs, p_rhs, size) == 0;\n}\n\n// 0.0039215686 = 1 / 255\n#define TRAFFICMONITOR_ONE_IN_255_NUM 0.0039215686\n// 0.0039215686 + 0.0000784314\n#define TRAFFICMONITOR_ONE_IN_255_NUM_CEIL 0.004\n#define TRAFFICMONITOR_ONE_IN_255_NUM_FLOOR 0.0038431372\n#define TRAFFICMONITOR_ONE_IN_255_CEIL TRAFFICMONITOR_STR(TRAFFICMONITOR_ONE_IN_255_NUM_CEIL)\n#define TRAFFICMONITOR_ONE_IN_255_FLOOR TRAFFICMONITOR_STR(TRAFFICMONITOR_ONE_IN_255_NUM_FLOOR)\n\n/**\n * @brief 每次循环都会在最开始时调用Resize()。\n * 此类在调用Resize前是部分初始化状态，此时调用其中的成员会发生未定义行为\n *\n */\nclass CTaskBarDlgDrawCommonWindowSupport\n{\nprivate:\n    class CD3DGdiInteropHelper final : public CDeviceResource<CD3D10Device1>\n    {\n        friend CTaskBarDlgDrawCommonWindowSupport;\n\n        using Base = CDeviceResource<CD3D10Device1>;\n        using Base::DeviceType;\n\n    private:\n        DeviceType m_p_device1{};\n        Microsoft::WRL::ComPtr<ID3D10Texture2D> m_p_gdi_initial_texture{};\n        Microsoft::WRL::ComPtr<IDXGISurface1> m_p_gdi_initial_surface{};\n        Microsoft::WRL::ComPtr<ID3D10Texture2D> m_p_gdi_final_texture{};\n        Microsoft::WRL::ComPtr<IDXGISurface1> m_p_gdi_final_surface{};\n        CImage2DEffect m_alpha_value_effect;\n        bool m_is_p_device1_recreated{false};\n\n        static auto CreateDefaultTexture(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1, const D2D1_SIZE_U size)\n            -> Microsoft::WRL::ComPtr<ID3D10Texture2D>;\n        static auto CreateCpuWriteableTexture(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1, const D2D1_SIZE_U size)\n            -> Microsoft::WRL::ComPtr<ID3D10Texture2D>;\n        static auto GetPsAlphaValueReducer() noexcept\n            -> Microsoft::WRL::ComPtr<ID3D10Blob>;\n\n    public:\n        CD3DGdiInteropHelper(CD3D10Device1& ref_device);\n        ~CD3DGdiInteropHelper() = default;\n\n        void OnDeviceRecreate(DeviceType p_new_device) noexcept override;\n\n        bool HandleDeviceRecreationIfNecessary();\n        void Resize(D2D1_SIZE_U size);\n        auto GetRenderTargetSurface()\n            -> Microsoft::WRL::ComPtr<IDXGISurface>;\n    };\n    class CDWriteHelper\n    {\n    private:\n        Microsoft::WRL::ComPtr<IDWriteTextFormat> m_p_text_format{};\n        HFONT m_h_last_font{};\n        LOGFONTW m_last_font{};\n\n    public:\n        CDWriteHelper() = default;\n        ~CDWriteHelper() = default;\n\n        void SetFont(HFONT h_font);\n        auto GetFont() noexcept\n            -> HFONT;\n        auto GetTextFormat() noexcept\n            -> Microsoft::WRL::ComPtr<IDWriteTextFormat>;\n    };\n\n    D2D1_SIZE_U m_size{0, 0};\n    CD3DGdiInteropHelper m_d3d_gdi_interop_helper;\n    CDWriteHelper m_dwrite_helper{};\n    CTaskBarDlgDrawCommonSupport& m_ref_taskbardlg_draw_common_support;\n    DWORD m_update_layered_window_error_code{0};\n    bool m_is_size_updated{true};\n\npublic:\n    constexpr static float DEFAULT_DPI = 96.f;\n    constexpr static auto PIXEL_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM;\n\n    explicit CTaskBarDlgDrawCommonWindowSupport(CTaskBarDlgDrawCommonSupport& ref_taskbdlg_draw_common_support);\n    ~CTaskBarDlgDrawCommonWindowSupport() = default;\n\n    void Resize(const D2D1_SIZE_U size);\n    void ResizeGdiInteropPart();\n    void SetFont(HFONT h_font);\n    /**\n     * @brief 从内存复制图片到显存中并作为D2D和GDI互操作时使用的临时缓存，并默认格式为BGRA\n     *\n     * @param p_data 内存图片的地址\n     * @param size 内存图片的大小\n     */\n    void SetGdiInteropTexture(void* p_data, D2D1_SIZE_U size);\n    auto GetTextFormat() noexcept\n        -> Microsoft::WRL::ComPtr<IDWriteTextFormat>;\n    auto GetRawPsDotLikeStyle() noexcept\n        -> ID2D1StrokeStyle*;\n    auto GetGdiInitalTextureSurface() noexcept\n        -> Microsoft::WRL::ComPtr<IDXGISurface1>;\n    auto GetGdiFinalTextureSurface() noexcept\n        -> Microsoft::WRL::ComPtr<IDXGISurface1>;\n    auto DrawAlphaValueReduceEffect() noexcept\n        -> CD3D10DrawCallWaiter;\n    auto GetSize() const noexcept\n        -> D2D1_SIZE_U;\n    auto GetFont() noexcept\n        -> HFONT;\n    void RequestD3D10Device1Recreate();\n};\n\n/**\n * @brief 此类具有和CTaskBarDlgDrawCommonWindowSupport相似的逻辑，\n 必须先SetWorkingDevice，再进行Resize才可以视为完全初始化的状态。\n 在没有Resize前，都视为未初始化的状态，此时不应该调用其它成员函数。\n *\n */\nclass CD2D1DeviceContextWindowSupport\n{\npublic:\n    class CD2D1DeviceContextHelper : public CDeviceResource<CD2D1Device>\n    {\n        using Base = CDeviceResource<CD2D1Device>;\n        using Base::DeviceType;\n\n    private:\n        DeviceType m_p_device{};\n        Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_p_device_context{};\n        Microsoft::WRL::ComPtr<ID2D1Bitmap1> m_p_d2d_render_target_bitmap{};\n        Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_p_foreground_color_brush{};\n        Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_p_background_color_brush{};\n        std::weak_ptr<class CD2D1BitmapCache> m_wp_bitmap_cache{};\n        D2D1_COLOR_F m_foreground_color{D2D1::ColorF::Black};\n        D2D1_COLOR_F m_background_color{D2D1::ColorF::Black};\n        bool m_need_recreate{false};\n\n        void Reinitialize();\n\n    public:\n        CD2D1DeviceContextHelper(CD2D1Device& ref_device);\n        bool HandleDeviceRecreationIfNecessary();\n        void SetBackColor(COLORREF color, BYTE alpha) noexcept;\n        auto GetRawBackSolidColorBruch() noexcept\n            -> ID2D1SolidColorBrush*;\n        void SetForeColor(COLORREF color, BYTE alpha) noexcept;\n        auto GetRawForeSolidColorBruch() noexcept\n            -> ID2D1SolidColorBrush*;\n        void OnDeviceRecreate(DeviceType p_new_device) noexcept override;\n        void RebindD2D1BitmapCache(std::weak_ptr<class CD2D1BitmapCache> wp_cache);\n        void RebindRenderTargetSurface(Microsoft::WRL::ComPtr<IDXGISurface> p_surface);\n        void Reset();\n        auto GetCachedBitmap(HBITMAP hbitmap) const\n            -> Microsoft::WRL::ComPtr<ID2D1Bitmap>;\n        auto GetDeviceContext() const\n            -> Microsoft::WRL::ComPtr<ID2D1DeviceContext>;\n    };\n    class CDCompositionHelper : public CDeviceResource<CDCompositionDevice>,\n                                public CDeviceResource<CD3D10Device1>\n    {\n        using CDCompositionResourceBase = CDeviceResource<CDCompositionDevice>;\n        using CDCompositionDeviceType = typename CDCompositionResourceBase::DeviceType;\n        using CD3D10Device1ResourceBase = CDeviceResource<CD3D10Device1>;\n        using CD3D10Device1Type = typename CD3D10Device1ResourceBase::DeviceType;\n\n    private:\n        // DComposition Part Begin\n        CDCompositionDeviceType m_p_composition_device{};\n        Microsoft::WRL::ComPtr<IDCompositionTarget> m_p_target{};\n        Microsoft::WRL::ComPtr<IDCompositionVisual> m_p_visual{};\n        // D3D10Device1 Part Begin\n        CD3D10Device1Type m_p_d3d10_device1{};\n        Microsoft::WRL::ComPtr<IDXGISwapChain1> m_p_swap_chain1{};\n        HWND m_hwnd{};\n        D2D1_SIZE_U m_size{};\n        bool m_need_recreate_dcomposition_device{false};\n        bool m_need_recreate_d3d10_device1{false};\n\n        void InitializeSwapChain(const D2D1_SIZE_U size);\n        void RebindSwapChain(Microsoft::WRL::ComPtr<IDXGISwapChain1> p_swap_chain1);\n        void ReinitializeDCompositionPart();\n        void ReinitializeD3D10Device1Part();\n\n    public:\n        CDCompositionHelper(CDCompositionDevice& ref_dcomposition_device, CD3D10Device1& ref_d3d10_device1, HWND hwnd);\n        void OnDeviceRecreate(CDCompositionDeviceType p_new_composition_device) noexcept override;\n        void OnDeviceRecreate(CD3D10Device1Type p_new_d3d10_device1) noexcept override;\n        bool HandleDeviceRecreationIfNecessary();\n        /**\n         * @brief 执行此函数前，必须调用CD2D1DeviceContextHelper::Reset()释放持有交换链的ID2D1Bitmap1和ID2D1DeviceContext\n         *\n         * @param size 新的交换链大小\n         * @return Microsoft::WRL::ComPtr<IDXGISurface> 使用Resize后交换链创建的IDXGISurface\n         */\n        auto Resize(const D2D1_SIZE_U size)\n            -> Microsoft::WRL::ComPtr<IDXGISurface>;\n        void Present();\n        auto GetD3D10Device1()\n            -> Microsoft::WRL::ComPtr<ID3D10Device1>;\n        bool IsInvalid() const;\n    };\n    class CD3DHelper : public CDeviceResource<CD3D10Device1>\n    {\n        using Base = CDeviceResource<CD3D10Device1>;\n        using Base::DeviceType;\n\n    private:\n        Microsoft::WRL::ComPtr<ID3D10Device1> m_p_device1{};\n        Microsoft::WRL::ComPtr<ID3D10Texture2D> m_p_render_target_texture{};\n        Microsoft::WRL::ComPtr<IDXGISurface1> m_p_render_target_surface{};\n        bool m_need_recreate{false};\n\n        static auto CreateGdiCompatibleTexture(Microsoft::WRL::ComPtr<ID3D10Device1> p_device1, const D2D1_SIZE_U size)\n            -> Microsoft::WRL::ComPtr<ID3D10Texture2D>;\n\n    public:\n        CD3DHelper(CD3D10Device1& ref_device);\n        auto Resize(const D2D1_SIZE_U size)\n            -> Microsoft::WRL::ComPtr<IDXGISurface>;\n        bool HandleDeviceRecreationIfNecessary();\n        void OnDeviceRecreate(DeviceType p_new_device) noexcept override;\n        auto GetRenderTargetSurface()\n            -> Microsoft::WRL::ComPtr<IDXGISurface1>;\n        auto GetD3D10Device1()\n            -> Microsoft::WRL::ComPtr<ID3D10Device1>;\n    };\n    using VariantStorage = AlignedUnionStorage<\n        CNullable<CDCompositionHelper>,\n        CNullable<CD3DHelper>>;\n\n    CTaskBarDlgDrawCommonSupport& m_ref_task_bar_dlg_draw_common_support;\n    D2D1_SIZE_U m_size{0, 0};\n    CD2D1DeviceContextHelper m_d2d1_device_context_helper;\n    DrawCommonHelper::RenderType m_render_type{DrawCommonHelper::RenderType::D2D1};\n    bool m_is_initialized{false};\n    VariantStorage m_impl_storage;\n\n    void Dispatch(std::initializer_list<std::tuple<DrawCommonHelper::RenderType, std::function<void()>>> initializer_list)\n    {\n        DrawCommonHelper::RenderType render_type;\n        std::function<void()> function;\n        for (auto&& item : initializer_list)\n        {\n            std::tie(render_type, function) = item;\n            if (render_type == m_render_type)\n            {\n                return function();\n            }\n        }\n    }\n\n    template <class R>\n    auto Dispatch(std::initializer_list<std::tuple<DrawCommonHelper::RenderType, std::function<R()>>> initializer_list)\n        -> CNullable<R>\n    {\n        DrawCommonHelper::RenderType render_type;\n        std::function<R()> function;\n        CNullable<R> result{};\n        for (auto&& item : initializer_list)\n        {\n            std::tie(render_type, function) = item;\n            if (render_type == m_render_type)\n            {\n                result.Construct(function());\n                return result;\n            }\n        }\n        return result;\n    }\n    template <class T>\n    auto GetStorageAs()\n        -> std::add_lvalue_reference_t<T>\n    {\n        return reinterpret_cast<std::add_lvalue_reference_t<T>>(m_impl_storage);\n    }\n    auto GetNullableDCompositionHelper()\n        -> CNullable<CDCompositionHelper>&;\n    auto GetNullableD3DHelper()\n        -> CNullable<CD3DHelper>&;\n    void DestroyStorage();\n\npublic:\n    CD2D1DeviceContextWindowSupport(CTaskBarDlgDrawCommonSupport& ref_task_bar_dlg_draw_common_support);\n    ~CD2D1DeviceContextWindowSupport();\n    auto SetWorkingDevice(CDCompositionDevice& ref_dcomposition_device, CD3D10Device1& ref_d3d10_device1, HWND hwnd)\n        -> CDCompositionHelper&;\n    auto SetWorkingDevice(CD3D10Device1& ref_device1)\n        -> CD3DHelper&;\n    auto Resize(const D2D1_SIZE_U size)\n        -> Microsoft::WRL::ComPtr<ID2D1DeviceContext>;\n    /**\n     * @brief 当m_render_type = DrawCommonHelper::RenderType::D2D1_WITH_DCOMPOSITION时才会执行\n     *\n     */\n    void PresentWhenUseDComposition();\n    /**\n     * @brief 当m_render_type = DrawCommonHelper::RenderType::D2D1时才返回非空值\n     *\n     * @return Microsoft::WRL::ComPtr<IDXGISurface1>\n     */\n    auto GetRenderTargetSurfaceWhenUseDefault()\n        -> Microsoft::WRL::ComPtr<IDXGISurface1>;\n    void RebindD2D1BitmapCache(std::weak_ptr<class CD2D1BitmapCache> wp_cache);\n    void SetBackColor(COLORREF color, BYTE alpha) noexcept;\n    auto GetRawBackSolidColorBruch() noexcept\n        -> ID2D1SolidColorBrush*;\n    auto SetForeColor(COLORREF color, BYTE alpha) noexcept\n        -> CD2D1DeviceContextWindowSupport*;\n    auto GetRawForeSolidColorBruch() noexcept\n        -> ID2D1SolidColorBrush*;\n    auto GetCachedBitmap(HBITMAP hbitmap)\n        -> Microsoft::WRL::ComPtr<ID2D1Bitmap>;\n    void RequestD3D10Device1Recreate();\n    void RequestD2D1DeviceRecreate(const HRESULT hr);\n    void RequestDCompositionDeviceRecreate(const HRESULT hr);\n};\n\nnamespace TaskBarDlgUser32DrawTextHook\n{\n    class EnableAllReplaceFunctionGuard;\n    namespace Details\n    {\n        auto GetArgb32BitmapInfo(CRect rect) noexcept\n            -> ::BITMAPINFO;\n        auto GetArgb32BitmapInfo(LONG width, LONG height) noexcept\n            -> ::BITMAPINFO;\n\n        struct DrawTextReplacedFunctionState\n        {\n            HDC m_on_draw_text_call_matched_hdc{NULL};\n        };\n\n        template <class DrawTextFunctionNamespace>\n        class CDrawTextReplacedFunction\n        {\n            friend auto EnableAllReplaceFunction(Details::DrawTextReplacedFunctionState& ref_state) noexcept\n                -> ::TaskBarDlgUser32DrawTextHook::EnableAllReplaceFunctionGuard;\n\n        private:\n            using ReplacedFunction = typename DrawTextFunctionNamespace::ReplacedFunction;\n\n            ReplacedFunction m_p_replaced_function;\n\n        public:\n            mutable DrawTextReplacedFunctionState m_state{};\n\n            CDrawTextReplacedFunction(ReplacedFunction replaced_function)\n                : m_p_replaced_function{replaced_function}\n            {\n            }\n\n            void Enable(const DrawTextReplacedFunctionState& state) const\n            {\n                m_state = state;\n\n                auto draw_text_function_manager_state =\n                    typename DrawTextFunctionNamespace::State{true, m_p_replaced_function};\n                DrawTextFunctionNamespace::SetState(draw_text_function_manager_state);\n            }\n            void Disable() const\n            {\n                DrawTextFunctionNamespace::SetEnable(false);\n            }\n            void Reset() const\n            {\n                Destroy(&m_state);\n                EmplaceAt(&m_state);\n            }\n        };\n\n        template <std::size_t N, std::size_t... Indexes>\n        constexpr auto AddNToTheSequence(std::index_sequence<Indexes...>)\n            -> std::index_sequence<(Indexes + N)...>\n        {\n            return {};\n        }\n\n#define TRAFFICMONITOR_MAKE_TAG_TYPE(tag_name) \\\n    struct tag_name                            \\\n    {                                          \\\n    };\n\n        TRAFFICMONITOR_MAKE_TAG_TYPE(WhenTupleAtFirst)\n        TRAFFICMONITOR_MAKE_TAG_TYPE(WhenTupleAtLast)\n        TRAFFICMONITOR_MAKE_TAG_TYPE(WhenTupleAtMiddle)\n\n        template <class NthTuple, class Func, class Tuple,\n                  std::size_t... IndexN, std::size_t... IndexAfterN>\n        constexpr auto ReplaceNthConsecutiveArgumentAndApplyImpl(\n            NthTuple&& nth_tuple, Func&& func, Tuple&& tuple, WhenTupleAtFirst,\n            std::index_sequence<IndexN...>, std::index_sequence<IndexAfterN...>)\n        {\n            return func(std::get<IndexN>(nth_tuple)..., std::get<IndexAfterN>(tuple)...);\n        }\n\n        template <class NthTuple, class Func, class Tuple,\n                  std::size_t... IndexBeforeN, std::size_t... IndexN>\n        constexpr auto ReplaceNthConsecutiveArgumentAndApplyImpl(\n            NthTuple&& nth_tuple, Func&& func, Tuple&& tuple, WhenTupleAtLast,\n            std::index_sequence<IndexBeforeN...>, std::index_sequence<IndexN...>)\n        {\n            return func(std::get<IndexBeforeN>(tuple)..., std::get<IndexN>(nth_tuple)...);\n        }\n\n        template <class NthTuple, class Func, class Tuple,\n                  std::size_t... IndexBeforeN, std::size_t... IndexN, std::size_t... IndexAfterN>\n        constexpr auto ReplaceNthConsecutiveArgumentAndApplyImpl(\n            NthTuple&& nth_tuple, Func&& func, Tuple&& tuple, WhenTupleAtMiddle,\n            std::index_sequence<IndexBeforeN...>, std::index_sequence<IndexN...>, std::index_sequence<IndexAfterN...>)\n        {\n            return func(std::get<IndexBeforeN>(tuple)..., std::get<IndexN>(nth_tuple)..., std::get<IndexAfterN>(tuple)...);\n        }\n\n        template <std::int64_t N, std::int64_t delta_size, class Checker = void>\n        struct ReplaceNthConsecutiveArgumentAndApplyDispatcher;\n        template <std::int64_t delta_size>\n        struct ReplaceNthConsecutiveArgumentAndApplyDispatcher<0, delta_size, std::enable_if_t<true>>\n        {\n            template <class NthTuple, class Func, class Tuple>\n            constexpr static auto Dispatch(NthTuple&& nth_tuple, Func&& func, Tuple&& tuple)\n            {\n                constexpr std::int64_t nth_tuple_size = std::tuple_size<NthTuple>::value;\n                constexpr std::int64_t function_args_size = std::tuple_size<Tuple>::value;\n\n                return ReplaceNthConsecutiveArgumentAndApplyImpl(\n                    std::forward<NthTuple>(nth_tuple), std::forward<Func>(func), std::forward<Tuple>(tuple), WhenTupleAtFirst{},\n                    std::make_index_sequence<nth_tuple_size>{}, AddNToTheSequence<nth_tuple_size>(std::make_index_sequence<function_args_size - nth_tuple_size>{}));\n            }\n        };\n        template <std::int64_t N, std::int64_t delta_size>\n        struct ReplaceNthConsecutiveArgumentAndApplyDispatcher<N, delta_size, std::enable_if_t<(N != 0 && delta_size > 0)>>\n        {\n            template <class NthTuple, class Func, class Tuple>\n            constexpr static auto Dispatch(NthTuple&& nth_tuple, Func&& func, Tuple&& tuple)\n            {\n                constexpr std::int64_t nth_tuple_size = std::tuple_size<NthTuple>::value;\n\n                return ReplaceNthConsecutiveArgumentAndApplyImpl(\n                    std::forward<NthTuple>(nth_tuple), std::forward<Func>(func), std::forward<Tuple>(tuple), WhenTupleAtMiddle{},\n                    std::make_index_sequence<N>{}, std::make_index_sequence<nth_tuple_size>{}, AddNToTheSequence<N + nth_tuple_size>(std::make_index_sequence<delta_size>{}));\n            }\n        };\n        template <std::int64_t N, std::int64_t delta_size>\n        struct ReplaceNthConsecutiveArgumentAndApplyDispatcher<N, delta_size, std::enable_if_t<N != 0 && !(delta_size > 0)>>\n        {\n            template <class NthTuple, class Func, class Tuple>\n            constexpr static auto Dispatch(NthTuple&& nth_tuple, Func&& func, Tuple&& tuple)\n            {\n                constexpr std::int64_t nth_tuple_size = std::tuple_size<NthTuple>::value;\n\n                return ReplaceNthConsecutiveArgumentAndApplyImpl(\n                    std::forward<NthTuple>(nth_tuple), std::forward<Func>(func), std::forward<Tuple>(tuple), WhenTupleAtLast{},\n                    std::make_index_sequence<N>{}, std::make_index_sequence<nth_tuple_size>{});\n            }\n        };\n\n        template <std::int64_t N, class NthTuple, class Func, class... Args>\n        constexpr auto ReplaceNthConsecutiveArgumentAndApply(NthTuple&& nth_tuple, Func&& func, Args&&... args)\n        {\n            constexpr std::int64_t size = sizeof...(Args);\n            constexpr std::int64_t nth_tuple_size = std::tuple_size<NthTuple>::value;\n            static_assert(size >= N + nth_tuple_size, \"N can NOT larger than size of parameters pack.\");\n            constexpr std::int64_t delta_size = size - nth_tuple_size - N;\n\n            return ReplaceNthConsecutiveArgumentAndApplyDispatcher<N, delta_size>::template Dispatch(\n                std::forward<NthTuple>(nth_tuple),\n                std::forward<Func>(func),\n                std::forward_as_tuple(args...));\n        }\n\n        extern const CDrawTextReplacedFunction<User32DrawTextManager::A> on_draw_text_a_call;\n\n        extern const CDrawTextReplacedFunction<User32DrawTextManager::W> on_draw_text_w_call;\n\n        extern const CDrawTextReplacedFunction<User32DrawTextManager::ExA> on_draw_text_exa_call;\n\n        extern const CDrawTextReplacedFunction<User32DrawTextManager::ExW> on_draw_text_exw_call;\n    }\n\n    auto EnableAllReplaceFunction(Details::DrawTextReplacedFunctionState& ref_state) noexcept\n        -> class EnableAllReplaceFunctionGuard;\n\n    class EnableAllReplaceFunctionGuard\n    {\n        friend auto EnableAllReplaceFunction(Details::DrawTextReplacedFunctionState&) noexcept\n            -> EnableAllReplaceFunctionGuard;\n\n    private:\n        EnableAllReplaceFunctionGuard() = default;\n\n    public:\n        ~EnableAllReplaceFunctionGuard();\n\n        EnableAllReplaceFunctionGuard(const EnableAllReplaceFunctionGuard&) = delete;\n        EnableAllReplaceFunctionGuard& operator=(const EnableAllReplaceFunctionGuard&) = delete;\n        EnableAllReplaceFunctionGuard(EnableAllReplaceFunctionGuard&&) = default;\n        EnableAllReplaceFunctionGuard& operator=(EnableAllReplaceFunctionGuard&&) = default;\n    };\n};\n\n#define TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_CACHE_MAP_AND_EXPIRE_INTERVAL(sp_data) \\\n    std::lock_guard<std::mutex> cache_and_expire_interval_lock_guard(sp_data->m_mutex)\n\n#define TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_GC_INTERVAL(sp_data) \\\n    std::lock_guard<std::mutex> gc_lock_guard(sp_data->m_gc_mutex)\n\nclass CD2D1BitmapCache\n{\npublic:\n    using CacheInitializer =\n        std::function<Microsoft::WRL::ComPtr<ID2D1Bitmap>(Microsoft::WRL::ComPtr<ID2D1RenderTarget>, HBITMAP)>;\n\nprivate:\n    struct Cache\n    {\n        Microsoft::WRL::ComPtr<ID2D1Bitmap> m_cache{};\n        std::chrono::steady_clock::time_point m_init_timestamp{std::chrono::steady_clock::now()};\n        CacheInitializer m_cache_initializer{CD2D1BitmapCache::CreateD2D1BitmapFromHBitmap};\n        void Update(Microsoft::WRL::ComPtr<ID2D1RenderTarget> p_render_target, HBITMAP hbitmap);\n    };\n    struct HeapData\n    {\n        std::mutex m_mutex{};\n        std::unordered_map<HBITMAP, Cache> m_cache_map;\n        std::chrono::seconds m_cache_expire_interval{std::chrono::seconds(10)};\n        /**\n         * @brief 检查缓存是否过期 ！！此函数不加锁！！\n         *\n         * @param cache 输入的缓存\n         * @param now 输入的时间，默认为std::chrono::steady_clock::now()\n         * @return true 缓存已过期\n         * @return false 缓存未过期\n         */\n        bool IsCacheExpire(const Cache& cache, std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now());\n\n        std::mutex m_gc_mutex{};\n        std::chrono::seconds m_gc_interval{std::chrono::seconds(60)};\n    };\n\n    Microsoft::WRL::ComPtr<ID2D1RenderTarget> m_p_render_target;\n    std::shared_ptr<HeapData> m_sp_data{std::make_shared<HeapData>()};\n    std::thread m_gc_thread{\n        [wp_data = std::weak_ptr<HeapData>(m_sp_data)]()\n        {\n            do\n            {\n                auto sp_data = wp_data.lock();\n                if (!sp_data)\n                {\n                    break;\n                }\n\n                CD2D1BitmapCache::GCImpl(sp_data);\n\n                decltype(sp_data->m_gc_interval) gc_interval;\n                {\n                    TRAFFICMONITOR_CD2D1BITMAPCACHE_LOCK_GC_INTERVAL(sp_data);\n                    gc_interval = sp_data->m_gc_interval;\n                }\n                std::this_thread::sleep_for(gc_interval);\n            } while (true);\n        }};\n\npublic:\n    CD2D1BitmapCache(Microsoft::WRL::ComPtr<ID2D1RenderTarget> p_render_target);\n    ~CD2D1BitmapCache();\n    // 尚不支持复制或移动\n    CD2D1BitmapCache(const CD2D1BitmapCache&) = delete;\n    CD2D1BitmapCache& operator=(const CD2D1BitmapCache&) = delete;\n\n    void RebindRenderTarget(Microsoft::WRL::ComPtr<ID2D1RenderTarget> p_render_target);\n    void AddHBitmap(HBITMAP hbitmap, CacheInitializer initializer);\n    void AddHBitmap(HBITMAP hbitmap);\n    void RemoveHBitmap(HBITMAP hbitmap);\n    void RecreateAllHBitmaps();\n    static auto CreateD2D1BitmapFromHBitmap(Microsoft::WRL::ComPtr<ID2D1RenderTarget> p_render_target, HBITMAP hbitmap)\n        -> Microsoft::WRL::ComPtr<ID2D1Bitmap>;\n    void GC();\n    void SetGCInterval(const std::chrono::seconds interval);\n    void SetExpireInterval(const std::chrono::seconds interval);\n    auto GetCachedBitmap(HBITMAP hbitmap)\n        -> Microsoft::WRL::ComPtr<ID2D1Bitmap>;\n\nprivate:\n    /**\n     * @brief 检查BITMAP是否已经缓存 ！！此函数不加锁！！\n     *\n     * @param hbitmap 输入的HBITMAP\n     * @return true BITMAP已经被缓存\n     * @return false BITMAP尚未缓存\n     */\n    bool IsHBitmapExist(HBITMAP hbitmap) const;\n    static void GCImpl(std::shared_ptr<HeapData> sp_data);\n};\n\nclass CTaskBarDlgDrawCommon final : public IDrawCommon\n{\nprivate:\n    constexpr static int DEFAULT_GDI_OP_TEXTURE_ALPHA = 2;\n\n    CTaskBarDlgDrawCommonWindowSupport* m_p_window_support{nullptr};\n    CD2D1DeviceContextWindowSupport* m_p_d2d1_device_context_support{nullptr};\n    Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_p_device_context{};\n    class CGdiInteropObject\n    {\n    public:\n        CDC m_gdi_interop_cdc{};\n        HBITMAP m_gdi_interop_hbitmap{};\n        void* m_p_gdi_interop_hbitmap_data{};\n        HGDIOBJ m_gdi_interop_old_hbitmap{};\n\n        CGdiInteropObject(D2D1_SIZE_U size);\n        ~CGdiInteropObject();\n    };\n    DefaultCLazyConstructableWithInitializer<CGdiInteropObject, D2D1_SIZE_U> m_gdi_interop_object{\n        [this]()\n        { return std::make_tuple(m_p_window_support->GetSize()); }};\n    COLORREF m_text_color{};\n    bool m_is_clipped{false};\n\n    void ResetClippedStateIfSet();\n\npublic:\n    CTaskBarDlgDrawCommon() = default;\n    ~CTaskBarDlgDrawCommon();\n\n    void SetBackColor(COLORREF back_color, BYTE alpha = 255) override;\n    void SetFont(CFont* pfont) override;\n    // 在指定的矩形区域内绘制文本\n    void DrawWindowText(CRect rect, LPCTSTR lpszString, COLORREF color, Alignment align = Alignment::LEFT, bool draw_back_ground = false, bool multi_line = false, BYTE alpha = 255) override;\n    // 设置绘图剪辑区域\n    void SetDrawRect(CRect rect) override;\n    // 用纯色填充矩形\n    void FillRect(CRect rect, COLORREF color, BYTE alpha = 255) override;\n    // 绘制矩形边框。如果dot_line为true，则为虚线\n    void DrawRectOutLine(CRect rect, COLORREF color, int width = 1, bool dot_line = false, BYTE alpha = 255) override;\n    // 使用当前画笔画线\n    void DrawLine(CPoint start_point, int height, COLORREF color, BYTE alpha = 255) override;\n    void SetTextColor(const COLORREF color, BYTE alpha = 255) override;\n    // 绘制一个位图\n    // （注意：当stretch_mode设置为StretchMode::FILL（填充）时，会设置绘图剪辑区域，如果之后需要绘制其他图形，\n    // 需要重新设置绘图剪辑区域，否则图片外的区域会无法绘制）\n    void DrawBitmap(HBITMAP hbitmap, CPoint start_point, CSize size, StretchMode stretch_mode = StretchMode::STRETCH, BYTE alpha = 255) override;\n\n    void Create(\n        CTaskBarDlgDrawCommonWindowSupport& taskbar_dlg_draw_common_window_support,\n        CD2D1DeviceContextWindowSupport& ref_d2d1_device_window_support,\n        const D2D1_SIZE_U size);\n    template <class GdiOp>\n    void ExecuteGdiOperation(CRect rect, GdiOp gdi_op)\n    {\n        auto& ref_gdi_interop_object = m_gdi_interop_object.Get();\n        auto old_hfont = ref_gdi_interop_object.m_gdi_interop_cdc.SelectObject(\n            m_p_window_support->GetFont());\n        ref_gdi_interop_object.m_gdi_interop_cdc.SetTextColor(m_text_color);\n        TaskBarDlgUser32DrawTextHook::Details::DrawTextReplacedFunctionState state{ref_gdi_interop_object.m_gdi_interop_cdc};\n\n        {\n            auto enable_all_replaced_function_guard =\n                TaskBarDlgUser32DrawTextHook::EnableAllReplaceFunction(state);\n            gdi_op(ref_gdi_interop_object.m_gdi_interop_cdc);\n        }\n\n        ref_gdi_interop_object.m_gdi_interop_cdc.SelectObject(old_hfont);\n    }\n\n    auto GetD3D10Device1RecreateRequester()\n        -> std::function<bool(CHResultException& ex)>;\n    auto GetD2D1DeviceRecreateRequester()\n        -> std::function<bool(CHResultException& ex)>;\n    auto GetDCompositionDeviceRecreateRequester()\n        -> std::function<bool(CHResultException& ex)>;\n\n    static auto Convert(CPoint point) noexcept\n        -> D2D1_POINT_2F;\n    static auto Convert(CRect rect) noexcept\n        -> D2D1_RECT_F;\n};\n\n/**\n * @brief 仅在RenderType = DrawCommonHelper::RenderType::D2D1时可用，\n 此时输入的IDXGISurface1是兼容GDI的\n *\n */\nclass CTaskBarDlgDrawBuffer final : public IDrawBuffer\n{\nprivate:\n    Microsoft::WRL::ComPtr<IDXGISurface1> m_p_gdi_surface{};\n    CSize m_size;\n    HWND m_target_hwnd;\n    CTaskBarDlgDrawCommonWindowSupport& m_ref_window_support;\n\npublic:\n    CTaskBarDlgDrawBuffer(\n        CTaskBarDlgDrawCommonWindowSupport& taskbar_dlg_draw_common_window_support,\n        CD2D1DeviceContextWindowSupport& ref_d2d1_device_context_support,\n        CSize size,\n        HWND hwnd);\n    ~CTaskBarDlgDrawBuffer() override;\n\n    static auto GetDefaultBlendFunctionPointer() noexcept\n        -> const ::PBLENDFUNCTION;\n};\n\nclass CTaskBarDlgDrawBufferUseDComposition : public IDrawBuffer\n{\nprivate:\n    CD2D1DeviceContextWindowSupport* m_p_d2d1_device_context_support{};\n\npublic:\n    CTaskBarDlgDrawBufferUseDComposition(CD2D1DeviceContextWindowSupport& ref_d2d1_device_context_support);\n    ~CTaskBarDlgDrawBufferUseDComposition() override;\n};\n"
  },
  {
    "path": "TrafficMonitor/TaskBarSettingsDlg.cpp",
    "content": "﻿// TaskBarSettingsDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"TaskBarSettingsDlg.h\"\n#include \"afxdialogex.h\"\n#include \"CMFCColorDialogEx.h\"\n#include \"CAutoAdaptSettingsDlg.h\"\n#include \"DisplayTextSettingDlg.h\"\n#include \"SetItemOrderDlg.h\"\n#include \"WindowsSettingHelper.h\"\n#include \"TrafficMonitorDlg.h\"\n#include \"FileDialogEx.h\"\n#include \"Win11TaskbarSettingDlg.h\"\n#include \"TaskbarHelper.h\"\n\n// CTaskBarSettingsDlg 对话框\n\nIMPLEMENT_DYNAMIC(CTaskBarSettingsDlg, CTabDlg)\n\nCTaskBarSettingsDlg::CTaskBarSettingsDlg(CWnd* pParent /*=NULL*/)\n    : CTabDlg(IDD_TASKBAR_SETTINGS_DIALOG, pParent)\n{\n\n}\n\nCTaskBarSettingsDlg::~CTaskBarSettingsDlg()\n{\n}\n\nbool CTaskBarSettingsDlg::IsStyleModified()\n{\n    bool modified{};\n    modified |= (theApp.m_taskbar_data.text_colors != m_data.text_colors);\n    modified |= (theApp.m_taskbar_data.back_color != m_data.back_color);\n    modified |= (theApp.m_taskbar_data.transparent_color != m_data.transparent_color);\n    modified |= (theApp.m_taskbar_data.status_bar_color != m_data.status_bar_color);\n    modified |= (theApp.m_taskbar_data.specify_each_item_color != m_data.specify_each_item_color);\n    return modified && m_style_modified;\n}\n\nvoid CTaskBarSettingsDlg::DrawStaticColor()\n{\n    //CCommon::FillStaticColor(m_text_color_static, m_data.text_color);\n    //CCommon::FillStaticColor(m_back_color_static, m_data.back_color);\n    if (m_data.specify_each_item_color)\n    {\n        int color_num{ static_cast<int>(m_data.text_colors.size()) * 2 };\n        if (color_num > 16)\n            color_num = 16;\n        int i{};\n        m_text_color_static.SetColorNum(color_num);\n        for (const auto& item : m_data.text_colors)\n        {\n            m_text_color_static.SetFillColor(i, item.second.label);\n            m_text_color_static.SetFillColor(i + 1, item.second.value);\n            i += 2;\n        }\n        m_text_color_static.Invalidate();\n    }\n    else if (!m_data.text_colors.empty())\n    {\n        m_text_color_static.SetFillColor(m_data.text_colors.begin()->second.label);\n    }\n    m_back_color_static.SetFillColor(m_data.back_color);\n    //m_trans_color_static.SetFillColor(m_data.transparent_color);\n    m_status_bar_color_static.SetFillColor(m_data.GetUsageGraphColor());\n}\n\nvoid CTaskBarSettingsDlg::IniUnitCombo()\n{\n    m_unit_combo.ResetContent();\n    m_unit_combo.AddString(CCommon::LoadText(IDS_AUTO));\n    if (m_data.unit_byte)\n    {\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" KB/s\")));\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" MB/s\")));\n    }\n    else\n    {\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" Kb/s\")));\n        m_unit_combo.AddString(CCommon::LoadText(IDS_FIXED_AS, _T(\" Mb/s\")));\n    }\n    m_unit_combo.SetCurSel(static_cast<int>(m_data.speed_unit));\n}\n\nvoid CTaskBarSettingsDlg::ApplyDefaultStyle(int index)\n{\n    theApp.m_taskbar_default_style.ApplyDefaultStyle(index, m_data);\n    DrawStaticColor();\n    ((CButton*)GetDlgItem(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK))->SetCheck(m_data.specify_each_item_color);\n    m_background_transparent_chk.SetCheck(m_data.IsTaskbarTransparent());\n}\n\nvoid CTaskBarSettingsDlg::ModifyDefaultStyle(int index)\n{\n    theApp.m_taskbar_default_style.ModifyDefaultStyle(index, m_data);\n}\n\nvoid CTaskBarSettingsDlg::EnableControl()\n{\n    bool exe_path_enable = (m_data.double_click_action == DoubleClickAction::SEPCIFIC_APP);\n    ShowDlgCtrl(IDC_EXE_PATH_STATIC, exe_path_enable);\n    ShowDlgCtrl(IDC_EXE_PATH_EDIT, exe_path_enable);\n    ShowDlgCtrl(IDC_BROWSE_BUTTON, exe_path_enable);\n    EnableDlgCtrl(IDC_AUTO_ADAPT_SETTINGS_BUTTON, m_data.auto_adapt_light_theme);\n    EnableDlgCtrl(IDC_SHOW_DASHED_BOX, m_data.show_status_bar || m_data.show_netspeed_figure);\n    m_status_bar_color_static.EnableWindow(m_data.show_status_bar || m_data.show_netspeed_figure);\n    EnableDlgCtrl(IDC_CM_GRAPH_BAR_RADIO, m_data.show_status_bar || m_data.show_netspeed_figure);\n    EnableDlgCtrl(IDC_CM_GRAPH_PLOT_RADIO, m_data.show_status_bar || m_data.show_netspeed_figure);\n    EnableDlgCtrl(IDC_NET_SPEED_FIGURE_MAX_VALUE_EDIT, m_data.show_netspeed_figure);\n    EnableDlgCtrl(IDC_NET_SPEED_FIGURE_MAX_VALUE_UNIT_COMBO, m_data.show_netspeed_figure);\n    //Win11下，任务栏左对齐时禁用“任务栏窗口显示在任务栏左侧”的选项\n    EnableDlgCtrl(IDC_TASKBAR_WND_ON_LEFT_CHECK, !theApp.IsWindows11Taskbar() || CWindowsSettingHelper::IsTaskbarCenterAlign());\n    EnableDlgCtrl(IDC_ENABLE_COLOR_EMOJI_CHECK, !m_data.disable_d2d);\n    EnableDlgCtrl(IDC_WIN11_SETTINGS_BUTTON, theApp.IsWindows11Taskbar());\n}\n\n\nvoid CTaskBarSettingsDlg::SetControlMouseWheelEnable(bool enable)\n{\n    m_unit_combo.SetMouseWheelEnable(enable);\n    m_double_click_combo.SetMouseWheelEnable(enable);\n    m_digit_number_combo.SetMouseWheelEnable(enable);\n    m_font_size_edit.SetMouseWheelEnable(enable);\n    m_memory_display_combo.SetMouseWheelEnable(enable);\n    m_item_space_edit.SetMouseWheelEnable(enable);\n    m_vertical_margin_edit.SetMouseWheelEnable(enable);\n    m_net_speed_figure_max_val_edit.SetMouseWheelEnable(enable);\n    m_net_speed_figure_max_val_unit_combo.SetMouseWheelEnable(enable);\n    m_displays_combo.SetMouseWheelEnable(enable);\n}\n\nbool CTaskBarSettingsDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_FONT_STATIC },\n        { CtrlTextInfo::C0, IDC_FONT_NAME_EDIT1 },\n        { CtrlTextInfo::R1, IDC_FONT_SIZE_STATIC },\n        { CtrlTextInfo::R2, IDC_FONT_SIZE_EDIT1 },\n        { CtrlTextInfo::R3, IDC_SET_FONT_BUTTON1, CtrlTextInfo::W16 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L2, IDC_TXT_COLOR_STATIC },\n        { CtrlTextInfo::L1, IDC_TEXT_COLOR_STATIC1 },\n        { CtrlTextInfo::C0, IDC_SPECIFY_EACH_ITEM_COLOR_CHECK, CtrlTextInfo::W16 },\n        { CtrlTextInfo::R1, IDC_DEFAULT_STYLE_BUTTON, CtrlTextInfo::W16 },\n        { CtrlTextInfo::L2, IDC_BACK_COLOR_STATIC },\n        { CtrlTextInfo::L1, IDC_TEXT_COLOR_STATIC2 },\n        { CtrlTextInfo::C0, IDC_BACKGROUND_TRANSPARENT_CHECK, CtrlTextInfo::W16 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::C0, IDC_AUTO_ADAPT_LIGHT_THEME_CHECK, CtrlTextInfo::W16 },\n        { CtrlTextInfo::R1, IDC_AUTO_ADAPT_SETTINGS_BUTTON, CtrlTextInfo::W16 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_NET_SPEED_WIDTH_STATIC },\n        { CtrlTextInfo::L3, IDC_DIGIT_NUMBER_COMBO },\n        { CtrlTextInfo::L2, IDC_CHARACTOR_STATIC }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, TXT_MEMORY_DISPLAY_MODE },\n        { CtrlTextInfo::C0, IDC_MEMORY_DISPLAY_COMBO }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_ITEM_SPACING_STATIC },\n        { CtrlTextInfo::L3, IDC_ITEM_SPACE_EDIT },\n        { CtrlTextInfo::L2, IDC_PIXELS_STATIC },\n        { CtrlTextInfo::L4, IDC_VERTICAL_MARGIN_STATIC },\n        { CtrlTextInfo::L3, IDC_VERTICAL_MARGIN_EDIT },\n        { CtrlTextInfo::L2, IDC_PIXELS_STATIC1 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_DISPLAY_TO_SHOW_TASKBAR_WND_STATIC },\n        { CtrlTextInfo::C0, IDC_DISPLAY_TO_SHOW_TASKBAR_WND_COMBO }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_WIN11_SETTINGS_BUTTON, CtrlTextInfo::W16 }\n    });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L1, IDC_DOUBLE_CLICK_ACTION_STATIC },\n        { CtrlTextInfo::C0, IDC_DOUBLE_CLICK_COMBO },\n        { CtrlTextInfo::L1, IDC_EXE_PATH_STATIC },\n        { CtrlTextInfo::C0, IDC_EXE_PATH_EDIT },\n        { CtrlTextInfo::R1, IDC_BROWSE_BUTTON }\n    });\n    RepositionTextBasedControls({\n    { CtrlTextInfo::L4, IDC_NET_SPEED_MAX_VALUE_STATIC },\n    { CtrlTextInfo::L3, IDC_NET_SPEED_FIGURE_MAX_VALUE_EDIT },\n    { CtrlTextInfo::L2, IDC_NET_SPEED_FIGURE_MAX_VALUE_UNIT_COMBO }\n        });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L2, IDC_USAGE_GRAPH_COLOR_STATIC },\n        { CtrlTextInfo::L1, IDC_TEXT_COLOR_STATIC3 },\n        { CtrlTextInfo::C0, IDC_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK, CtrlTextInfo::W16 }\n        });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_GRAPH_DISPLAY_MODE_STATIC },\n        { CtrlTextInfo::L3, IDC_CM_GRAPH_BAR_RADIO, CtrlTextInfo::W16 },\n        { CtrlTextInfo::L2, IDC_CM_GRAPH_PLOT_RADIO, CtrlTextInfo::W16 }\n        });\n\n    return true;\n}\n\nvoid CTaskBarSettingsDlg::DoDataExchange(CDataExchange* pDX)\n{\n    DDX_Control(pDX, IDC_TEXT_COLOR_STATIC1, m_text_color_static);\n    DDX_Control(pDX, IDC_TEXT_COLOR_STATIC2, m_back_color_static);\n    DDX_Control(pDX, IDC_TEXT_COLOR_STATIC3, m_status_bar_color_static);\n    CTabDlg::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_UNIT_COMBO, m_unit_combo);\n    DDX_Control(pDX, IDC_HIDE_UNIT_CHECK, m_hide_unit_chk);\n    DDX_Control(pDX, IDC_FONT_SIZE_EDIT1, m_font_size_edit);\n    DDX_Control(pDX, IDC_DOUBLE_CLICK_COMBO, m_double_click_combo);\n    DDX_Control(pDX, IDC_DIGIT_NUMBER_COMBO, m_digit_number_combo);\n    //DDX_Control(pDX, IDC_TRANSPARENT_COLOR_STATIC, m_trans_color_static);\n    DDX_Control(pDX, IDC_BACKGROUND_TRANSPARENT_CHECK, m_background_transparent_chk);\n    DDX_Control(pDX, IDC_AUTO_ADAPT_LIGHT_THEME_CHECK, m_atuo_adapt_light_theme_chk);\n    DDX_Control(pDX, IDC_AUTO_SET_BACK_COLOR_CHECK, m_auto_set_back_color_chk);\n    DDX_Control(pDX, IDC_MEMORY_DISPLAY_COMBO, m_memory_display_combo);\n    DDX_Control(pDX, IDC_ITEM_SPACE_EDIT, m_item_space_edit);\n    DDX_Control(pDX, IDC_VERTICAL_MARGIN_EDIT, m_vertical_margin_edit);\n    DDX_Control(pDX, IDC_NET_SPEED_FIGURE_MAX_VALUE_EDIT, m_net_speed_figure_max_val_edit);\n    DDX_Control(pDX, IDC_NET_SPEED_FIGURE_MAX_VALUE_UNIT_COMBO, m_net_speed_figure_max_val_unit_combo);\n    DDX_Control(pDX, IDC_DISPLAY_TO_SHOW_TASKBAR_WND_COMBO, m_displays_combo);\n}\n\n\nBEGIN_MESSAGE_MAP(CTaskBarSettingsDlg, CTabDlg)\n    ON_BN_CLICKED(IDC_SET_FONT_BUTTON1, &CTaskBarSettingsDlg::OnBnClickedSetFontButton1)\n    ON_BN_CLICKED(IDC_TASKBAR_WND_ON_LEFT_CHECK, &CTaskBarSettingsDlg::OnBnClickedTaskbarWndOnLeftCheck)\n    ON_BN_CLICKED(IDC_SPEED_SHORT_MODE_CHECK, &CTaskBarSettingsDlg::OnBnClickedSpeedShortModeCheck)\n    ON_CBN_SELCHANGE(IDC_UNIT_COMBO, &CTaskBarSettingsDlg::OnCbnSelchangeUnitCombo)\n    ON_BN_CLICKED(IDC_HIDE_UNIT_CHECK, &CTaskBarSettingsDlg::OnBnClickedHideUnitCheck)\n    ON_BN_CLICKED(IDC_VALUE_RIGHT_ALIGN_CHECK, &CTaskBarSettingsDlg::OnBnClickedValueRightAlignCheck)\n    ON_BN_CLICKED(IDC_HIDE_PERCENTAGE_CHECK, &CTaskBarSettingsDlg::OnBnClickedHidePercentageCheck)\n    ON_MESSAGE(WM_STATIC_CLICKED, &CTaskBarSettingsDlg::OnStaticClicked)\n    ON_BN_CLICKED(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK, &CTaskBarSettingsDlg::OnBnClickedSpecifyEachItemColorCheck)\n    ON_CBN_SELCHANGE(IDC_DOUBLE_CLICK_COMBO, &CTaskBarSettingsDlg::OnCbnSelchangeDoubleClickCombo)\n    ON_BN_CLICKED(IDC_HORIZONTAL_ARRANGE_CHECK, &CTaskBarSettingsDlg::OnBnClickedHorizontalArrangeCheck)\n    ON_BN_CLICKED(IDC_SHOW_STATUS_BAR_CHECK, &CTaskBarSettingsDlg::OnBnClickedShowStatusBarCheck)\n    ON_BN_CLICKED(IDC_SEPARATE_VALUE_UNIT_CHECK, &CTaskBarSettingsDlg::OnBnClickedSeparateValueUnitCheck)\n    ON_BN_CLICKED(IDC_UNIT_BYTE_RADIO, &CTaskBarSettingsDlg::OnBnClickedUnitByteRadio)\n    ON_BN_CLICKED(IDC_UNIT_BIT_RADIO, &CTaskBarSettingsDlg::OnBnClickedUnitBitRadio)\n    ON_BN_CLICKED(IDC_SHOW_TOOL_TIP_CHK, &CTaskBarSettingsDlg::OnBnClickedShowToolTipChk)\n    ON_BN_CLICKED(IDC_DEFAULT_STYLE_BUTTON, &CTaskBarSettingsDlg::OnBnClickedDefaultStyleButton)\n    ON_WM_DESTROY()\n    ON_BN_CLICKED(IDC_BROWSE_BUTTON, &CTaskBarSettingsDlg::OnBnClickedBrowseButton)\n    ON_BN_CLICKED(IDC_CM_GRAPH_BAR_RADIO, &CTaskBarSettingsDlg::OnBnClickedCMGraphBarRadio)\n    ON_BN_CLICKED(IDC_CM_GRAPH_PLOT_RADIO, &CTaskBarSettingsDlg::OnBnClickedCMGraphPLOTRadio)\n    ON_BN_CLICKED(IDC_BACKGROUND_TRANSPARENT_CHECK, &CTaskBarSettingsDlg::OnBnClickedBackgroundTransparentCheck)\n    ON_BN_CLICKED(IDC_AUTO_ADAPT_SETTINGS_BUTTON, &CTaskBarSettingsDlg::OnBnClickedAutoAdaptSettingsButton)\n    ON_BN_CLICKED(IDC_AUTO_ADAPT_LIGHT_THEME_CHECK, &CTaskBarSettingsDlg::OnBnClickedAutoAdaptLightThemeCheck)\n    ON_BN_CLICKED(IDC_AUTO_SET_BACK_COLOR_CHECK, &CTaskBarSettingsDlg::OnBnClickedAutoSetBackColorCheck)\n    ON_BN_CLICKED(IDC_DISPLAY_TEXT_SETTING_BUTTON, &CTaskBarSettingsDlg::OnBnClickedDisplayTextSettingButton)\n    ON_CBN_SELCHANGE(IDC_MEMORY_DISPLAY_COMBO, &CTaskBarSettingsDlg::OnCbnSelchangeMemoryDisplayCombo)\n    ON_BN_CLICKED(IDC_SHOW_DASHED_BOX, &CTaskBarSettingsDlg::OnBnClickedShowDashedBox)\n    ON_BN_CLICKED(IDC_SET_ORDER_BUTTON, &CTaskBarSettingsDlg::OnBnClickedSetOrderButton)\n    ON_EN_CHANGE(IDC_ITEM_SPACE_EDIT, &CTaskBarSettingsDlg::OnEnChangeItemSpaceEdit)\n    ON_EN_CHANGE(IDC_VERTICAL_MARGIN_EDIT, &CTaskBarSettingsDlg::OnEnChangeVerticalMarginEdit)\n    ON_BN_CLICKED(IDC_SHOW_NET_SPEED_FIGURE_CHECK, &CTaskBarSettingsDlg::OnBnClickedShowNetSpeedFigureCheck)\n    ON_CBN_SELCHANGE(IDC_NET_SPEED_FIGURE_MAX_VALUE_UNIT_COMBO, &CTaskBarSettingsDlg::OnCbnSelchangeNetSpeedFigureMaxValueUnitCombo)\n    ON_EN_CHANGE(IDC_NET_SPEED_FIGURE_MAX_VALUE_EDIT, &CTaskBarSettingsDlg::OnEnChangeNetSpeedFigureMaxValueEdit)\n    ON_BN_CLICKED(IDC_GDI_RADIO, &CTaskBarSettingsDlg::OnBnClickedGdiRadio)\n    ON_BN_CLICKED(IDC_D2D_RADIO, &CTaskBarSettingsDlg::OnBnClickedD2dRadio)\n    ON_BN_CLICKED(IDC_ENABLE_COLOR_EMOJI_CHECK, &CTaskBarSettingsDlg::OnBnClickedEnableColorEmojiCheck)\n    ON_CBN_SELCHANGE(IDC_DIGIT_NUMBER_COMBO, &CTaskBarSettingsDlg::OnCbnSelchangeDigitNumberCombo)\n    ON_BN_CLICKED(IDC_WIN11_SETTINGS_BUTTON, &CTaskBarSettingsDlg::OnBnClickedWin11SettingsButton)\n    ON_BN_CLICKED(IDC_TASKBAR_WND_IN_SECONDARY_DISPLAY_CHECK, &CTaskBarSettingsDlg::OnBnClickedTaskbarWndInSecondaryDisplayCheck)\n    ON_CBN_SELCHANGE(IDC_DISPLAY_TO_SHOW_TASKBAR_WND_COMBO, &CTaskBarSettingsDlg::OnCbnSelchangeDisplayToShowTaskbarWndCombo)\n    ON_BN_CLICKED(IDC_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK, &CTaskBarSettingsDlg::OnBnClickedUsageGraphFollowSystemCheck)\n    ON_EN_CHANGE(IDC_FONT_SIZE_EDIT1, &CTaskBarSettingsDlg::OnEnChangeFontSizeEdit1)\nEND_MESSAGE_MAP()\n\n\n// CTaskBarSettingsDlg 消息处理程序\n\n\nBOOL CTaskBarSettingsDlg::OnInitDialog()\n{\n    CTabDlg::OnInitDialog();\n\n    // TODO:  在此添加额外的初始化\n\n    theApp.m_taskbar_default_style.LoadConfig();\n\n    //初始化各控件状态\n    SetDlgItemText(IDC_FONT_NAME_EDIT1, m_data.font.name);\n    //wchar_t buff[16];\n    //swprintf_s(buff, L\"%d\", m_data.font_size);\n    //SetDlgItemText(IDC_FONT_SIZE_EDIT1, buff);\n    m_font_size_edit.SetRange(5, 72);\n    m_font_size_edit.SetValue(m_data.font.size);\n\n    //SetDlgItemText(IDC_UPLOAD_EDIT1, m_data.disp_str.Get(TDI_UP).c_str());\n    //SetDlgItemText(IDC_DOWNLOAD_EDIT1, m_data.disp_str.Get(TDI_DOWN).c_str());\n    //SetDlgItemText(IDC_CPU_EDIT1, m_data.disp_str.Get(TDI_CPU).c_str());\n    //SetDlgItemText(IDC_MEMORY_EDIT1, m_data.disp_str.Get(TDI_MEMORY).c_str());\n\n    //((CButton*)GetDlgItem(IDC_SWITCH_UP_DOWN_CHECK1))->SetCheck(m_data.swap_up_down);\n    ((CButton*)GetDlgItem(IDC_TASKBAR_WND_ON_LEFT_CHECK))->SetCheck(m_data.tbar_wnd_on_left);\n    ((CButton*)GetDlgItem(IDC_SPEED_SHORT_MODE_CHECK))->SetCheck(m_data.speed_short_mode);\n    ((CButton*)GetDlgItem(IDC_VALUE_RIGHT_ALIGN_CHECK))->SetCheck(m_data.value_right_align);\n    ((CButton*)GetDlgItem(IDC_HORIZONTAL_ARRANGE_CHECK))->SetCheck(m_data.horizontal_arrange);\n    ((CButton*)GetDlgItem(IDC_SHOW_STATUS_BAR_CHECK))->SetCheck(m_data.show_status_bar);\n    ((CButton*)GetDlgItem(IDC_SEPARATE_VALUE_UNIT_CHECK))->SetCheck(m_data.separate_value_unit_with_space);\n    ((CButton*)GetDlgItem(IDC_SHOW_TOOL_TIP_CHK))->SetCheck(m_data.show_tool_tip);\n\n    CheckDlgButton(IDC_TASKBAR_WND_IN_SECONDARY_DISPLAY_CHECK, m_data.show_taskbar_wnd_in_secondary_display);\n\n    m_text_color_static.SetLinkCursor();\n    m_back_color_static.SetLinkCursor();\n    //m_trans_color_static.SetLinkCursor();\n    m_status_bar_color_static.SetLinkCursor();\n    DrawStaticColor();\n\n#ifdef COMPILE_FOR_WINXP\n    m_background_transparent_chk.EnableWindow(FALSE);\n#endif // COMPILE_FOR_WINXP\n\n    if (theApp.m_win_version.IsWindows7())\n        m_background_transparent_chk.EnableWindow(FALSE);\n\n    m_toolTip.Create(this);\n    m_toolTip.SetMaxTipWidth(theApp.DPI(300));\n    m_toolTip.AddTool(GetDlgItem(IDC_SPEED_SHORT_MODE_CHECK), CCommon::LoadText(IDS_SPEED_SHORT_MODE_TIP));\n    m_toolTip.AddTool(&m_atuo_adapt_light_theme_chk, CCommon::LoadText(IDS_AUTO_ADAPT_TIP_INFO));\n    m_toolTip.AddTool(GetDlgItem(IDC_SHOW_STATUS_BAR_CHECK), CCommon::LoadText(IDS_SHOW_RESOURCE_USAGE_GRAPH_TIP));\n    m_toolTip.AddTool(GetDlgItem(IDC_SHOW_NET_SPEED_FIGURE_CHECK), CCommon::LoadText(IDS_SHOW_NET_SPEED_GRAPH_TIP));\n\n\n    if (m_data.unit_byte)\n        ((CButton*)GetDlgItem(IDC_UNIT_BYTE_RADIO))->SetCheck(TRUE);\n    else\n        ((CButton*)GetDlgItem(IDC_UNIT_BIT_RADIO))->SetCheck(TRUE);\n\n    IniUnitCombo();\n\n    m_hide_unit_chk.SetCheck(m_data.hide_unit);\n    if (m_data.speed_unit == SpeedUnit::AUTO)\n    {\n        m_hide_unit_chk.SetCheck(FALSE);\n        m_data.hide_unit = false;\n        m_hide_unit_chk.EnableWindow(FALSE);\n    }\n    ((CButton*)GetDlgItem(IDC_HIDE_PERCENTAGE_CHECK))->SetCheck(m_data.hide_percent);\n    ((CButton*)GetDlgItem(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK))->SetCheck(m_data.specify_each_item_color);\n    m_background_transparent_chk.SetCheck(m_data.IsTaskbarTransparent());\n    m_atuo_adapt_light_theme_chk.SetCheck(m_data.auto_adapt_light_theme);\n    m_auto_set_back_color_chk.SetCheck(m_data.auto_set_background_color);\n    m_auto_set_back_color_chk.EnableWindow(theApp.m_win_version.IsWindows8OrLater());\n\n    if (theApp.m_win_version.GetMajorVersion() < 10)\n    {\n        m_data.auto_adapt_light_theme = false;\n        m_atuo_adapt_light_theme_chk.EnableWindow(FALSE);\n    }\n\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_CONNECTION_DETIAL));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_HISTORICAL_TRAFFIC));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_SHOW_HIDE_CPU_MEMORY));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_OPTION_SETTINGS));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_OPEN_TASK_MANAGER));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_SPECIFIC_APP));\n    m_double_click_combo.AddString(CCommon::LoadText(IDS_NONE));\n    m_double_click_combo.SetCurSel(static_cast<int>(m_data.double_click_action));\n\n    m_digit_number_combo.AddString(_T(\"3\"));\n    m_digit_number_combo.AddString(_T(\"4\"));\n    m_digit_number_combo.AddString(_T(\"5\"));\n    m_digit_number_combo.AddString(_T(\"6\"));\n    m_digit_number_combo.AddString(_T(\"7\"));\n    m_digit_number_combo.SetCurSel(m_data.digits_number - 3);\n\n    SetDlgItemText(IDC_EXE_PATH_EDIT, m_data.double_click_exe.c_str());\n\n    //m_default_style_menu.LoadMenu(IDR_TASKBAR_STYLE_MENU);\n\n    if (m_data.cm_graph_type)\n        CheckDlgButton(IDC_CM_GRAPH_PLOT_RADIO, TRUE);\n    else\n        CheckDlgButton(IDC_CM_GRAPH_BAR_RADIO, TRUE);\n    CheckDlgButton(IDC_SHOW_DASHED_BOX, m_data.show_graph_dashed_box);\n    CheckDlgButton(IDC_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK, m_data.graph_color_following_system);\n\n    m_item_space_edit.SetRange(0, 32);\n    m_item_space_edit.SetValue(m_data.item_space);\n    CTaskBarDlg* taskbar_dlg{ CTrafficMonitorDlg::Instance()->GetTaskbarWindow() };\n    m_vertical_margin_edit.SetRange(-10, 10);\n    m_vertical_margin_edit.SetValue(m_data.vertical_margin);\n    if (taskbar_dlg != nullptr)\n        m_vertical_margin_edit.EnableWindow(taskbar_dlg->IsTasksbarOnTopOrBottom());\n\n    //初始化内存显示方式下拉列表\n    m_memory_display_combo.AddString(CCommon::LoadText(IDS_USAGE_PERCENTAGE));\n    m_memory_display_combo.AddString(CCommon::LoadText(IDS_MEMORY_USED));\n    m_memory_display_combo.AddString(CCommon::LoadText(IDS_MEMORY_AVAILABLE));\n    m_memory_display_combo.SetCurSel(static_cast<int>(m_data.memory_display));\n\n    CheckDlgButton(IDC_SHOW_NET_SPEED_FIGURE_CHECK, m_data.show_netspeed_figure);\n    m_net_speed_figure_max_val_edit.SetRange(1, 1024);\n    m_net_speed_figure_max_val_edit.SetValue(m_data.netspeed_figure_max_value);\n    m_net_speed_figure_max_val_unit_combo.AddString(_T(\"KB\"));\n    m_net_speed_figure_max_val_unit_combo.AddString(_T(\"MB\"));\n    m_net_speed_figure_max_val_unit_combo.SetCurSel(m_data.netspeed_figure_max_value_unit);\n\n    ((CButton*)GetDlgItem(IDC_SET_ORDER_BUTTON))->SetIcon(theApp.GetMenuIcon(IDI_ITEM));\n\n    //初始化“预设方案”菜单\n    m_default_style_menu.CreatePopupMenu();\n    m_modify_default_style_menu.CreatePopupMenu();\n    for (int i{ 0 }; i < TASKBAR_DEFAULT_STYLE_NUM; i++)\n    {\n        CString item_name;\n        item_name.Format(_T(\"%s %d\"), CCommon::LoadText(IDS_PRESET).GetString(), i + 1);\n        m_default_style_menu.AppendMenu(MF_STRING | MF_ENABLED, ID_DEFAULT_STYLE1 + i, item_name);\n        m_modify_default_style_menu.AppendMenu(MF_STRING | MF_ENABLED, ID_MODIFY_DEFAULT_STYLE1 + i, item_name);\n    }\n    m_default_style_menu.AppendMenu(MF_SEPARATOR);\n    m_default_style_menu.AppendMenu(MF_POPUP | MF_STRING, (UINT)m_modify_default_style_menu.m_hMenu, CCommon::LoadText(IDS_MODIFY_PRESET));\n\n    //获取副显示器的数量\n    std::vector<HWND> secondary_displays;\n    CTaskbarHelper::GetAllSecondaryDisplayTaskbar(secondary_displays);\n    //初始化“显示任务栏窗口的显示器”下拉列表\n    m_displays_combo.AddString(CCommon::LoadText(IDS_PRIMARY_DISPLAY));\n    for (size_t i = 0; i < secondary_displays.size(); i++)\n    {\n        m_displays_combo.AddString(CCommon::LoadTextFormat(IDS_SECONDARY_DISPLAY, { i + 1 }));\n    }\n    if (!m_data.show_taskbar_wnd_in_secondary_display)\n    {\n        m_displays_combo.SetCurSel(0);\n    }\n    else\n    {\n        int combo_index = m_data.secondary_display_index + 1;\n        int combo_item_count = m_displays_combo.GetCount();\n        if (combo_index >= combo_item_count)\n            combo_index = combo_item_count - 1;\n        m_displays_combo.SetCurSel(combo_index);\n    }\n\n    //设置是否禁用D2D\n    if (!CTaskBarDlgDrawCommonSupport::CheckSupport())\n    {\n        m_data.disable_d2d = true;\n        //不支持时禁用选项\n        EnableDlgCtrl(IDC_D2D_RADIO, false);\n    }\n\n    if (m_data.disable_d2d)\n        CheckDlgButton(IDC_GDI_RADIO, true);\n    else\n        CheckDlgButton(IDC_D2D_RADIO, true);\n\n    CheckDlgButton(IDC_ENABLE_COLOR_EMOJI_CHECK, m_data.enable_colorful_emoji);\n\n    EnableControl();\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n                  // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedSetFontButton1()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    LOGFONT lf{};\n    lf.lfHeight = FontSizeToLfHeight(m_data.font.size);\n    lf.lfWeight = (m_data.font.bold ? FW_BOLD : FW_NORMAL);\n    lf.lfItalic = m_data.font.italic;\n    lf.lfUnderline = m_data.font.underline;\n    lf.lfStrikeOut = m_data.font.strike_out;\n    lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;\n    //wcsncpy_s(lf.lfFaceName, m_data.font.name.GetString(), 32);\n    CCommon::WStringCopy(lf.lfFaceName, 32, m_data.font.name.GetString());\n    CCommon::NormalizeFont(lf);\n    CFontDialog fontDlg(&lf);   //构造字体对话框，初始选择字体为之前字体\n    if (IDOK == fontDlg.DoModal())     // 显示字体对话框\n    {\n        //获取字体信息\n        m_data.font.name = fontDlg.GetFaceName();\n        m_data.font.size = fontDlg.GetSize() / 10;\n        m_data.font.bold = (fontDlg.IsBold() != FALSE);\n        m_data.font.italic = (fontDlg.IsItalic() != FALSE);\n        m_data.font.underline = (fontDlg.IsUnderline() != FALSE);\n        m_data.font.strike_out = (fontDlg.IsStrikeOut() != FALSE);\n        //将字体信息显示出来\n        SetDlgItemText(IDC_FONT_NAME_EDIT1, m_data.font.name);\n        wchar_t buff[16];\n        swprintf_s(buff, L\"%d\", m_data.font.size);\n        SetDlgItemText(IDC_FONT_SIZE_EDIT1, buff);\n    }\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedTaskbarWndOnLeftCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.tbar_wnd_on_left = (((CButton*)GetDlgItem(IDC_TASKBAR_WND_ON_LEFT_CHECK))->GetCheck() != 0);\n    EnableControl();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedSpeedShortModeCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.speed_short_mode = (((CButton*)GetDlgItem(IDC_SPEED_SHORT_MODE_CHECK))->GetCheck() != 0);\n}\n\n\nBOOL CTaskBarSettingsDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    if (pMsg->message == WM_MOUSEMOVE)\n        m_toolTip.RelayEvent(pMsg);\n\n    return CTabDlg::PreTranslateMessage(pMsg);\n}\n\n\nvoid CTaskBarSettingsDlg::OnCbnSelchangeUnitCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.speed_unit = static_cast<SpeedUnit>(m_unit_combo.GetCurSel());\n    if (m_data.speed_unit == SpeedUnit::AUTO)\n    {\n        m_hide_unit_chk.SetCheck(FALSE);\n        m_data.hide_unit = false;\n        m_hide_unit_chk.EnableWindow(FALSE);\n    }\n    else\n    {\n        m_hide_unit_chk.EnableWindow(TRUE);\n    }\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedHideUnitCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.hide_unit = (m_hide_unit_chk.GetCheck() != 0);\n}\n\n\nvoid CTaskBarSettingsDlg::OnOK()\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //获取字体设置\n    int font_size;\n    font_size = m_font_size_edit.GetValue();\n    if (font_size > MAX_FONT_SIZE || font_size < MIN_FONT_SIZE)\n    {\n        CString info;\n        info.Format(CCommon::LoadText(IDS_FONT_SIZE_WARNING), MIN_FONT_SIZE, MAX_FONT_SIZE);\n        MessageBox(info, NULL, MB_OK | MB_ICONWARNING);\n    }\n    else\n    {\n        m_data.font.size = font_size;\n    }\n    GetDlgItemText(IDC_FONT_NAME_EDIT1, m_data.font.name);\n\n    bool is_taskbar_transparent_checked = (m_background_transparent_chk.GetCheck() != 0);\n    m_data.SetTaskabrTransparent(is_taskbar_transparent_checked);\n\n    SaveColorSettingToDefaultStyle();\n\n    CTabDlg::OnOK();\n}\n\n\nvoid CTaskBarSettingsDlg::SaveColorSettingToDefaultStyle()\n{\n    //如果开启了自动适应Windows10深色/浅色模式功能时，自动将当前配置保存到对应预设\n    if (theApp.m_taskbar_data.auto_save_taskbar_color_settings_to_preset && m_data.auto_adapt_light_theme && IsStyleModified())\n    {\n        int default_style_saved{ CWindowsSettingHelper::IsWindows10LightTheme() ? m_data.light_default_style : m_data.dark_default_style };\n        ModifyDefaultStyle(default_style_saved);\n    }\n}\n\nvoid CTaskBarSettingsDlg::OnBnClickedValueRightAlignCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.value_right_align = (((CButton*)GetDlgItem(IDC_VALUE_RIGHT_ALIGN_CHECK))->GetCheck() != 0);\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedHidePercentageCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.hide_percent = (((CButton*)GetDlgItem(IDC_HIDE_PERCENTAGE_CHECK))->GetCheck() != 0);\n}\n\n\nafx_msg LRESULT CTaskBarSettingsDlg::OnStaticClicked(WPARAM wParam, LPARAM lParam)\n{\n    switch (::GetDlgCtrlID(((CWnd*)wParam)->m_hWnd))\n    {\n    case IDC_TEXT_COLOR_STATIC1:        //点击“文本颜色”时\n    {\n        //设置文本颜色\n        if (m_data.specify_each_item_color)\n        {\n            CTaskbarColorDlg colorDlg(m_data.text_colors);\n            if (colorDlg.DoModal() == IDOK)\n            {\n                m_data.text_colors = colorDlg.GetColors();\n                DrawStaticColor();\n                m_style_modified = true;\n            }\n        }\n        else if (!m_data.text_colors.empty())\n        {\n            CMFCColorDialogEx colorDlg(m_data.text_colors.begin()->second.label, 0, this);\n            if (colorDlg.DoModal() == IDOK)\n            {\n                m_data.text_colors.begin()->second.label = colorDlg.GetColor();\n                if (m_data.back_color == m_data.text_colors.begin()->second.label)\n                    MessageBox(CCommon::LoadText(IDS_SAME_TEXT_BACK_COLOR_WARNING), NULL, MB_ICONWARNING);\n                DrawStaticColor();\n                m_style_modified = true;\n            }\n        }\n        break;\n    }\n    case IDC_TEXT_COLOR_STATIC2:        //点击“背景颜色”时\n    {\n        //设置背景颜色\n        CMFCColorDialogEx colorDlg(m_data.back_color, 0, this);\n        if (colorDlg.DoModal() == IDOK)\n        {\n            bool background_transparent = m_data.IsTaskbarTransparent();\n            m_data.back_color = colorDlg.GetColor();\n            if (m_data.back_color == m_data.text_colors.begin()->second.label)\n                MessageBox(CCommon::LoadText(IDS_SAME_BACK_TEXT_COLOR_WARNING), NULL, MB_ICONWARNING);\n            if (background_transparent)\n            {\n                CCommon::TransparentColorConvert(m_data.back_color);\n                //如果当前设置了背景透明，则更改了背景色后同时将透明色设置成和背景色一样的颜色，以保持背景透明\n                m_data.transparent_color = m_data.back_color;\n            }\n            DrawStaticColor();\n            m_style_modified = true;\n        }\n        break;\n    }\n    //case IDC_TRANSPARENT_COLOR_STATIC:        //点击“透明色”时\n    //{\n    //  CMFCColorDialogEx colorDlg(m_data.transparent_color, 0, this);\n    //  if (colorDlg.DoModal() == IDOK)\n    //  {\n    //      m_data.transparent_color = colorDlg.GetColor();\n    //      DrawStaticColor();\n    //  }\n    //  break;\n    //}\n    case IDC_TEXT_COLOR_STATIC3:        //点击“状态条颜色”时\n    {\n        CMFCColorDialogEx colorDlg(m_data.status_bar_color, 0, this);\n        if (colorDlg.DoModal() == IDOK)\n        {\n            m_data.status_bar_color = colorDlg.GetColor();\n\n            //更改了资源占用图的颜色后，去掉“跟随Windows主题颜色”的勾选\n            CheckDlgButton(IDC_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK, FALSE);\n            m_data.graph_color_following_system = false;\n\n            DrawStaticColor();\n            m_style_modified = true;\n        }\n        break;\n    }\n    default:\n        break;\n    }\n    return 0;\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedSpecifyEachItemColorCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.specify_each_item_color = (((CButton*)GetDlgItem(IDC_SPECIFY_EACH_ITEM_COLOR_CHECK))->GetCheck() != 0);\n    DrawStaticColor();\n    m_style_modified = true;\n}\n\n\nvoid CTaskBarSettingsDlg::OnCbnSelchangeDoubleClickCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.double_click_action = static_cast<DoubleClickAction>(m_double_click_combo.GetCurSel());\n    EnableControl();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedHorizontalArrangeCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.horizontal_arrange = (((CButton*)GetDlgItem(IDC_HORIZONTAL_ARRANGE_CHECK))->GetCheck() != 0);\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedShowStatusBarCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.show_status_bar = (((CButton*)GetDlgItem(IDC_SHOW_STATUS_BAR_CHECK))->GetCheck() != 0);\n    EnableControl();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedSeparateValueUnitCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.separate_value_unit_with_space = (((CButton*)GetDlgItem(IDC_SEPARATE_VALUE_UNIT_CHECK))->GetCheck() != 0);\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedUnitByteRadio()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.unit_byte = true;\n    IniUnitCombo();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedUnitBitRadio()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.unit_byte = false;\n    IniUnitCombo();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedShowToolTipChk()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.show_tool_tip = (((CButton*)GetDlgItem(IDC_SHOW_TOOL_TIP_CHK))->GetCheck() != 0);\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedDefaultStyleButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CWnd* pBtn = GetDlgItem(IDC_DEFAULT_STYLE_BUTTON);\n    CPoint point;\n    if (pBtn != nullptr)\n    {\n        CRect rect;\n        pBtn->GetWindowRect(rect);\n        point.x = rect.left;\n        point.y = rect.bottom;\n        m_default_style_menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);\n    }\n}\n\n\nvoid CTaskBarSettingsDlg::OnDestroy()\n{\n    CTabDlg::OnDestroy();\n\n    // TODO: 在此处添加消息处理程序代码\n    theApp.m_taskbar_default_style.SaveConfig();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedBrowseButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CString szFilter = CCommon::LoadText(IDS_EXE_FILTER);\n    CFileDialogEx fileDlg(TRUE, NULL, szFilter);\n    if (IDOK == fileDlg.DoModal())\n    {\n        m_data.double_click_exe = fileDlg.GetPathName();\n        SetDlgItemText(IDC_EXE_PATH_EDIT, m_data.double_click_exe.c_str());\n    }\n}\n\nvoid CTaskBarSettingsDlg::OnBnClickedCMGraphPLOTRadio()\n{\n    m_data.cm_graph_type = true;\n}\n\nvoid CTaskBarSettingsDlg::OnBnClickedCMGraphBarRadio()\n{\n    m_data.cm_graph_type = false;\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedBackgroundTransparentCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    bool checked = (m_background_transparent_chk.GetCheck() != 0);\n    m_data.SetTaskabrTransparent(checked);\n    m_style_modified = true;\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedAutoAdaptSettingsButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CAutoAdaptSettingsDlg dlg(m_data);\n    dlg.DoModal();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedAutoAdaptLightThemeCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.auto_adapt_light_theme = (m_atuo_adapt_light_theme_chk.GetCheck() != 0);\n    EnableControl();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedAutoSetBackColorCheck()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.auto_set_background_color = (m_auto_set_back_color_chk.GetCheck() != 0);\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedDisplayTextSettingButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CDisplayTextSettingDlg dlg(m_data.disp_str);\n    dlg.DoModal();\n}\n\n\nvoid CTaskBarSettingsDlg::OnCbnSelchangeMemoryDisplayCombo()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.memory_display = static_cast<MemoryDisplay>(m_memory_display_combo.GetCurSel());\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedShowDashedBox()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    m_data.show_graph_dashed_box = (IsDlgButtonChecked(IDC_SHOW_DASHED_BOX) != 0);\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedSetOrderButton()\n{\n    // TODO: 在此添加控件通知处理程序代码\n    CSetItemOrderDlg dlg;\n    dlg.SetItemOrder(m_data.item_order.GetItemOrderConst());\n    dlg.SetDisplayItem(m_data.display_item);\n    dlg.SetPluginDisplayItem(m_data.plugin_display_item);\n    if (dlg.DoModal() == IDOK)\n    {\n        m_data.item_order.SetOrder(dlg.GetItemOrder());\n        m_data.display_item = dlg.GetDisplayItem();\n        m_data.plugin_display_item = dlg.GetPluginDisplayItem();\n    }\n}\n\n\nvoid CTaskBarSettingsDlg::OnEnChangeItemSpaceEdit()\n{\n    // TODO:  如果该控件是 RICHEDIT 控件，它将不\n    // 发送此通知，除非重写 CTabDlg::OnInitDialog()\n    // 函数并调用 CRichEditCtrl().SetEventMask()，\n    // 同时将 ENM_CHANGE 标志“或”运算到掩码中。\n\n    // TODO:  在此添加控件通知处理程序代码\n    m_data.item_space = m_item_space_edit.GetValue();\n    m_data.ValidItemSpace();\n}\n\nvoid CTaskBarSettingsDlg::OnEnChangeVerticalMarginEdit()\n{\n    m_data.vertical_margin = m_vertical_margin_edit.GetValue();\n    m_data.ValidVerticalMargin();\n}\n\nBOOL CTaskBarSettingsDlg::OnCommand(WPARAM wParam, LPARAM lParam)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    UINT cmd = LOWORD(wParam);\n\n    if (cmd >= ID_DEFAULT_STYLE1 && cmd < ID_DEFAULT_STYLE_MAX)\n    {\n        int default_style = cmd - ID_DEFAULT_STYLE1;\n        ApplyDefaultStyle(default_style);\n    }\n    if (cmd >= ID_MODIFY_DEFAULT_STYLE1 && cmd < ID_MODIFY_DEFAULT_STYLE_MAX)\n    {\n        int default_style = cmd - ID_MODIFY_DEFAULT_STYLE1;\n        if (MessageBox(CCommon::LoadTextFormat(IDS_SAVE_DEFAULT_STYLE_INQUIRY, { default_style + 1 }), NULL, MB_ICONQUESTION | MB_YESNO) == IDYES)\n        {\n            ModifyDefaultStyle(default_style);\n        }\n    }\n\n    return CTabDlg::OnCommand(wParam, lParam);\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedShowNetSpeedFigureCheck()\n{\n    m_data.show_netspeed_figure = (IsDlgButtonChecked(IDC_SHOW_NET_SPEED_FIGURE_CHECK) != 0);\n    EnableControl();\n}\n\n\nvoid CTaskBarSettingsDlg::OnCbnSelchangeNetSpeedFigureMaxValueUnitCombo()\n{\n    m_data.netspeed_figure_max_value_unit = m_net_speed_figure_max_val_unit_combo.GetCurSel();\n}\n\n\nvoid CTaskBarSettingsDlg::OnEnChangeNetSpeedFigureMaxValueEdit()\n{\n    m_data.netspeed_figure_max_value = m_net_speed_figure_max_val_edit.GetValue();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedGdiRadio()\n{\n    m_data.disable_d2d = true;\n    EnableControl();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedD2dRadio()\n{\n    m_data.disable_d2d = false;\n    EnableControl();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedEnableColorEmojiCheck()\n{\n    m_data.enable_colorful_emoji = (IsDlgButtonChecked(IDC_ENABLE_COLOR_EMOJI_CHECK) != FALSE);\n}\n\n\nvoid CTaskBarSettingsDlg::OnCbnSelchangeDigitNumberCombo()\n{\n    //获取数据位数的设置\n    m_data.digits_number = m_digit_number_combo.GetCurSel() + 3;\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedWin11SettingsButton()\n{\n    CWin11TaskbarSettingDlg dlg(m_data);\n    dlg.DoModal();\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedTaskbarWndInSecondaryDisplayCheck()\n{\n    m_data.show_taskbar_wnd_in_secondary_display = (IsDlgButtonChecked(IDC_TASKBAR_WND_IN_SECONDARY_DISPLAY_CHECK) != FALSE);\n}\n\n\nvoid CTaskBarSettingsDlg::OnCbnSelchangeDisplayToShowTaskbarWndCombo()\n{\n    \n    int combo_index = m_displays_combo.GetCurSel();\n    if (combo_index == 0)\n    {\n        m_data.show_taskbar_wnd_in_secondary_display = false;\n    }\n    else\n    {\n        m_data.show_taskbar_wnd_in_secondary_display = true;\n        m_data.secondary_display_index = combo_index - 1;\n\n    }\n}\n\n\nvoid CTaskBarSettingsDlg::OnBnClickedUsageGraphFollowSystemCheck()\n{\n    m_data.graph_color_following_system = (IsDlgButtonChecked(IDC_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK) != FALSE);\n    DrawStaticColor();\n}\n\n\nvoid CTaskBarSettingsDlg::OnEnChangeFontSizeEdit1()\n{\n    m_data.font.size = m_font_size_edit.GetValue();\n}\n"
  },
  {
    "path": "TrafficMonitor/TaskBarSettingsDlg.h",
    "content": "﻿#pragma once\r\n#include \"ColorStatic.h\"\r\n#include \"afxwin.h\"\r\n#include \"SpinEdit.h\"\r\n#include \"TabDlg.h\"\r\n#include \"TaskbarColorDlg.h\"\r\n#include \"ComboBox2.h\"\r\n\r\n// CTaskBarSettingsDlg 对话框\r\n\r\nclass CTaskBarSettingsDlg : public CTabDlg\r\n{\r\n    DECLARE_DYNAMIC(CTaskBarSettingsDlg)\r\n\r\npublic:\r\n    CTaskBarSettingsDlg(CWnd* pParent = NULL);   // 标准构造函数\r\n    virtual ~CTaskBarSettingsDlg();\r\n\r\n    bool IsStyleModified();\r\n\r\n    //如果开启了自动适应Windows10深色/浅色模式功能时，将当前配置保存到对应预设\r\n    void SaveColorSettingToDefaultStyle();\r\n\r\n    //选项设置数据\r\n    TaskBarSettingData m_data;\r\n\r\n\tCWinVersionHelper m_win_version;        //当前Windows的版本\r\n\r\n    // 对话框数据\r\n#ifdef AFX_DESIGN_TIME\r\n    enum { IDD = IDD_TASKBAR_SETTINGS_DIALOG };\r\n#endif\r\n\r\nprotected:\r\n    //控件变量\r\n    CColorStatic m_text_color_static;\r\n    CColorStatic m_back_color_static;\r\n    CColorStatic m_trans_color_static;\r\n    CColorStatic m_status_bar_color_static;\r\n    CToolTipCtrl m_toolTip;\r\n    CComboBox2 m_unit_combo;\r\n    CButton m_hide_unit_chk;\r\n    CSpinEdit m_font_size_edit;\r\n    CComboBox2 m_double_click_combo;\r\n    CComboBox2 m_digit_number_combo;\r\n    CMenu m_default_style_menu;\r\n    CMenu m_modify_default_style_menu;\r\n    CButton m_background_transparent_chk;\r\n    CButton m_atuo_adapt_light_theme_chk;\r\n    CButton m_auto_set_back_color_chk;\r\n    CComboBox2 m_memory_display_combo;\r\n    CSpinEdit m_item_space_edit;\r\n    CSpinEdit m_vertical_margin_edit;\r\n    CSpinEdit m_net_speed_figure_max_val_edit;\r\n    CComboBox2 m_net_speed_figure_max_val_unit_combo;\r\n    CComboBox2 m_displays_combo;\r\n\r\n    bool m_style_modified{};\r\n\r\nprotected:\r\n    void DrawStaticColor();\r\n    void IniUnitCombo();\r\n\r\n    void ApplyDefaultStyle(int index);      //应用一个预设方案\r\n\r\npublic:\r\n    void ModifyDefaultStyle(int index);     //将当前颜色设置保存到一个预设方案\r\n\r\nprotected:\r\n    void EnableControl();\r\n    virtual void SetControlMouseWheelEnable(bool enable) override;\r\n    virtual bool InitializeControls() override;\r\n\r\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\r\n\r\n    DECLARE_MESSAGE_MAP()\r\npublic:\r\n    virtual BOOL OnInitDialog();\r\n    afx_msg void OnBnClickedSetFontButton1();\r\n    afx_msg void OnBnClickedTaskbarWndOnLeftCheck();\r\n    afx_msg void OnBnClickedSpeedShortModeCheck();\r\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\r\n    afx_msg void OnCbnSelchangeUnitCombo();\r\n    afx_msg void OnBnClickedHideUnitCheck();\r\n    virtual void OnOK();\r\n    afx_msg void OnBnClickedValueRightAlignCheck();\r\n    afx_msg void OnBnClickedHidePercentageCheck();\r\nprotected:\r\n    afx_msg LRESULT OnStaticClicked(WPARAM wParam, LPARAM lParam);\r\npublic:\r\n    afx_msg void OnBnClickedSpecifyEachItemColorCheck();\r\n    afx_msg void OnCbnSelchangeDoubleClickCombo();\r\n    afx_msg void OnBnClickedHorizontalArrangeCheck();\r\n    afx_msg void OnBnClickedShowStatusBarCheck();\r\n    afx_msg void OnBnClickedSeparateValueUnitCheck();\r\n    afx_msg void OnBnClickedUnitByteRadio();\r\n    afx_msg void OnBnClickedUnitBitRadio();\r\n    afx_msg void OnBnClickedShowToolTipChk();\r\n    afx_msg void OnBnClickedDefaultStyleButton();\r\n    afx_msg void OnDestroy();\r\n    afx_msg void OnBnClickedBrowseButton();\r\n    afx_msg void OnBnClickedCMGraphBarRadio();\r\n    afx_msg void OnBnClickedCMGraphPLOTRadio();\r\n    afx_msg void OnBnClickedBackgroundTransparentCheck();\r\n    afx_msg void OnBnClickedAutoAdaptSettingsButton();\r\n    afx_msg void OnBnClickedAutoAdaptLightThemeCheck();\r\n    afx_msg void OnBnClickedAutoSetBackColorCheck();\r\n    afx_msg void OnBnClickedDisplayTextSettingButton();\r\n    afx_msg void OnCbnSelchangeMemoryDisplayCombo();\r\n    afx_msg void OnBnClickedShowDashedBox();\r\n    afx_msg void OnBnClickedSetOrderButton();\r\n    afx_msg void OnEnChangeItemSpaceEdit();\r\n    afx_msg void OnEnChangeVerticalMarginEdit();\r\n    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);\r\n    afx_msg void OnBnClickedShowNetSpeedFigureCheck();\r\n    afx_msg void OnCbnSelchangeNetSpeedFigureMaxValueUnitCombo();\r\n    afx_msg void OnEnChangeNetSpeedFigureMaxValueEdit();\r\n    afx_msg void OnBnClickedGdiRadio();\r\n    afx_msg void OnBnClickedD2dRadio();\r\n    afx_msg void OnBnClickedEnableColorEmojiCheck();\r\n    afx_msg void OnCbnSelchangeDigitNumberCombo();\r\n    afx_msg void OnBnClickedWin11SettingsButton();\r\n    afx_msg void OnBnClickedTaskbarWndInSecondaryDisplayCheck();\r\n    afx_msg void OnCbnSelchangeDisplayToShowTaskbarWndCombo();\r\n    afx_msg void OnBnClickedUsageGraphFollowSystemCheck();\r\n    afx_msg void OnEnChangeFontSizeEdit1();\r\n};\r\n"
  },
  {
    "path": "TrafficMonitor/TaskbarColorDlg.cpp",
    "content": "﻿// TaskbarColorDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"TaskbarColorDlg.h\"\n#include \"afxdialogex.h\"\n#include \"CMFCColorDialogEx.h\"\n\n\n// CTaskbarColorDlg 对话框\n\nIMPLEMENT_DYNAMIC(CTaskbarColorDlg, CBaseDialog)\n\nCTaskbarColorDlg::CTaskbarColorDlg(const std::map<CommonDisplayItem, TaskbarItemColor>& colors, CWnd* pParent /*=NULL*/)\n\t: CBaseDialog(IDD_TASKBAR_COLOR_DIALOG, pParent), m_colors(colors)\n{\n}\n\nCTaskbarColorDlg::~CTaskbarColorDlg()\n{\n}\n\nCString CTaskbarColorDlg::GetDialogName() const\n{\n    return _T(\"TaskbarColorDlg\");\n}\n\nvoid CTaskbarColorDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_LIST1, m_list_ctrl);\n}\n\n\nBEGIN_MESSAGE_MAP(CTaskbarColorDlg, CBaseDialog)\n    ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CTaskbarColorDlg::OnNMDblclkList1)\nEND_MESSAGE_MAP()\n\n\n// CTaskbarColorDlg 消息处理程序\n\n\nBOOL CTaskbarColorDlg::OnInitDialog()\n{\n\tCBaseDialog::OnInitDialog();\n\n\t// TODO:  在此添加额外的初始化\n\n    SetIcon(theApp.GetMenuIcon(IDI_TASKBAR_WINDOW), FALSE);\t\t// 设置小图标\n\n    //初始化列表控件\n    CRect rect;\n    m_list_ctrl.GetClientRect(rect);\n    m_list_ctrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);\n    int width0 = rect.Width() /2;\n    int width1 = (rect.Width() - width0 - theApp.DPI(20) - 1) / 2;\n    int width2 = rect.Width() - width0 - width1 - theApp.DPI(20) - 1;\n    m_list_ctrl.InsertColumn(0, CCommon::LoadText(IDS_ITEM), LVCFMT_LEFT, width0);\n    m_list_ctrl.InsertColumn(1, CCommon::LoadText(IDS_COLOR_LABEL), LVCFMT_LEFT, width1);\n    m_list_ctrl.InsertColumn(2, CCommon::LoadText(IDS_COLOR_VALUE), LVCFMT_LEFT, width2);\n    m_list_ctrl.SetDrawItemRangMargin(theApp.DPI(2));\n\n    //向列表中插入行\n    for (auto iter = theApp.m_plugins.AllDisplayItemsWithPlugins().begin(); iter != theApp.m_plugins.AllDisplayItemsWithPlugins().end(); ++iter)\n    {\n        CString item_name = iter->GetItemName();\n        if (!item_name.IsEmpty())\n        {\n            int index = m_list_ctrl.GetItemCount();\n            m_list_ctrl.InsertItem(index, item_name);\n            m_list_ctrl.SetItemColor(index, 1, m_colors[*iter].label);\n            m_list_ctrl.SetItemColor(index, 2, m_colors[*iter].value);\n            m_list_ctrl.SetItemData(index, (DWORD_PTR)&(*iter));\n        }\n    }\n\n\treturn TRUE;  // return TRUE unless you set the focus to a control\n\t\t\t\t  // 异常: OCX 属性页应返回 FALSE\n}\n\n\n\nvoid CTaskbarColorDlg::OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)\n{\n    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\n    // TODO: 在此添加控件通知处理程序代码\n    int index = pNMItemActivate->iItem;\n    int col = pNMItemActivate->iSubItem;\n    if (col == 1 || col == 2)\n    {\n        COLORREF color = m_list_ctrl.GetItemColor(index, col);\n        CMFCColorDialogEx colorDlg(color, 0, this);\n        if (colorDlg.DoModal() == IDOK)\n        {\n            color = colorDlg.GetColor();\n            m_list_ctrl.SetItemColor(index, col, color);\n            CommonDisplayItem* item = (CommonDisplayItem*)(m_list_ctrl.GetItemData(index));\n            if (col == 1)\n                m_colors[*item].label = color;\n            else\n                m_colors[*item].value = color;\n        }\n    }\n\n    *pResult = 0;\n}\n"
  },
  {
    "path": "TrafficMonitor/TaskbarColorDlg.h",
    "content": "﻿#pragma once\n#include \"ColorStatic.h\"\n#include \"afxwin.h\"\n#include \"ColorSettingListCtrl.h\"\n#include \"BaseDialog.h\"\n\n// CTaskbarColorDlg 对话框\n\nclass CTaskbarColorDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CTaskbarColorDlg)\n\npublic:\n\tCTaskbarColorDlg(const std::map<CommonDisplayItem, TaskbarItemColor>& colors, CWnd* pParent = NULL);   // 标准构造函数\n\tvirtual ~CTaskbarColorDlg();\n\n    const std::map<CommonDisplayItem, TaskbarItemColor>& GetColors() const { return m_colors; }\n\n\t// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_TASKBAR_COLOR_DIALOG };\n#endif\n\nprotected:\n    std::map<CommonDisplayItem, TaskbarItemColor> m_colors;\n    CColorSettingListCtrl m_list_ctrl;\n\n    virtual CString GetDialogName() const override;\n\nprotected:\n\tvirtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n\tDECLARE_MESSAGE_MAP()\npublic:\n\tvirtual BOOL OnInitDialog();\n    afx_msg void OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult);\n};\n"
  },
  {
    "path": "TrafficMonitor/TaskbarDefaultStyle.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"TaskbarDefaultStyle.h\"\n#include \"SettingsHelper.h\"\n#include \"TrafficMonitor.h\"\n#include \"WindowsSettingHelper.h\"\n\nCTaskbarDefaultStyle::CTaskbarDefaultStyle()\n{\n}\n\nCTaskbarDefaultStyle::~CTaskbarDefaultStyle()\n{\n\tSaveConfig();\n}\n\nvoid CTaskbarDefaultStyle::LoadConfig()\n{\n    CSettingsHelper ini;\n    for (int i = 0; i < TASKBAR_DEFAULT_STYLE_NUM; i++)\n\t{\n        COLORREF default_text_color = (TASKBAR_DEFAULT_LIGHT_STYLE(i) ? RGB(0, 0, 0) : RGB(255, 255, 255));\n        COLORREF darkmode_default_back_color = 0;\n        if (theApp.m_win_version.IsWindows8Or8point1())\n            darkmode_default_back_color = RGB(0, 0, 1);\n        COLORREF default_back_color = (TASKBAR_DEFAULT_LIGHT_STYLE(i) ? RGB(210, 210, 211) : darkmode_default_back_color);\n        COLORREF default_transparent_color = (TASKBAR_DEFAULT_LIGHT_STYLE(i) ? RGB(210, 210, 211) : darkmode_default_back_color);\n        COLORREF default_status_bar_color = (TASKBAR_DEFAULT_LIGHT_STYLE(i) ? RGB(165, 165, 165) : 0x005A5A5A);\n        wchar_t buff[64];\n        swprintf_s(buff, L\"default%d_\", i + 1);\n        wstring key_name = buff;\n\n        bool specify_each_item_color_default = false;\n        //为预设2和预设3设置默认的文本颜色\n        if (i == 1)\n        {\n            const wchar_t* str_default_text_color = L\"4574711,16777215,5107653,16777215,16632499,16777215,16494036,16777215,14601983,16777215,16760992,10221779,13425662,16777215,4574711,16777215,\";\n            ini.LoadTaskbarWndColors(L\"taskbar_default_style\", (key_name + L\"text_color\").c_str(), m_default_style[i].text_colors, str_default_text_color);\n            specify_each_item_color_default = true;\n        }\n        else if (i == 2)\n        {\n            const wchar_t* str_default_text_color = L\"31957,0,2533120,0,13857281,0,14354551,0,1145775,0,4328380,0,167504,0,31957,0,\";\n            ini.LoadTaskbarWndColors(L\"taskbar_default_style\", (key_name + L\"text_color\").c_str(), m_default_style[i].text_colors, str_default_text_color);\n            specify_each_item_color_default = true;\n        }\n        else\n        {\n            ini.LoadTaskbarWndColors(L\"taskbar_default_style\", (key_name + L\"text_color\").c_str(), m_default_style[i].text_colors, default_text_color);\n        }\n        m_default_style[i].back_color = ini.GetInt(L\"taskbar_default_style\", (key_name + L\"back_color\").c_str(), default_back_color);\n        m_default_style[i].transparent_color = ini.GetInt(L\"taskbar_default_style\", (key_name + L\"transparent_color\").c_str(), default_transparent_color);\n        m_default_style[i].status_bar_color = ini.GetInt(L\"taskbar_default_style\", (key_name + L\"status_bar_color\").c_str(), default_status_bar_color);\n        m_default_style[i].specify_each_item_color = ini.GetBool(L\"taskbar_default_style\", (key_name + L\"specify_each_item_color\").c_str(), specify_each_item_color_default);\n\t}\n}\n\nvoid CTaskbarDefaultStyle::SaveConfig() const\n{\n    CSettingsHelper ini;\n    for (int i = 0; i < TASKBAR_DEFAULT_STYLE_NUM; i++)\n\t{\n\t\twchar_t buff[64];\n\t\tswprintf_s(buff, L\"default%d_\", i + 1);\n\t\twstring key_name = buff;\n        if (IsTaskBarStyleDataValid(m_default_style[i]))           //保存前检查当前颜色预设是否有效\n        {\n            ini.SaveTaskbarWndColors(L\"taskbar_default_style\", (key_name + L\"text_color\").c_str(), m_default_style[i].text_colors);\n            ini.WriteInt(L\"taskbar_default_style\", (key_name + L\"back_color\").c_str(), m_default_style[i].back_color);\n            ini.WriteInt(L\"taskbar_default_style\", (key_name + L\"transparent_color\").c_str(), m_default_style[i].transparent_color);\n            ini.WriteInt(L\"taskbar_default_style\", (key_name + L\"status_bar_color\").c_str(), m_default_style[i].status_bar_color);\n            ini.WriteBool(L\"taskbar_default_style\", (key_name + L\"specify_each_item_color\").c_str(), m_default_style[i].specify_each_item_color);\n        }\n        else\n        {\n            //写入日志\n            CString log_str;\n            log_str.Format(_T(\"在保存预设%d时检测到背景色和文字颜色都为黑色，该预设未被保存。\"), i);\n            CCommon::WriteLog(log_str, theApp.m_log_path.c_str());\n            return;\n        }\n\t}\n\tini.Save();\n}\n\nvoid CTaskbarDefaultStyle::ApplyDefaultStyle(int index, TaskBarSettingData & data) const\n{\n    /*if (index == TASKBAR_DEFAULT_LIGHT_STYLE_INDEX)\n    {\n        ApplyDefaultLightStyle(data);\n    }\n    else */if (index >= 0 && index < TASKBAR_DEFAULT_STYLE_NUM)\n\t{\n        if (!IsTaskBarStyleDataValid(m_default_style[index]))\n            return;\n\n        data.text_colors = m_default_style[index].text_colors;\n\t\tdata.back_color = m_default_style[index].back_color;\n\t\tdata.transparent_color = m_default_style[index].transparent_color;\n\t\tdata.status_bar_color = m_default_style[index].status_bar_color;\n\t\tdata.specify_each_item_color = m_default_style[index].specify_each_item_color;\n\t\tif (data.transparent_color == data.back_color)\n\t\t{\n\t\t\tCCommon::TransparentColorConvert(data.back_color);\n\t\t\tCCommon::TransparentColorConvert(data.transparent_color);\n\t\t}\n\t}\n}\n\n//void CTaskbarDefaultStyle::ApplyDefaultLightStyle(TaskBarSettingData& data)\n//{\n//\tfor (auto& item : data.text_colors)\n//    {\n//        item.second.label = RGB(0, 0, 0);\n//        item.second.value = RGB(0, 0, 0);\n//    }\n//\tdata.back_color = RGB(210, 210, 211);\n//\tdata.transparent_color = RGB(210, 210, 211);\n//\tdata.status_bar_color = RGB(165, 165, 165);\n//}\n\nvoid CTaskbarDefaultStyle::ModifyDefaultStyle(int index, TaskBarSettingData & data)\n{\n\tif (index < 0 || index >= TASKBAR_DEFAULT_STYLE_NUM)\n\t\treturn;\n\n    m_default_style[index].text_colors = data.text_colors;\n\tm_default_style[index].back_color = data.back_color;\n\tm_default_style[index].transparent_color = data.transparent_color;\n\tm_default_style[index].status_bar_color = data.status_bar_color;\n\tm_default_style[index].specify_each_item_color = data.specify_each_item_color;\n}\n\nbool CTaskbarDefaultStyle::IsTaskBarStyleDataValid(const TaskBarStyleData& data)\n{\n    for (const auto& item : data.text_colors)\n    {\n        if (item.second.label != data.back_color || item.second.value != data.back_color)\n            return true;\n    }\n    return false;     //如果文本颜色全部等于背景颜色，则该颜色预设无效\n}\n"
  },
  {
    "path": "TrafficMonitor/TaskbarDefaultStyle.h",
    "content": "﻿#pragma once\n#include \"CommonData.h\"\n\n#define TASKBAR_DEFAULT_STYLE_NUM 4\n#define TASKBAR_DEFAULT_LIGHT_STYLE_INDEX 3\n#define TASKBAR_DEFAULT_LIGHT_STYLE(i) (i == 2 || i == 3)       //定义预设3和预设4为浅色模式的预设\n\nclass CTaskbarDefaultStyle\n{\npublic:\n\tstruct TaskBarStyleData\n\t{\n        std::map<CommonDisplayItem, TaskbarItemColor> text_colors{};\n\t\tCOLORREF back_color{};\n\t\tCOLORREF transparent_color{};\n\t\tCOLORREF status_bar_color{};\n\t\tbool specify_each_item_color{};\n\t};\n\n\tCTaskbarDefaultStyle();\n\t~CTaskbarDefaultStyle();\n\n\tvoid LoadConfig();\n\tvoid SaveConfig() const;\n\n\tvoid ApplyDefaultStyle(int index, TaskBarSettingData& data) const;\t\t//应用一个颜色预设\n\t//static void ApplyDefaultLightStyle(TaskBarSettingData& data);\t\t//应用默认的浅色模式预设\n\tvoid ModifyDefaultStyle(int index, TaskBarSettingData& data);     //将当前颜色设置保存到一个预设方案\n\n    static bool IsTaskBarStyleDataValid(const TaskBarStyleData& data);     //判断一个颜色模式是否有效\n\nprivate:\n\tTaskBarStyleData m_default_style[TASKBAR_DEFAULT_STYLE_NUM];    //预设样式\n\n};\n"
  },
  {
    "path": "TrafficMonitor/TaskbarHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"TaskbarHelper.h\"\n#include <algorithm>\n\n// 存储显示器信息\nstruct MonitorInfo\n{\n    HMONITOR hMonitor;\n    CRect rect;\n};\n\n// 存储任务栏信息\nstruct TaskbarInfo\n{\n    HWND hwnd;\n    CRect rect;\n};\n\nstd::vector<MonitorInfo> monitors;\nstd::vector<TaskbarInfo> taskbars;\n\n// 枚举显示器的回调函数\nstatic BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)\n{\n    MonitorInfo info;\n    info.hMonitor = hMonitor;\n    info.rect = *lprcMonitor;\n    if (!info.rect.IsRectEmpty())\n        monitors.push_back(info);\n    else\n        ASSERT(FALSE);\n    return TRUE;\n}\n\n// 枚举窗口的回调函数\nstatic BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)\n{\n    TCHAR className[256];\n    GetClassName(hwnd, className, 256);\n\n    // 检查是否是副显示器的任务栏\n    if (_tcscmp(className, _T(\"Shell_SecondaryTrayWnd\")) == 0)\n    {\n        TaskbarInfo info;\n        info.hwnd = hwnd;\n        GetWindowRect(hwnd, &info.rect);\n        taskbars.push_back(info);\n    }\n\n    return TRUE;\n}\n\n// 比较函数：按显示器的左上角坐标排序\nstatic bool CompareTaskbarByMonitorOrder(const TaskbarInfo& a, const TaskbarInfo& b)\n{\n    // 遍历所有显示器\n    for (const auto& monitor : monitors)\n    {\n        // 检查任务栏 a 是否在当前显示器内\n        bool aInMonitor = (a.rect.left >= monitor.rect.left && a.rect.top >= monitor.rect.top);\n        // 检查任务栏 b 是否在当前显示器内\n        bool bInMonitor = (b.rect.left >= monitor.rect.left && b.rect.top >= monitor.rect.top);\n\n        // 如果 a 在当前显示器内而 b 不在，则 a 应该在 b 前面\n        if (aInMonitor && !bInMonitor)\n            return true;\n        // 如果 b 在当前显示器内而 a 不在，则 b 应该在 a 前面\n        if (bInMonitor && !aInMonitor)\n            return false;\n        // 如果 a 和 b 都在当前显示器内，则按任务栏的位置排序\n        if (aInMonitor && bInMonitor)\n        {\n            if (a.rect.left != b.rect.left)\n                return a.rect.left < b.rect.left;\n            return a.rect.top < b.rect.top;\n        }\n    }\n    // 默认情况下，a 和 b 相等\n    return false;\n}\n\nvoid CTaskbarHelper::GetAllSecondaryDisplayTaskbar(std::vector<HWND>& secondary_taskbars)\n{\n    monitors.clear();\n    taskbars.clear();\n    secondary_taskbars.clear();\n\n    // 获取所有显示器信息\n    EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, 0);\n\n    // 获取所有任务栏句柄\n    EnumWindows(EnumWindowsProc, 0);\n\n    // 按显示器顺序对任务栏排序\n    std::sort(taskbars.begin(), taskbars.end(), CompareTaskbarByMonitorOrder);\n\n    //保存任务栏句柄\n    for (const auto& taskbar : taskbars)\n    {\n        secondary_taskbars.push_back(taskbar.hwnd);\n    }\n}\n\nint CTaskbarHelper::GetDisplayNum()\n{\n    monitors.clear();\n    EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, 0);\n    return static_cast<int>(monitors.size());\n}\n\nint CTaskbarHelper::GetSecondaryTaskbarNum()\n{\n    taskbars.clear();\n    EnumWindows(EnumWindowsProc, 0);\n    return static_cast<int>(taskbars.size());\n}\n"
  },
  {
    "path": "TrafficMonitor/TaskbarHelper.h",
    "content": "﻿#pragma once\n#include <vector>\nclass CTaskbarHelper\n{\npublic:\n    //获取所有副显示器上的任务栏，并确保按显示器的顺序\n    static void GetAllSecondaryDisplayTaskbar(std::vector<HWND>& secondary_taskbars);\n\n    //获取显示器数量\n    static int GetDisplayNum();\n\n    //获取副显示器任务栏的数量\n    static int GetSecondaryTaskbarNum();\n};\n\n"
  },
  {
    "path": "TrafficMonitor/TaskbarItemOrderHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"TaskbarItemOrderHelper.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n\n//////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////////////////////////////////////////////////\n\nCTaskbarItemOrderHelper::CTaskbarItemOrderHelper(bool displayed_only)\n    : m_displayed_only(displayed_only)\n{\n}\n\nvoid CTaskbarItemOrderHelper::Init()\n{\n    for (const auto& item : theApp.m_plugins.AllDisplayItemsWithPlugins())\n    {\n        m_all_item_in_default_order.push_back(item);\n    }\n}\n\nstd::vector<CommonDisplayItem> CTaskbarItemOrderHelper::GetAllDisplayItemsWithOrder() const\n{\n    std::vector<CommonDisplayItem> items;\n    for (auto i : m_item_order)\n    {\n        if (i >= 0 && i < static_cast<int>(m_all_item_in_default_order.size()))\n        {\n            if (m_displayed_only && !IsItemDisplayed(m_all_item_in_default_order[i]))\n            {\n                continue;\n            }\n            items.push_back(m_all_item_in_default_order[i]);\n        }\n    }\n\n    return items;\n}\n\nvoid CTaskbarItemOrderHelper::FromString(const std::wstring& str)\n{\n    m_item_order.clear();\n    std::vector<std::wstring> str_list;\n    CCommon::StringSplit(str, L',', str_list);\n    for (const auto& s : str_list)\n    {\n        m_item_order.push_back(_wtoi(s.c_str()));\n    }\n    NormalizeItemOrder();\n}\n\nstd::wstring CTaskbarItemOrderHelper::ToString() const\n{\n    std::wstring result;\n    for (int i : m_item_order)\n    {\n        result += std::to_wstring(i);\n        result.push_back(L',');\n    }\n    if (!m_item_order.empty())\n        result.pop_back();\n    return result;\n}\n\nvoid CTaskbarItemOrderHelper::SetOrder(const vector<int>& item_order)\n{\n    m_item_order = item_order;\n    NormalizeItemOrder();\n}\n\nconst vector<int>& CTaskbarItemOrderHelper::GetItemOrderConst() const\n{\n    return m_item_order;\n}\n\nvector<int>& CTaskbarItemOrderHelper::GetItemOrder()\n{\n    return m_item_order;\n}\n\nCString CTaskbarItemOrderHelper::GetItemDisplayName(CommonDisplayItem item)\n{\n    return item.GetItemName();\n}\n\nbool CTaskbarItemOrderHelper::IsItemDisplayed(CommonDisplayItem item)\n{\n    bool displayed = true;\n    if (!item.IsPlugin())\n    {\n        if ((item == TDI_CPU_TEMP) && !theApp.m_general_data.IsHardwareEnable(HI_CPU))\n            displayed = false;\n        if ((item == TDI_GPU_TEMP) && !theApp.m_general_data.IsHardwareEnable(HI_GPU))\n            displayed = false;\n        if ((item == TDI_HDD_TEMP) && !theApp.m_general_data.IsHardwareEnable(HI_HDD))\n            displayed = false;\n        if (item == TDI_MAIN_BOARD_TEMP && !theApp.m_general_data.IsHardwareEnable(HI_MBD))\n            displayed = false;\n    }\n\n    return displayed;\n}\n\nvoid CTaskbarItemOrderHelper::NormalizeItemOrder()\n{\n    //检查是否有超出范围的序号\n    int item_num = static_cast<int>(theApp.m_plugins.AllDisplayItemsWithPlugins().size());\n    for (auto iter = m_item_order.begin(); iter != m_item_order.end();)\n    {\n        if (*iter < 0 || *iter >= item_num)\n            iter = m_item_order.erase(iter);\n        else\n            ++iter;\n    }\n    //删除不显示的序号\n    if (m_displayed_only)\n    {\n        for (auto iter = m_item_order.begin(); iter != m_item_order.end();)\n        {\n            if (*iter >= 0 && *iter < static_cast<int>(m_all_item_in_default_order.size()))\n            {\n                CommonDisplayItem item = m_all_item_in_default_order[*iter];\n                if (!IsItemDisplayed(item))\n                {\n                    iter = m_item_order.erase(iter);\n                    continue;\n                }\n            }\n            ++iter;\n        }\n    }\n    //删除重复的序号\n    CCommon::RemoveVectorDuplicateItem(m_item_order);\n    //检查是否有缺少的序号\n    for (int i = 0; i < item_num; i++)\n    {\n        auto iter = std::find(m_item_order.begin(), m_item_order.end(), i);\n        if (iter == m_item_order.end())\n            m_item_order.push_back(i);\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/TaskbarItemOrderHelper.h",
    "content": "﻿#pragma once\n#include \"DisplayItem.h\"\n\nclass CTaskbarItemOrderHelper\n{\npublic:\n    CTaskbarItemOrderHelper(bool displayed_only = false);\n\n    void Init();\n\n    //根据设定的顺序获取任务窗口每个显示项目\n    std::vector<CommonDisplayItem> GetAllDisplayItemsWithOrder() const;\n\n    void FromString(const std::wstring& str);\n    std::wstring ToString() const;\n    void SetOrder(const vector<int>& item_order);\n    const vector<int>& GetItemOrderConst() const;\n    vector<int>& GetItemOrder();\n\n    static CString GetItemDisplayName(CommonDisplayItem item);\n    static bool IsItemDisplayed(CommonDisplayItem item);\n\nprivate:\n    //规范m_item_order里的项目，如果m_item_order里有序号超过了显示项目的个数，则将其移除，并在后面添加缺少的项目的序号\n    void NormalizeItemOrder();\n\nprivate:\n    vector<int> m_item_order;   //保存每个项目的顺序\n    vector<CommonDisplayItem> m_all_item_in_default_order;    //以默认顺序保存的所有显示项目\n    bool m_displayed_only;\n};\n"
  },
  {
    "path": "TrafficMonitor/Test.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"Test.h\"\n#include \"Common.h\"\n#include \"SkinFile.h\"\n#include \"TrafficMonitor.h\"\n#include \"IniHelper.h\"\n#include \"PluginUpdateHelper.h\"\n#include \"MessageDlg.h\"\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////\nstatic void TestHttpQequest()\n{\n    wstring result;\n    bool rtn = CCommon::GetURL(L\"https://v4.yinghualuo.cn/bejson\", result, true, L\"TrafficMonitor_V1.78\");\n    int a = 0;\n}\n\nstatic void TestGetLicense()\n{\n    CString license_str;\n    HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_LICENSE), _T(\"TEXT\"));\n    if (hRes != NULL)\n    {\n        HGLOBAL hglobal = LoadResource(NULL, hRes);\n        if (hglobal != NULL)\n        {\n            license_str = CCommon::StrToUnicode((const char*)hglobal, true).c_str();\n            int a = 0;\n        }\n    }\n}\n\nstatic void TestSkin()\n{\n    CSkinFile skin;\n    skin.Load(L\"0默认皮肤\");\n    int a = 0;\n}\n\nstatic void TestCrash()\n{\n    CString* pStr = nullptr;\n    int a = pStr->GetLength();\n    printf(\"%d\", a);\n\n}\n\nstatic void TestPlugin()\n{\n    if (!theApp.m_plugins.GetPlugins().empty())\n    {\n        theApp.m_plugins.GetPlugins()[0].plugin->ShowOptionsDialog(theApp.m_pMainWnd->m_hWnd);\n    }\n}\n\nstatic void TestDate()\n{\n    Date d;\n    d.year = 2021;\n    d.month = 1;\n    d.day = 4;\n    int week = d.week();\n    int a = 0;\n}\n\nstatic void TestIni()\n{\n    CIniHelper ini(L\"D:\\\\Temp\\\\config.ini\");\n    ini.RemoveSection(L\"skin_360悬浮窗dark\");\n    ini.Save();\n    int a = 0;\n}\n\nstatic void TestPluginVersion()\n{\n    ASSERT(PluginVersion(L\"1.0.0\") == PluginVersion(L\"1.00\"));\n    ASSERT(PluginVersion(L\"1.2\") < PluginVersion(L\"1.20\"));\n    ASSERT(PluginVersion(L\"0.8.0\") < PluginVersion(L\"1.00\"));\n    ASSERT(PluginVersion(L\"1.0.3\") < PluginVersion(L\"1.03\"));\n\n    //CPluginUpdateHelper helper;\n    //helper.CheckForUpdate();\n    //int a = 0;\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////\nCTest::CTest()\n{\n}\n\nCTest::~CTest()\n{\n}\n\nvoid CTest::Test()\n{\n    //TestHttpQequest();\n    //TestGetLicense();\n    //TestSkin();\n    //TestCrash();\n    //TestDate();\n    //TestIni();\n    TestPluginVersion();\n}\n\nvoid CTest::TestCommand()\n{\n    //TestPlugin();\n\n    //测试消息对话框\n    CMessageDlg dlg;\n    dlg.SetWindowTitle(_T(\"System Info\"));\n    dlg.SetInfoText(_T(\"System Information for TrafficMonitor.\"));\n    dlg.SetMessageText(theApp.GetSystemInfoString().GetString());\n    dlg.SetStandarnMessageIcon(CMessageDlg::SI_INFORMATION);\n    dlg.DoModal();\n}\n"
  },
  {
    "path": "TrafficMonitor/Test.h",
    "content": "﻿#pragma once\nclass CTest\n{\npublic:\n    CTest();\n    ~CTest();\n\n    static void Test();\n    static void TestCommand();\n};\n"
  },
  {
    "path": "TrafficMonitor/TinyXml2Helper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"TinyXml2Helper.h\"\n#include \"Common.h\"\n\nbool CTinyXml2Helper::LoadXmlFile(tinyxml2::XMLDocument& doc, const wchar_t* file_path)\n{\n    //由于XMLDocument::LoadFile函数不支持Unicode，因此这里自行读取文件内容，并调用XMLDocument::Parse函数解析\n    size_t length;\n    const char* xml_contents = CCommon::GetFileContent(file_path, length);\n    auto err = doc.Parse(xml_contents, length);\n    delete[] xml_contents;\n    return err == tinyxml2::XML_SUCCESS;\n}\n\nvoid CTinyXml2Helper::IterateChildNode(tinyxml2::XMLElement* ele, std::function<void(tinyxml2::XMLElement*)> fun)\n{\n    if (ele == nullptr)\n        return;\n\n    tinyxml2::XMLElement* child = ele->FirstChildElement();\n    if (child == nullptr)\n        return;\n    fun(child);\n    while (true)\n    {\n        child = child->NextSiblingElement();\n        if (child != nullptr)\n            fun(child);\n        else\n            break;\n    }\n}\n\nconst char * CTinyXml2Helper::ElementAttribute(tinyxml2::XMLElement * ele, const char * attr)\n{\n    if (ele != nullptr)\n    {\n        const char* str = ele->Attribute(attr);\n        if (str != nullptr)\n            return str;\n    }\n    return \"\";\n}\n\nconst char* CTinyXml2Helper::ElementName(tinyxml2::XMLElement* ele)\n{\n    if (ele != nullptr)\n    {\n        const char* str = ele->Name();\n        if (str != nullptr)\n            return str;\n    }\n    return \"\";\n}\n\nconst char* CTinyXml2Helper::ElementText(tinyxml2::XMLElement* ele)\n{\n    if (ele != nullptr)\n    {\n        const char* str = ele->GetText();\n        if (str != nullptr)\n            return str;\n    }\n    return \"\";\n}\n\nbool CTinyXml2Helper::StringToBool(const char* str)\n{\n    string str_text{ str };\n    return (!str_text.empty() && str_text != \"0\");\n}\n\n"
  },
  {
    "path": "TrafficMonitor/TinyXml2Helper.h",
    "content": "﻿#pragma once\n#include \"tinyxml2/tinyxml2.h\"\n#include <string>\n#include <functional>\n\nclass CTinyXml2Helper\n{\npublic:\n\n    //从文件读取XML内容\n    static bool LoadXmlFile(tinyxml2::XMLDocument& doc, const wchar_t* file_path);\n\n    //遍历一个XML节点\n    //fun: 一个函数对象，遍历到一个节点时被调用\n    static void IterateChildNode(tinyxml2::XMLElement* ele, std::function<void(tinyxml2::XMLElement*)> fun);\n\n    //获取一个节点的属性（返回值不会为空指针，如果找不到则返回空字符串）\n    static const char* ElementAttribute(tinyxml2::XMLElement* ele, const char* attr);\n\n    //获取一个节点的名称（返回值不会为空指针，如果找不到则返回空字符串）\n    static const char* ElementName(tinyxml2::XMLElement* ele);\n\n    //获取一个节点的文本（返回值不会为空指针，如果找不到则返回空字符串）\n    static const char* ElementText(tinyxml2::XMLElement* ele);\n\n    static bool StringToBool(const char* str);\n};\n"
  },
  {
    "path": "TrafficMonitor/TrafficMonitor.cpp",
    "content": "﻿\n// TrafficMonitor.cpp : 定义应用程序的类行为。\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"TrafficMonitorDlg.h\"\n#include \"crashtool.h\"\n#include \"UpdateHelper.h\"\n#include \"Test.h\"\n#include \"WIC.h\"\n#include \"auto_start_helper.h\"\n#include \"AppAlreadyRuningDlg.h\"\n#include \"WindowsSettingHelper.h\"\n#include \"SkinManager.h\"\n#include \"SettingsHelper.h\"\n#ifndef DISABLE_WINDOWS_WEB_EXPERIENCE_DETECTOR\n#include \"winrt/base.h\"\n#endif\n#include <gdiplus.h>\n\n#ifdef _DEBUG\n#define new DEBUG_NEW\n#endif\n\n\n// CTrafficMonitorApp\n\nBEGIN_MESSAGE_MAP(CTrafficMonitorApp, CWinApp)\n    //ON_COMMAND(ID_HELP, &CWinApp::OnHelp)\n    ON_COMMAND(ID_HELP, &CTrafficMonitorApp::OnHelp)\n    ON_COMMAND(ID_FREQUENTY_ASKED_QUESTIONS, &CTrafficMonitorApp::OnFrequentyAskedQuestions)\n    ON_COMMAND(ID_UPDATE_LOG, &CTrafficMonitorApp::OnUpdateLog)\nEND_MESSAGE_MAP()\n\n\nCTrafficMonitorApp* CTrafficMonitorApp::self = NULL;\n\n\n// CTrafficMonitorApp 构造\nCTrafficMonitorApp::CTrafficMonitorApp()\n{\n    self = this;\n    // 支持重新启动管理器\n    //m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;\n\n    // TODO: 在此处添加构造代码，\n    // 将所有重要的初始化放置在 InitInstance 中\n    CRASHREPORT::StartCrashReport();\n#ifndef DISABLE_WINDOWS_WEB_EXPERIENCE_DETECTOR\n    if (m_win_version.IsWindows11OrLater())\n        winrt::init_apartment();\n#endif\n\n    CheckWindows11Taskbar();\n    m_theme_color = CCommon::GetWindowsThemeColor();\n}\n\nvoid CTrafficMonitorApp::LoadLanguageConfig()\n{\n    CIniHelper ini{ m_config_path };\n    m_general_data.language = static_cast<WORD>(ini.GetInt(_T(\"general\"), _T(\"language\"), 0));\n}\n\nvoid CTrafficMonitorApp::LoadConfig()\n{\n    CSettingsHelper ini;\n\n    //常规设置\n    m_general_data.check_update_when_start = ini.GetBool(_T(\"general\"), _T(\"check_update_when_start\"), true);\n    //m_general_data.allow_skin_cover_font = ini.GetBool(_T(\"general\"), _T(\"allow_skin_cover_font\"), true);\n    //m_general_data.allow_skin_cover_text = ini.GetBool(_T(\"general\"), _T(\"allow_skin_cover_text\"), true);\n    m_general_data.show_all_interface = ini.GetBool(L\"general\", L\"show_all_interface\", false);\n    bool is_chinese_language{ m_str_table.IsSimplifiedChinese() };     //当前语言是否为简体中文\n    m_general_data.update_source = ini.GetInt(L\"general\", L\"update_source\", is_chinese_language ? 1 : 0);   //如果当前语言为简体，则默认更新源为Gitee，否则为GitHub\n    //载入获取CPU利用率的方式，默认使用性能计数器获取\n    m_general_data.cpu_usage_acquire_method = static_cast<GeneralSettingData::CpuUsageAcquireMethod>(ini.GetInt(L\"general\", L\"cpu_usage_acquire_method\", GeneralSettingData::CA_PDH));\n    //Lite版获取CPU利用率的方式不能为“通过硬件监控”\n#ifdef WITHOUT_TEMPERATURE\n    if (m_general_data.cpu_usage_acquire_method == GeneralSettingData::CA_HARDWARE_MONITOR)\n        m_general_data.cpu_usage_acquire_method = GeneralSettingData::CA_CPU_TIME;\n#endif\n\n    m_general_data.monitor_time_span = ini.GetInt(L\"general\", L\"monitor_time_span\", 1000);\n    if (m_general_data.monitor_time_span < MONITOR_TIME_SPAN_MIN || m_general_data.monitor_time_span > MONITOR_TIME_SPAN_MAX)\n        m_general_data.monitor_time_span = 1000;\n    m_general_data.hard_disk_name = ini.GetString(L\"general\", L\"hard_disk_name\", L\"\");\n    m_general_data.cpu_core_name = ini.GetString(L\"general\", L\"cpu_core_name\", L\"Core Average\");\n    m_general_data.hardware_monitor_item = ini.GetInt(L\"general\", L\"hardware_monitor_item\", 0);\n    std::vector<std::wstring> connections_hide;\n    ini.GetStringList(L\"general\", L\"connections_hide\", connections_hide, std::vector<std::wstring>{});\n    m_general_data.connections_hide.FromVector(connections_hide);\n\n    //Windows10颜色模式设置\n    bool is_windows10_light_theme = CWindowsSettingHelper::IsWindows10LightTheme();\n    if (is_windows10_light_theme)\n        CCommon::SetColorMode(ColorMode::Light);\n    else\n        CCommon::SetColorMode(ColorMode::Default);\n\n    //主窗口设置\n    m_cfg_data.m_transparency = ini.GetInt(_T(\"config\"), _T(\"transparency\"), 80);\n    m_main_wnd_data.m_always_on_top = ini.GetBool(_T(\"config\"), _T(\"always_on_top\"), true);\n    m_main_wnd_data.m_lock_window_pos = ini.GetBool(_T(\"config\"), _T(\"lock_window_pos\"), false);\n    m_general_data.show_notify_icon = ini.GetBool(_T(\"config\"), _T(\"show_notify_icon\"), true);\n    m_cfg_data.m_show_more_info = ini.GetBool(_T(\"config\"), _T(\"show_cpu_memory\"), false);\n    m_main_wnd_data.m_mouse_penetrate = ini.GetBool(_T(\"config\"), _T(\"mouse_penetrate\"), false);\n    m_cfg_data.m_show_task_bar_wnd = ini.GetBool(_T(\"config\"), _T(\"show_task_bar_wnd\"), false);\n    m_cfg_data.m_position_x = ini.GetInt(_T(\"config\"), _T(\"position_x\"), -1);\n    m_cfg_data.m_position_y = ini.GetInt(_T(\"config\"), _T(\"position_y\"), -1);\n    m_cfg_data.m_auto_select = ini.GetBool(_T(\"connection\"), _T(\"auto_select\"), true);\n    m_cfg_data.m_select_all = ini.GetBool(_T(\"connection\"), _T(\"select_all\"), false);\n    m_cfg_data.m_hide_main_window = ini.GetBool(_T(\"config\"), _T(\"hide_main_window\"), false);\n    m_cfg_data.m_connection_name = CCommon::UnicodeToStr(ini.GetString(L\"connection\", L\"connection_name\", L\"\").c_str());\n    m_cfg_data.m_skin_name = ini.GetString(_T(\"config\"), _T(\"skin_selected\"), _T(\"\"));\n    if (m_cfg_data.m_skin_name.substr(0, 8) == L\".\\\\skins\\\\\")       //如果读取到的皮肤名称前面有\".\\\\skins\\\\\"，则把它删除。（用于和前一个版本保持兼容性）\n        m_cfg_data.m_skin_name = m_cfg_data.m_skin_name.substr(7);\n    CSkinManager::SkinNameNormalize(m_cfg_data.m_skin_name);\n\n    m_cfg_data.skin_auto_adapt = ini.GetBool(L\"skins\", L\"skin_auto_adapt\", false);\n    m_cfg_data.skin_name_dark_mode = ini.GetString(L\"skins\", L\"skin_name_dark_mode\", L\"\");\n    m_cfg_data.skin_name_light_mode = ini.GetString(L\"skins\", L\"skin_name_light_mode\", L\"\");\n\n    m_cfg_data.m_notify_icon_selected = ini.GetInt(_T(\"config\"), _T(\"notify_icon_selected\"), (m_win_version.IsWindows7() || m_win_version.IsWindows8Or8point1() ? 2 : m_cfg_data.m_dft_notify_icon));       //Win7/8/8.1默认使用蓝色通知区图标，因为隐藏通知区图标后白色图标会看不清，其他系统默认使用白色图标\n    m_cfg_data.m_notify_icon_auto_adapt = ini.GetBool(_T(\"config\"), _T(\"notify_icon_auto_adapt\"), true);\n    if (m_cfg_data.m_notify_icon_auto_adapt)\n        AutoSelectNotifyIcon();\n    m_main_wnd_data.swap_up_down = ini.GetBool(_T(\"config\"), _T(\"swap_up_down\"), false);\n    m_main_wnd_data.hide_main_wnd_when_fullscreen = ini.GetBool(_T(\"config\"), _T(\"hide_main_wnd_when_fullscreen\"), true);\n\n    //由于主窗口的文本颜色、字体、显示文本设置不再从配置文件读取，这些设置保存在每个皮肤的单独设置中，因此这里只将它们初始化为固定的值\n    m_main_wnd_data.text_colors[TDI_UP] = RGB(255, 255, 255);\n    m_main_wnd_data.specify_each_item_color = false;\n    m_main_wnd_data.font.name = m_str_table.GetLanguageInfo().default_font_name.c_str();\n    m_main_wnd_data.font.size = 10;\n    m_main_wnd_data.disp_str.Get(TDI_UP) = CCommon::LoadText(IDS_UPLOAD_DISP, L\": \");\n    m_main_wnd_data.disp_str.Get(TDI_DOWN) = CCommon::LoadText(IDS_DOWNLOAD_DISP, L\": \");\n    m_main_wnd_data.disp_str.Get(TDI_CPU) = L\"CPU: \";\n    m_main_wnd_data.disp_str.Get(TDI_MEMORY) = CCommon::LoadText(IDS_MEMORY_DISP, _T(\": \"));\n\n    m_main_wnd_data.speed_short_mode = ini.GetBool(_T(\"config\"), _T(\"speed_short_mode\"), false);\n    m_main_wnd_data.separate_value_unit_with_space = ini.GetBool(_T(\"config\"), _T(\"separate_value_unit_with_space\"), true);\n    m_main_wnd_data.show_tool_tip = ini.GetBool(_T(\"config\"), _T(\"show_tool_tip\"), true);\n    m_main_wnd_data.memory_display = static_cast<MemoryDisplay>(ini.GetInt(L\"config\", L\"memory_display\", static_cast<int>(MemoryDisplay::USAGE_PERCENTAGE)));\n    m_main_wnd_data.unit_byte = ini.GetBool(_T(\"config\"), _T(\"unit_byte\"), true);\n    m_main_wnd_data.speed_unit = static_cast<SpeedUnit>(ini.GetInt(_T(\"config\"), _T(\"speed_unit\"), 0));\n    m_main_wnd_data.hide_unit = ini.GetBool(_T(\"config\"), _T(\"hide_unit\"), false);\n    m_main_wnd_data.hide_percent = ini.GetBool(_T(\"config\"), _T(\"hide_percent\"), false);\n    m_main_wnd_data.double_click_action = static_cast<DoubleClickAction>(ini.GetInt(_T(\"config\"), _T(\"double_click_action\"), 0));\n    m_main_wnd_data.double_click_exe = ini.GetString(L\"config\", L\"double_click_exe\", (theApp.m_system_dir + L\"\\\\Taskmgr.exe\").c_str());\n\n    m_main_wnd_data.m_alow_out_of_border = ini.GetBool(_T(\"config\"), _T(\"alow_out_of_border\"), false);\n\n    m_general_data.traffic_tip_enable = ini.GetBool(L\"notify_tip\", L\"traffic_tip_enable\", false);\n    m_general_data.traffic_tip_value = ini.GetInt(L\"notify_tip\", L\"traffic_tip_value\", 200);\n    m_general_data.traffic_tip_unit = ini.GetInt(L\"notify_tip\", L\"traffic_tip_unit\", 0);\n    m_general_data.memory_usage_tip.enable = ini.GetBool(L\"notify_tip\", L\"memory_usage_tip_enable\", false);\n    m_general_data.memory_usage_tip.tip_value = ini.GetInt(L\"notify_tip\", L\"memory_tip_value\", 80);\n    m_general_data.cpu_temp_tip.enable = ini.GetBool(L\"notify_tip\", L\"cpu_temperature_tip_enable\", false);\n    m_general_data.cpu_temp_tip.tip_value = ini.GetInt(L\"notify_tip\", L\"cpu_temperature_tip_value\", 80);\n    m_general_data.gpu_temp_tip.enable = ini.GetBool(L\"notify_tip\", L\"gpu_temperature_tip_enable\", false);\n    m_general_data.gpu_temp_tip.tip_value = ini.GetInt(L\"notify_tip\", L\"gpu_temperature_tip_value\", 80);\n    m_general_data.hdd_temp_tip.enable = ini.GetBool(L\"notify_tip\", L\"hdd_temperature_tip_enable\", false);\n    m_general_data.hdd_temp_tip.tip_value = ini.GetInt(L\"notify_tip\", L\"hdd_temperature_tip_value\", 80);\n    m_general_data.mainboard_temp_tip.enable = ini.GetBool(L\"notify_tip\", L\"mainboard_temperature_tip_enable\", false);\n    m_general_data.mainboard_temp_tip.tip_value = ini.GetInt(L\"notify_tip\", L\"mainboard_temperature_tip_value\", 80);\n\n    //任务栏窗口设置\n    m_taskbar_data.back_color = ini.GetInt(_T(\"task_bar\"), _T(\"task_bar_back_color\"), m_taskbar_data.dft_back_color);\n    m_taskbar_data.transparent_color = ini.GetInt(_T(\"task_bar\"), _T(\"transparent_color\"), m_taskbar_data.dft_transparent_color);\n    if (m_taskbar_data.IsTaskbarTransparent()) //如果任务栏背景透明，则需要将颜色转换一下\n    {\n        CCommon::TransparentColorConvert(m_taskbar_data.back_color);\n        CCommon::TransparentColorConvert(m_taskbar_data.transparent_color);\n    }\n    m_taskbar_data.status_bar_color = ini.GetInt(_T(\"task_bar\"), _T(\"status_bar_color\"), m_taskbar_data.dft_status_bar_color);\n    //m_taskbar_data.text_color = GetPrivateProfileInt(_T(\"task_bar\"), _T(\"task_bar_text_color\"), 0x00ffffffU, m_config_path.c_str());\n    ini.LoadTaskbarWndColors(_T(\"task_bar\"), _T(\"task_bar_text_color\"), m_taskbar_data.text_colors, m_taskbar_data.dft_text_colors);\n    m_taskbar_data.specify_each_item_color = ini.GetBool(L\"task_bar\", L\"specify_each_item_color\", false);\n    //m_cfg_data.m_tbar_show_cpu_memory = ini.GetBool(_T(\"task_bar\"), _T(\"task_bar_show_cpu_memory\"), false);\n    m_taskbar_data.display_item.FromInt(ini.GetInt(L\"task_bar\", L\"tbar_display_item\", DisplayItemSet{ TDI_UP, TDI_DOWN }.ToInt()));\n    m_taskbar_data.show_taskbar_wnd_in_secondary_display = ini.GetBool(L\"task_bar\", L\"show_taskbar_wnd_in_secondary_display\", false);\n    m_taskbar_data.secondary_display_index = ini.GetInt(L\"task_bar\", L\"secondary_display_index\", 0);\n\n    //不含温度监控的版本，不显示温度监控相关项目\n#ifdef WITHOUT_TEMPERATURE\n    m_taskbar_data.display_item.Remove(TDI_CPU_TEMP);\n    m_taskbar_data.display_item.Remove(TDI_GPU_TEMP);\n    m_taskbar_data.display_item.Remove(TDI_HDD_TEMP);\n    m_taskbar_data.display_item.Remove(TDI_MAIN_BOARD_TEMP);\n#endif\n\n    //如果选项设置中关闭了某个硬件监控，则不显示对应的温度监控相关项目\n    if (!m_general_data.IsHardwareEnable(HI_CPU))\n        m_taskbar_data.display_item.Remove(TDI_CPU_TEMP);\n    if (!m_general_data.IsHardwareEnable(HI_GPU))\n    {\n        m_taskbar_data.display_item.Remove(TDI_GPU_TEMP);\n    }\n    if (!m_general_data.IsHardwareEnable(HI_HDD))\n    {\n        m_taskbar_data.display_item.Remove(TDI_HDD_TEMP);\n    }\n    if (!m_general_data.IsHardwareEnable(HI_MBD))\n        m_taskbar_data.display_item.Remove(TDI_MAIN_BOARD_TEMP);\n\n    //m_taskbar_data.swap_up_down = ini.GetBool(_T(\"task_bar\"), _T(\"task_bar_swap_up_down\"), false);\n\n    if (m_taskbar_data.back_color == 0 && !m_taskbar_data.text_colors.empty() && m_taskbar_data.text_colors.begin()->second.label == 0)     //万一读取到的背景色和文本颜色都为0（黑色），则将文本色和背景色设置成默认颜色\n    {\n        m_taskbar_data.back_color = m_taskbar_data.dft_back_color;\n        m_taskbar_data.text_colors.begin()->second.label = m_taskbar_data.dft_text_colors;\n    }\n\n    FontInfo default_font;\n    default_font.name = m_str_table.GetLanguageInfo().default_font_name.c_str();\n    default_font.size = 9;\n    ini.LoadFontData(_T(\"task_bar\"), m_taskbar_data.font, default_font);\n\n    //载入显示文本设置\n    ini.LoadDisplayStr(L\"task_bar\", m_taskbar_data.disp_str, false);\n    ini.LoadPluginDisplayStr(L\"plugin_display_str_taskbar_window\", m_taskbar_data.disp_str, false);\n\n    m_taskbar_data.tbar_wnd_on_left = ini.GetBool(_T(\"task_bar\"), _T(\"task_bar_wnd_on_left\"), false);\n    m_taskbar_data.speed_short_mode = ini.GetBool(_T(\"task_bar\"), _T(\"task_bar_speed_short_mode\"), false);\n    m_taskbar_data.tbar_wnd_snap = ini.GetBool(_T(\"task_bar\"), _T(\"task_bar_wnd_snap\"), false);\n    m_taskbar_data.unit_byte = ini.GetBool(_T(\"task_bar\"), _T(\"unit_byte\"), true);\n    m_taskbar_data.speed_unit = static_cast<SpeedUnit>(ini.GetInt(_T(\"task_bar\"), _T(\"task_bar_speed_unit\"), 0));\n    m_taskbar_data.hide_unit = ini.GetBool(_T(\"task_bar\"), _T(\"task_bar_hide_unit\"), false);\n    m_taskbar_data.hide_percent = ini.GetBool(_T(\"task_bar\"), _T(\"task_bar_hide_percent\"), false);\n    m_taskbar_data.value_right_align = ini.GetBool(_T(\"task_bar\"), _T(\"value_right_align\"), true);\n    m_taskbar_data.horizontal_arrange = ini.GetBool(_T(\"task_bar\"), _T(\"horizontal_arrange\"), false);\n    m_taskbar_data.show_status_bar = ini.GetBool(_T(\"task_bar\"), _T(\"show_status_bar\"), false);\n    m_taskbar_data.separate_value_unit_with_space = ini.GetBool(_T(\"task_bar\"), _T(\"separate_value_unit_with_space\"), true);\n    m_taskbar_data.show_tool_tip = ini.GetBool(_T(\"task_bar\"), _T(\"show_tool_tip\"), true);\n    m_taskbar_data.digits_number = ini.GetInt(_T(\"task_bar\"), _T(\"digits_number\"), 4);\n    m_taskbar_data.memory_display = static_cast<MemoryDisplay>(ini.GetInt(L\"task_bar\", L\"memory_display\", static_cast<int>(MemoryDisplay::USAGE_PERCENTAGE)));\n    m_taskbar_data.double_click_action = static_cast<DoubleClickAction>(ini.GetInt(_T(\"task_bar\"), _T(\"double_click_action\"), 0));\n    m_taskbar_data.double_click_exe = ini.GetString(L\"task_bar\", L\"double_click_exe\", (theApp.m_system_dir + L\"\\\\Taskmgr.exe\").c_str());\n    m_taskbar_data.cm_graph_type = ini.GetBool(_T(\"task_bar\"), _T(\"cm_graph_type\"), true);\n    m_taskbar_data.show_graph_dashed_box = ini.GetBool(L\"task_bar\", L\"show_graph_dashed_box\", false);\n    m_taskbar_data.item_space = ini.GetInt(L\"task_bar\", L\"item_space\", 8);\n    m_taskbar_data.vertical_margin = ini.GetInt(L\"task_bar\", L\"vertical_margin\", 0);\n    m_taskbar_data.window_offset_top = ini.GetInt(L\"task_bar\", L\"window_offset_top\", 0);\n    m_taskbar_data.window_offset_left = ini.GetInt(L\"task_bar\", L\"window_offset_left\", 0);\n    m_taskbar_data.ValidItemSpace();\n    m_taskbar_data.ValidWindowOffsetTop();\n    m_taskbar_data.ValidWindowOffsetLeft();\n    m_taskbar_data.avoid_overlap_with_widgets = ini.GetBool(_T(\"task_bar\"), _T(\"avoid_overlap_with_widgets\"), false);\n    m_taskbar_data.taskbar_left_space_win11 = ini.GetInt(L\"task_bar\", L\"taskbar_left_space_win11\", 160);\n    m_taskbar_data.taskbar_right_space_win11 = ini.GetInt(L\"task_bar\", L\"taskbar_right_space_win11\", 280);\n\n    if (m_win_version.IsWindows10OrLater())     //只有Win10才支持自动适应系统深色/浅色主题\n        m_taskbar_data.auto_adapt_light_theme = ini.GetBool(L\"task_bar\", L\"auto_adapt_light_theme\", false);\n    else\n        m_taskbar_data.auto_adapt_light_theme = false;\n    m_taskbar_data.dark_default_style = ini.GetInt(L\"task_bar\", L\"dark_default_style\", 0);\n    m_taskbar_data.light_default_style = ini.GetInt(L\"task_bar\", L\"light_default_style\", TASKBAR_DEFAULT_LIGHT_STYLE_INDEX);\n\n    if (m_win_version.IsWindows8OrLater())\n        m_taskbar_data.auto_set_background_color = ini.GetBool(L\"task_bar\", L\"auto_set_background_color\", false);\n    else\n        m_taskbar_data.auto_set_background_color = false;\n\n    m_taskbar_data.item_order.Init();\n    m_taskbar_data.item_order.FromString(ini.GetString(L\"task_bar\", L\"item_order\", L\"\"));\n    m_taskbar_data.plugin_display_item.FromString(ini.GetString(L\"task_bar\", L\"plugin_display_item\", L\"\"));\n    m_taskbar_data.auto_save_taskbar_color_settings_to_preset = ini.GetBool(L\"task_bar\", L\"auto_save_taskbar_color_settings_to_preset\", true);\n\n    m_taskbar_data.show_netspeed_figure = ini.GetBool(L\"task_bar\", L\"show_netspeed_figure\", false);\n    m_taskbar_data.netspeed_figure_max_value = ini.GetInt(L\"task_bar\", L\"netspeed_figure_max_value\", 512);\n    m_taskbar_data.netspeed_figure_max_value_unit = ini.GetInt(L\"task_bar\", L\"netspeed_figure_max_value_unit\", 0);\n    m_taskbar_data.graph_color_following_system = ini.GetBool(L\"task_bar\", L\"graph_color_following_system\", false);\n\n    if (CTaskBarDlgDrawCommonSupport::CheckSupport())\n        m_taskbar_data.disable_d2d = ini.GetBool(L\"task_bar\", L\"disable_d2d\", true);\n    else\n        m_taskbar_data.disable_d2d = true;\n    m_taskbar_data.enable_colorful_emoji = ini.GetBool(L\"task_bar\", L\"enable_colorful_emoji\", true);\n\n    //其他设置\n    //m_cfg_data.m_show_internet_ip = ini.GetBool(L\"connection_details\", L\"show_internet_ip\", false);\n    m_cfg_data.m_use_log_scale = ini.GetBool(_T(\"histroy_traffic\"), _T(\"use_log_scale\"), true);\n    m_cfg_data.m_sunday_first = ini.GetBool(_T(\"histroy_traffic\"), _T(\"sunday_first\"), true);\n    m_cfg_data.m_view_type = static_cast<HistoryTrafficViewType>(ini.GetInt(_T(\"histroy_traffic\"), _T(\"view_type\"), static_cast<int>(HistoryTrafficViewType::HV_DAY)));\n\n    m_no_multistart_warning = ini.GetBool(_T(\"other\"), _T(\"no_multistart_warning\"), false);\n    m_notify_interval = ini.GetInt(_T(\"other\"), _T(\"notify_interval\"), 60);\n    m_exit_when_start_by_restart_manager = ini.GetBool(_T(\"other\"), _T(\"exit_when_start_by_restart_manager\"), true);\n    m_debug_log = ini.GetBool(_T(\"other\"), _T(\"debug_log\"), false);\n    //由于Win7系统中设置任务栏窗口透明色会导致任务栏窗口不可见，因此默认在Win7中禁用透明色的设定\n    m_taksbar_transparent_color_enable = ini.GetBool(L\"other\", L\"taksbar_transparent_color_enable\", !m_win_version.IsWindows7());\n    m_last_light_mode = ini.GetBool(L\"other\", L\"last_light_mode\", CWindowsSettingHelper::IsWindows10LightTheme());\n    m_show_mouse_panetrate_tip = ini.GetBool(L\"other\", L\"show_mouse_panetrate_tip\", true);\n    m_show_dot_net_notinstalled_tip = ini.GetBool(L\"other\", L\"show_dot_net_notinstalled_tip\", true);\n}\n\nvoid CTrafficMonitorApp::SaveConfig()\n{\n    CSettingsHelper ini;\n\n    //常规设置\n    ini.WriteBool(_T(\"general\"), _T(\"check_update_when_start\"), m_general_data.check_update_when_start);\n    //ini.WriteBool(_T(\"general\"), _T(\"allow_skin_cover_font\"), m_general_data.allow_skin_cover_font);\n    //ini.WriteBool(_T(\"general\"), _T(\"allow_skin_cover_text\"), m_general_data.allow_skin_cover_text);\n    ini.WriteInt(_T(\"general\"), _T(\"language\"), static_cast<int>(m_general_data.language));\n    ini.WriteInt(L\"general\", L\"update_source\", m_general_data.update_source);\n    ini.WriteBool(L\"general\", L\"show_all_interface\", m_general_data.show_all_interface);\n    ini.WriteInt(L\"general\", L\"cpu_usage_acquire_method\", m_general_data.cpu_usage_acquire_method);\n    ini.WriteInt(L\"general\", L\"monitor_time_span\", m_general_data.monitor_time_span);\n    ini.WriteString(L\"general\", L\"hard_disk_name\", m_general_data.hard_disk_name);\n    ini.WriteString(L\"general\", L\"cpu_core_name\", m_general_data.cpu_core_name);\n    ini.WriteInt(L\"general\", L\"hardware_monitor_item\", m_general_data.hardware_monitor_item);\n    ini.WriteStringList(L\"general\", L\"connections_hide\", m_general_data.connections_hide.ToVector());\n\n    //主窗口设置\n    ini.WriteInt(L\"config\", L\"transparency\", m_cfg_data.m_transparency);\n    ini.WriteBool(L\"config\", L\"always_on_top\", m_main_wnd_data.m_always_on_top);\n    ini.WriteBool(L\"config\", L\"lock_window_pos\", m_main_wnd_data.m_lock_window_pos);\n    ini.WriteBool(L\"config\", L\"show_notify_icon\", m_general_data.show_notify_icon);\n    ini.WriteBool(L\"config\", L\"show_cpu_memory\", m_cfg_data.m_show_more_info);\n    ini.WriteBool(L\"config\", L\"mouse_penetrate\", m_main_wnd_data.m_mouse_penetrate);\n    ini.WriteBool(L\"config\", L\"show_task_bar_wnd\", m_cfg_data.m_show_task_bar_wnd);\n    ini.WriteInt(L\"config\", L\"position_x\", m_cfg_data.m_position_x);\n    ini.WriteInt(L\"config\", L\"position_y\", m_cfg_data.m_position_y);\n    ini.WriteBool(L\"connection\", L\"auto_select\", m_cfg_data.m_auto_select);\n    ini.WriteBool(L\"connection\", L\"select_all\", m_cfg_data.m_select_all);\n    //ini.SaveMainWndColors(L\"config\", L\"text_color\", m_main_wnd_data.text_colors);\n    //ini.WriteBool(_T(\"config\"), _T(\"specify_each_item_color\"), m_main_wnd_data.specify_each_item_color);\n    ini.WriteInt(L\"config\", L\"hide_main_window\", m_cfg_data.m_hide_main_window);\n    ini.WriteString(L\"connection\", L\"connection_name\", CCommon::StrToUnicode(m_cfg_data.m_connection_name.c_str()));\n    ini.WriteString(_T(\"config\"), _T(\"skin_selected\"), m_cfg_data.m_skin_name.c_str());\n\n    ini.WriteBool(L\"skins\", L\"skin_auto_adapt\", m_cfg_data.skin_auto_adapt);\n    ini.WriteString(L\"skins\", L\"skin_name_dark_mode\", m_cfg_data.skin_name_dark_mode);\n    ini.WriteString(L\"skins\", L\"skin_name_light_mode\", m_cfg_data.skin_name_light_mode);\n\n    ini.WriteInt(L\"config\", L\"notify_icon_selected\", m_cfg_data.m_notify_icon_selected);\n    ini.WriteBool(L\"config\", L\"notify_icon_auto_adapt\", m_cfg_data.m_notify_icon_auto_adapt);\n\n    //ini.SaveFontData(L\"config\", m_main_wnd_data.font);\n\n    ini.WriteBool(L\"config\", L\"swap_up_down\", m_main_wnd_data.swap_up_down);\n    ini.WriteBool(L\"config\", L\"hide_main_wnd_when_fullscreen\", m_main_wnd_data.hide_main_wnd_when_fullscreen);\n\n    //ini.SaveDisplayStr(L\"config\", m_main_wnd_data.disp_str);\n    //ini.SavePluginDisplayStr(L\"plugin_display_str_main_window\", m_main_wnd_data.disp_str);\n\n    ini.WriteBool(L\"config\", L\"speed_short_mode\", m_main_wnd_data.speed_short_mode);\n    ini.WriteBool(L\"config\", L\"separate_value_unit_with_space\", m_main_wnd_data.separate_value_unit_with_space);\n    ini.WriteBool(L\"config\", L\"show_tool_tip\", m_main_wnd_data.show_tool_tip);\n    ini.WriteInt(L\"config\", L\"memory_display\", static_cast<int>(m_main_wnd_data.memory_display));\n    ini.WriteBool(L\"config\", L\"unit_byte\", m_main_wnd_data.unit_byte);\n    ini.WriteInt(L\"config\", L\"speed_unit\", static_cast<int>(m_main_wnd_data.speed_unit));\n    ini.WriteBool(L\"config\", L\"hide_unit\", m_main_wnd_data.hide_unit);\n    ini.WriteBool(L\"config\", L\"hide_percent\", m_main_wnd_data.hide_percent);\n    ini.WriteInt(L\"config\", L\"double_click_action\", static_cast<int>(m_main_wnd_data.double_click_action));\n    ini.WriteString(L\"config\", L\"double_click_exe\", m_main_wnd_data.double_click_exe);\n\n    ini.WriteInt(L\"config\", L\"alow_out_of_border\", m_main_wnd_data.m_alow_out_of_border);\n\n    ini.WriteBool(L\"notify_tip\", L\"traffic_tip_enable\", m_general_data.traffic_tip_enable);\n    ini.WriteInt(L\"notify_tip\", L\"traffic_tip_value\", m_general_data.traffic_tip_value);\n    ini.WriteInt(L\"notify_tip\", L\"traffic_tip_unit\", m_general_data.traffic_tip_unit);\n    ini.WriteBool(L\"notify_tip\", L\"memory_usage_tip_enable\", m_general_data.memory_usage_tip.enable);\n    ini.WriteInt(L\"notify_tip\", L\"memory_tip_value\", m_general_data.memory_usage_tip.tip_value);\n    ini.WriteBool(L\"notify_tip\", L\"cpu_temperature_tip_enable\", m_general_data.cpu_temp_tip.enable);\n    ini.WriteInt(L\"notify_tip\", L\"cpu_temperature_tip_value\", m_general_data.cpu_temp_tip.tip_value);\n    ini.WriteBool(L\"notify_tip\", L\"gpu_temperature_tip_enable\", m_general_data.gpu_temp_tip.enable);\n    ini.WriteInt(L\"notify_tip\", L\"gpu_temperature_tip_value\", m_general_data.gpu_temp_tip.tip_value);\n    ini.WriteBool(L\"notify_tip\", L\"hdd_temperature_tip_enable\", m_general_data.hdd_temp_tip.enable);\n    ini.WriteInt(L\"notify_tip\", L\"hdd_temperature_tip_value\", m_general_data.hdd_temp_tip.tip_value);\n    ini.WriteBool(L\"notify_tip\", L\"mainboard_temperature_tip_enable\", m_general_data.mainboard_temp_tip.enable);\n    ini.WriteInt(L\"notify_tip\", L\"mainboard_temperature_tip_value\", m_general_data.mainboard_temp_tip.tip_value);\n\n    //任务栏窗口设置\n    ini.WriteInt(L\"task_bar\", L\"task_bar_back_color\", m_taskbar_data.back_color);\n    ini.WriteInt(L\"task_bar\", L\"transparent_color\", m_taskbar_data.transparent_color);\n    ini.WriteInt(L\"task_bar\", L\"status_bar_color\", m_taskbar_data.status_bar_color);\n    ini.SaveTaskbarWndColors(L\"task_bar\", L\"task_bar_text_color\", m_taskbar_data.text_colors);\n    ini.WriteBool(L\"task_bar\", L\"specify_each_item_color\", m_taskbar_data.specify_each_item_color);\n    //ini.WriteBool(L\"task_bar\", L\"task_bar_show_cpu_memory\", m_cfg_data.m_tbar_show_cpu_memory);\n    ini.WriteInt(L\"task_bar\", L\"tbar_display_item\", m_taskbar_data.display_item.ToInt());\n    ini.SaveFontData(L\"task_bar\", m_taskbar_data.font);\n    //ini.WriteBool(L\"task_bar\", L\"task_bar_swap_up_down\", m_taskbar_data.swap_up_down);\n    ini.WriteBool(L\"task_bar\", L\"show_taskbar_wnd_in_secondary_display\", m_taskbar_data.show_taskbar_wnd_in_secondary_display);\n    ini.WriteInt(L\"task_bar\", L\"secondary_display_index\", m_taskbar_data.secondary_display_index);\n\n    ini.SaveDisplayStr(L\"task_bar\", m_taskbar_data.disp_str);\n    ini.SavePluginDisplayStr(L\"plugin_display_str_taskbar_window\", m_taskbar_data.disp_str);\n\n    ini.WriteBool(L\"task_bar\", L\"task_bar_wnd_on_left\", m_taskbar_data.tbar_wnd_on_left);\n    ini.WriteBool(L\"task_bar\", L\"task_bar_wnd_snap\", m_taskbar_data.tbar_wnd_snap);\n    ini.WriteBool(L\"task_bar\", L\"task_bar_speed_short_mode\", m_taskbar_data.speed_short_mode);\n    ini.WriteBool(L\"task_bar\", L\"unit_byte\", m_taskbar_data.unit_byte);\n    ini.WriteInt(L\"task_bar\", L\"task_bar_speed_unit\", static_cast<int>(m_taskbar_data.speed_unit));\n    ini.WriteBool(L\"task_bar\", L\"task_bar_hide_unit\", m_taskbar_data.hide_unit);\n    ini.WriteBool(L\"task_bar\", L\"task_bar_hide_percent\", m_taskbar_data.hide_percent);\n    ini.WriteBool(L\"task_bar\", L\"value_right_align\", m_taskbar_data.value_right_align);\n    ini.WriteBool(L\"task_bar\", L\"horizontal_arrange\", m_taskbar_data.horizontal_arrange);\n    ini.WriteBool(L\"task_bar\", L\"show_status_bar\", m_taskbar_data.show_status_bar);\n    ini.WriteBool(L\"task_bar\", L\"separate_value_unit_with_space\", m_taskbar_data.separate_value_unit_with_space);\n    ini.WriteBool(L\"task_bar\", L\"show_tool_tip\", m_taskbar_data.show_tool_tip);\n    ini.WriteInt(L\"task_bar\", L\"digits_number\", m_taskbar_data.digits_number);\n    ini.WriteInt(L\"task_bar\", L\"memory_display\", static_cast<int>(m_taskbar_data.memory_display));\n    ini.WriteInt(L\"task_bar\", L\"double_click_action\", static_cast<int>(m_taskbar_data.double_click_action));\n    ini.WriteString(L\"task_bar\", L\"double_click_exe\", m_taskbar_data.double_click_exe);\n    ini.WriteBool(L\"task_bar\", L\"cm_graph_type\", m_taskbar_data.cm_graph_type);\n    ini.WriteBool(L\"task_bar\", L\"show_graph_dashed_box\", m_taskbar_data.show_graph_dashed_box);\n    ini.WriteInt(L\"task_bar\", L\"item_space\", m_taskbar_data.item_space);\n    ini.WriteInt(L\"task_bar\", L\"vertical_margin\", m_taskbar_data.vertical_margin);\n    ini.WriteInt(L\"task_bar\", L\"window_offset_top\", m_taskbar_data.window_offset_top);\n    ini.WriteInt(L\"task_bar\", L\"window_offset_left\", m_taskbar_data.window_offset_left);\n    ini.WriteBool(L\"task_bar\", L\"avoid_overlap_with_widgets\", m_taskbar_data.avoid_overlap_with_widgets);\n    ini.WriteInt(L\"task_bar\", L\"taskbar_left_space_win11\", m_taskbar_data.taskbar_left_space_win11);\n    ini.WriteInt(L\"task_bar\", L\"taskbar_right_space_win11\", m_taskbar_data.taskbar_right_space_win11);\n\n    ini.WriteBool(L\"task_bar\", L\"auto_adapt_light_theme\", m_taskbar_data.auto_adapt_light_theme);\n    ini.WriteInt(L\"task_bar\", L\"dark_default_style\", m_taskbar_data.dark_default_style);\n    ini.WriteInt(L\"task_bar\", L\"light_default_style\", m_taskbar_data.light_default_style);\n    ini.WriteBool(L\"task_bar\", L\"auto_set_background_color\", m_taskbar_data.auto_set_background_color);\n\n    ini.WriteString(L\"task_bar\", L\"item_order\", m_taskbar_data.item_order.ToString());\n    ini.WriteString(L\"task_bar\", L\"plugin_display_item\", m_taskbar_data.plugin_display_item.ToString());\n    ini.WriteBool(L\"task_bar\", L\"auto_save_taskbar_color_settings_to_preset\", m_taskbar_data.auto_save_taskbar_color_settings_to_preset);\n\n    ini.WriteBool(L\"task_bar\", L\"show_netspeed_figure\", m_taskbar_data.show_netspeed_figure);\n    ini.WriteInt(L\"task_bar\", L\"netspeed_figure_max_value\", m_taskbar_data.netspeed_figure_max_value);\n    ini.WriteInt(L\"task_bar\", L\"netspeed_figure_max_value_unit\", m_taskbar_data.netspeed_figure_max_value_unit);\n    ini.WriteBool(L\"task_bar\", L\"graph_color_following_system\", m_taskbar_data.graph_color_following_system);\n\n    ini.WriteBool(L\"task_bar\", L\"disable_d2d\", m_taskbar_data.disable_d2d);\n    ini.WriteBool(L\"task_bar\", L\"enable_colorful_emoji\", m_taskbar_data.enable_colorful_emoji);\n\n    //其他设置\n    //ini.WriteBool(L\"connection_details\", L\"show_internet_ip\", m_cfg_data.m_show_internet_ip);\n    ini.WriteBool(L\"histroy_traffic\", L\"use_log_scale\", m_cfg_data.m_use_log_scale);\n    ini.WriteBool(L\"histroy_traffic\", L\"sunday_first\", m_cfg_data.m_sunday_first);\n    ini.WriteInt(L\"histroy_traffic\", L\"view_type\", static_cast<int>(m_cfg_data.m_view_type));\n\n    ini.WriteBool(_T(\"other\"), _T(\"no_multistart_warning\"), m_no_multistart_warning);\n    ini.WriteBool(_T(\"other\"), _T(\"exit_when_start_by_restart_manager\"), m_exit_when_start_by_restart_manager);\n    ini.WriteBool(_T(\"other\"), _T(\"debug_log\"), m_debug_log);\n    ini.WriteInt(_T(\"other\"), _T(\"notify_interval\"), m_notify_interval);\n    ini.WriteBool(_T(\"other\"), _T(\"taksbar_transparent_color_enable\"), m_taksbar_transparent_color_enable);\n    ini.WriteBool(_T(\"other\"), _T(\"last_light_mode\"), m_last_light_mode);\n    ini.WriteBool(_T(\"other\"), _T(\"show_mouse_panetrate_tip\"), m_show_mouse_panetrate_tip);\n    ini.WriteBool(_T(\"other\"), _T(\"show_dot_net_notinstalled_tip\"), m_show_dot_net_notinstalled_tip);\n\n    ini.WriteString(L\"config\", L\"plugin_disabled\", m_cfg_data.plugin_disabled.ToString());\n\n    ini.WriteString(L\"app\", L\"version\", VERSION);\n\n    //检查是否保存成功\n    if (!ini.Save())\n    {\n        if (m_cannot_save_config_warning)\n        {\n            CString info = CCommon::LoadText(IDS_CONNOT_SAVE_CONFIG_WARNING);\n            info.Replace(_T(\"<%file_path%>\"), m_config_path.c_str());\n            AfxMessageBox(info, MB_ICONWARNING);\n        }\n        m_cannot_save_config_warning = false;\n        return;\n    }\n}\n\nvoid CTrafficMonitorApp::LoadPluginDisabledSettings()\n{\n    CIniHelper ini{ m_config_path };\n    m_cfg_data.plugin_disabled.FromString(ini.GetString(L\"config\", L\"plugin_disabled\", L\"\"));\n}\n\nvoid CTrafficMonitorApp::LoadGlobalConfig()\n{\n    bool portable_mode_default{ false };\n    wstring global_cfg_path{ m_module_dir + L\"global_cfg.ini\" };\n    if (!CCommon::FileExist(global_cfg_path.c_str()))       //如果global_cfg.ini不存在，则根据AppData/Roaming/TrafficMonitor目录下是否存在config.ini来判断配置文件的保存位置\n    {\n        portable_mode_default = !CCommon::FileExist((m_appdata_dir + L\"config.ini\").c_str());\n    }\n\n    CIniHelper ini{ global_cfg_path };\n    m_general_data.portable_mode = ini.GetBool(L\"config\", L\"portable_mode\", portable_mode_default);\n\n    //执行一次保存操作，以检查当前目录是否有写入权限\n    m_module_dir_writable = ini.Save();\n\n    if (m_module_dir.find(CCommon::GetTemplateDir()) != wstring::npos)      //如果当前路径是在Temp目录下，则强制将数据保存到Appdata\n    {\n        m_module_dir_writable = false;\n    }\n\n    if (!m_module_dir_writable)              //如果当前目录没有写入权限，则设置配置保存到AppData目录\n    {\n        m_general_data.portable_mode = false;\n    }\n}\n\nvoid CTrafficMonitorApp::SaveGlobalConfig()\n{\n    CIniHelper ini{ m_module_dir + L\"global_cfg.ini\" };\n    ini.WriteBool(L\"config\", L\"portable_mode\", m_general_data.portable_mode);\n\n    //检查是否保存成功\n    if (!ini.Save())\n    {\n        //if (m_cannot_save_global_config_warning)\n        //{\n        //    CString info;\n        //    info.LoadString(IDS_CONNOT_SAVE_CONFIG_WARNING);\n        //    info.Replace(_T(\"<%file_path%>\"), m_module_dir.c_str());\n        //    AfxMessageBox(info, MB_ICONWARNING);\n        //}\n        //m_cannot_save_global_config_warning = false;\n        //return;\n    }\n}\n\nint CTrafficMonitorApp::DPI(int pixel)\n{\n    return m_dpi * pixel / 96;\n}\n\nvoid CTrafficMonitorApp::DPI(CRect& rect)\n{\n    rect.left = DPI(rect.left);\n    rect.right = DPI(rect.right);\n    rect.top = DPI(rect.top);\n    rect.bottom = DPI(rect.bottom);\n}\n\nvoid CTrafficMonitorApp::DPIFromWindow(CWnd* pWnd)\n{\n    CWindowDC dc(pWnd);\n    HDC hDC = dc.GetSafeHdc();\n    m_dpi = GetDeviceCaps(hDC, LOGPIXELSY);\n}\n\nvoid CTrafficMonitorApp::CheckUpdate(bool message)\n{\n    if (m_checking_update)      //如果还在检查更新，则直接返回\n        return;\n    CFlagLocker update_locker(m_checking_update);\n    CWaitCursor wait_cursor;\n\n    wstring version;        //程序版本\n    wstring link;           //下载链接\n    wstring contents_zh_cn; //更新内容（简体中文）\n    wstring contents_en;    //更新内容（English）\n    wstring contents_zh_tw; //更新内容（繁体中文）\n    CUpdateHelper update_helper;\n    update_helper.SetUpdateSource(static_cast<CUpdateHelper::UpdateSource>(m_general_data.update_source));\n    if (!update_helper.CheckForUpdate())\n    {\n        if (message)\n            AfxMessageBox(CCommon::LoadText(IDS_CHECK_UPDATE_FAILD), MB_OK | MB_ICONWARNING);\n        return;\n    }\n    version = update_helper.GetVersion();\n#ifdef _M_X64\n    link = update_helper.GetLink64();\n#elif defined _M_ARM64EC\n    link = update_helper.GetLinkArm64ec();\n#else\n    link = update_helper.GetLink();\n#endif\n    contents_zh_cn = update_helper.GetContentsZhCn();\n    contents_en = update_helper.GetContentsEn();\n    contents_zh_tw = update_helper.GetContentsZhTw();\n    if (version.empty() || link.empty())\n    {\n        if (message)\n        {\n            CString info = CCommon::LoadText(IDS_CHECK_UPDATE_ERROR);\n            info += _T(\"\\r\\nrow_data=\");\n            info += std::to_wstring(update_helper.IsRowData()).c_str();\n\n            AfxMessageBox(info, MB_OK | MB_ICONWARNING);\n        }\n        return;\n    }\n    if (version > VERSION)      //如果服务器上的版本大于本地版本\n    {\n        CString info;\n        //根据语言设置选择对应语言版本的更新内容\n        wstring language_tag = m_str_table.GetLanguageInfo().bcp_47;\n        wstring contents_lan;\n        if (language_tag == L\"zh-CN\")\n            contents_lan = contents_zh_cn;\n        else if (language_tag == L\"zh-TW\")\n            contents_lan = contents_zh_tw;\n        else\n            contents_lan = contents_en;\n        if (contents_lan.empty())\n            info.Format(CCommon::LoadText(IDS_UPDATE_AVLIABLE), version.c_str());\n        else\n            info.Format(CCommon::LoadText(IDS_UPDATE_AVLIABLE2), version.c_str(), contents_lan.c_str());\n\n        if (AfxMessageBox(info, MB_YESNO | MB_ICONQUESTION) == IDYES)\n        {\n            ShellExecute(NULL, _T(\"open\"), link.c_str(), NULL, NULL, SW_SHOW);      //转到下载链接\n        }\n    }\n    else\n    {\n        if (message)\n            AfxMessageBox(CCommon::LoadText(IDS_ALREADY_UPDATED), MB_OK | MB_ICONINFORMATION);\n    }\n}\n\nvoid CTrafficMonitorApp::CheckUpdateInThread(bool message)\n{\n    AfxBeginThread(CheckUpdateThreadFunc, (LPVOID)message);\n}\n\nUINT CTrafficMonitorApp::CheckUpdateThreadFunc(LPVOID lpParam)\n{\n    CCommon::SetThreadLanguage(theApp.m_general_data.language);     //设置线程语言\n#ifndef _DEBUG      //DEBUG下不在启动时检查更新\n    theApp.CheckUpdate(lpParam);        //检查更新\n#endif\n    //检测插件更新\n    if (!theApp.m_plugins.GetPlugins().empty())\n    {\n        theApp.m_plugin_update.CheckForUpdate();\n    }\n    return 0;\n}\n\nUINT CTrafficMonitorApp::InitOpenHardwareMonitorLibThreadFunc(LPVOID lpParam)\n{\n#ifndef WITHOUT_TEMPERATURE\n    CSingleLock sync(&theApp.m_minitor_lib_critical, TRUE);\n    theApp.m_pMonitor = OpenHardwareMonitorApi::CreateInstance();\n    if (theApp.m_pMonitor == nullptr)\n    {\n        AfxMessageBox(OpenHardwareMonitorApi::GetErrorMessage().c_str(), MB_ICONERROR | MB_OK);\n    }\n    //设置硬件监控的启用状态\n    theApp.UpdateOpenHardwareMonitorEnableState();\n#endif\n    return 0;\n}\n\nbool  CTrafficMonitorApp::SetAutoRun(bool auto_run)\n{\n    //不含温度监控的版本使用添加注册表项的方式实现开机自启动\n#ifdef WITHOUT_TEMPERATURE\n    return SetAutoRunByRegistry(auto_run);\n#else\n    //包含温度监控的版本使用任务计划的方式实现开机自启动\n    return SetAutoRunByTaskScheduler(auto_run);\n#endif\n}\n\nbool CTrafficMonitorApp::GetAutoRun(wstring* auto_run_path)\n{\n    if (auto_run_path != nullptr)\n        auto_run_path->clear();\n    //不含温度监控的版本使用添加注册表项的方式实现开机自启动\n#ifdef WITHOUT_TEMPERATURE\n    CRegKey key;\n    if (key.Open(HKEY_CURRENT_USER, _T(\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\")) != ERROR_SUCCESS)\n    {\n        //打开注册表“Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run”失败，则返回false\n        return false;\n    }\n    wchar_t buff[256];\n    ULONG size{ 256 };\n    if (key.QueryStringValue(APP_NAME, buff, &size) == ERROR_SUCCESS)       //如果找到了“TrafficMonitor”键\n    {\n        if (auto_run_path != nullptr)\n        {\n            //保存路径\n            *auto_run_path = buff;\n            //去掉前后的引号\n            if (auto_run_path->front() == L'\\\"')\n                *auto_run_path = auto_run_path->substr(1);\n            if (auto_run_path->back() = L'\\\"')\n                auto_run_path->pop_back();\n        }\n        return (m_module_path_reg == buff); //如果“TrafficMonitor”的值是当前程序的路径，就返回true，否则返回false\n    }\n    else\n    {\n        return false;       //没有找到“TrafficMonitor”键，返回false\n    }\n#else\n    //包含温度监控的版本使用任务计划的方式实现开机自启动\n    return is_auto_start_task_active_for_this_user(auto_run_path);\n#endif\n}\n\nbool CTrafficMonitorApp::SetAutoRunByRegistry(bool auto_run)\n{\n    CRegKey key;\n    //打开注册表项\n    if (key.Open(HKEY_CURRENT_USER, _T(\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\")) != ERROR_SUCCESS)\n    {\n        AfxMessageBox(CCommon::LoadText(IDS_AUTORUN_FAILED_NO_KEY), MB_OK | MB_ICONWARNING);\n        return false;\n    }\n    if (auto_run)       //写入注册表项\n    {\n        //通过注册表设置开机自启动项时删除计划任务中的自启动项\n        SetAutoRunByTaskScheduler(false);\n\n        if (key.SetStringValue(APP_NAME, m_module_path_reg.c_str()) != ERROR_SUCCESS)\n        {\n            AfxMessageBox(CCommon::LoadText(IDS_AUTORUN_FAILED_NO_ACCESS), MB_OK | MB_ICONWARNING);\n            return false;\n        }\n    }\n    else        //删除注册表项\n    {\n        //删除前先检查注册表项是否存在，如果不存在，则直接返回\n        wchar_t buff[256];\n        ULONG size{ 256 };\n        if (key.QueryStringValue(APP_NAME, buff, &size) != ERROR_SUCCESS)\n            return false;\n        if (key.DeleteValue(APP_NAME) != ERROR_SUCCESS)\n        {\n            AfxMessageBox(CCommon::LoadText(IDS_AUTORUN_DELETE_FAILED), MB_OK | MB_ICONWARNING);\n            return false;\n        }\n    }\n    return true;\n}\n\nbool CTrafficMonitorApp::SetAutoRunByTaskScheduler(bool auto_run)\n{\n    bool succeed = delete_auto_start_task_for_this_user();     //先删除开机自启动\n    if (auto_run)\n    {\n        //通过计划任务设置开机自启动项时删除注册表中的自启动项\n        SetAutoRunByRegistry(false);\n\n        succeed = create_auto_start_task_for_this_user(true);\n    }\n    return succeed;\n}\n\nCString CTrafficMonitorApp::GetSystemInfoString()\n{\n    CString info;\n    info += _T(\"System Info:\\r\\n\");\n\n    CString strTmp;\n    strTmp.Format(_T(\"Windows Version: %d.%d build %d\"), m_win_version.GetMajorVersion(),\n        m_win_version.GetMinorVersion(), m_win_version.GetBuildNumber());\n    info += strTmp;\n\n    if (m_win_version.IsWine())\n        info += _T(\" (Wine)\");\n\n    info += _T(\"\\r\\n\");\n\n    strTmp.Format(_T(\"DPI: %d\"), m_dpi);\n    info += strTmp;\n    info += _T(\"\\r\\n\");\n\n    info += _T(\"Version: \");\n    info += VERSION;\n    info += _T(\" \");\n#ifdef _M_X64\n    info += _T(\"x64\");\n#elif defined _M_ARM64EC\n    info += _T(\"Arm64EC\");\n#else\n    info += _T(\"x86\");\n#endif\n\n#ifdef WITHOUT_TEMPERATURE\n    info += _T(\" (Lite)\");\n#endif\n\n    info += _T(\"\\r\\nLast compiled date: \");\n    info += CCommon::GetLastCompileTime();\n\n    return info;\n}\n\n\nvoid CTrafficMonitorApp::InitMenuResourse()\n{\n    //载入菜单\n    CCommon::LoadMenuResource(m_main_menu, IDR_MENU1);\n    CCommon::LoadMenuResource(m_main_menu_plugin, IDR_MENU1);\n    CCommon::LoadMenuResource(m_taskbar_menu, IDR_TASK_BAR_MENU);\n    CCommon::LoadMenuResource(m_taskbar_menu_plugin, IDR_TASK_BAR_MENU);\n\n    //为插件菜单添加额外项目\n    m_main_menu_plugin_sub_menu.CreatePopupMenu();\n    m_main_menu_plugin_sub_menu.AppendMenu(MF_STRING | MF_ENABLED, ID_PLUGIN_OPTIONS, CCommon::LoadText(IDS_PLUGIN_OPTIONS, _T(\"...\")));\n    m_main_menu_plugin_sub_menu.AppendMenu(MF_STRING | MF_ENABLED, ID_PLUGIN_DETAIL, CCommon::LoadText(IDS_PLUGIN_INFO, _T(\"...\")));\n    CMenuIcon::AddIconToMenuItem(m_main_menu_plugin_sub_menu.GetSafeHmenu(), ID_PLUGIN_OPTIONS, FALSE, GetMenuIcon(IDI_SETTINGS));\n    CMenuIcon::AddIconToMenuItem(m_main_menu_plugin_sub_menu.GetSafeHmenu(), ID_PLUGIN_DETAIL, FALSE, GetMenuIcon(IDI_INFO));\n    CMenu* main_menu_plugin = m_main_menu_plugin.GetSubMenu(0);\n    main_menu_plugin->AppendMenu(MF_SEPARATOR);\n    main_menu_plugin->AppendMenu(MF_POPUP | MF_STRING, (UINT)m_main_menu_plugin_sub_menu.m_hMenu, _T(\"<plugin name>\"));\n\n    m_taskbar_menu_plugin_sub_menu.CreatePopupMenu();\n    m_taskbar_menu_plugin_sub_menu.AppendMenu(MF_STRING | MF_ENABLED, ID_PLUGIN_OPTIONS_TASKBAR, CCommon::LoadText(IDS_PLUGIN_OPTIONS, _T(\"...\")));\n    m_taskbar_menu_plugin_sub_menu.AppendMenu(MF_STRING | MF_ENABLED, ID_PLUGIN_DETAIL_TASKBAR, CCommon::LoadText(IDS_PLUGIN_INFO, _T(\"...\")));\n    CMenuIcon::AddIconToMenuItem(m_taskbar_menu_plugin_sub_menu.GetSafeHmenu(), ID_PLUGIN_OPTIONS_TASKBAR, FALSE, GetMenuIcon(IDI_SETTINGS));\n    CMenuIcon::AddIconToMenuItem(m_taskbar_menu_plugin_sub_menu.GetSafeHmenu(), ID_PLUGIN_DETAIL_TASKBAR, FALSE, GetMenuIcon(IDI_INFO));\n    CMenu* taskbar_menu_plugin = m_taskbar_menu_plugin.GetSubMenu(0);\n    taskbar_menu_plugin->AppendMenu(MF_SEPARATOR);\n    taskbar_menu_plugin->AppendMenu(MF_POPUP | MF_STRING, (UINT)m_taskbar_menu_plugin_sub_menu.m_hMenu, _T(\"<plugin name>\"));\n\n    //为菜单项添加图标\n    auto addIconsForMainWindowMenu = [&](const CMenu& menu)\n    {\n        CMenuIcon::AddIconToMenuItem(menu.GetSubMenu(0)->GetSafeHmenu(), 0, TRUE, GetMenuIcon(IDI_CONNECTION));\n        CMenuIcon::AddIconToMenuItem(menu.GetSubMenu(0)->GetSafeHmenu(), 11, TRUE, GetMenuIcon(IDI_FUNCTION));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_NETWORK_INFO, FALSE, GetMenuIcon(IDI_INFO));\n        if (!m_win_version.IsWindows11OrLater())\n            CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_ALWAYS_ON_TOP, FALSE, GetMenuIcon(IDI_PIN));\n        if (!m_win_version.IsWindows11OrLater())\n            CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_MOUSE_PENETRATE, FALSE, GetMenuIcon(IDI_MOUSE));\n        if (!m_win_version.IsWindows11OrLater())\n            CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_LOCK_WINDOW_POS, FALSE, GetMenuIcon(IDI_LOCK));\n        //if (!m_win_version.IsWindows11OrLater())\n        //    CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_SHOW_NOTIFY_ICON, FALSE, GetMenuIcon(IDI_NOTIFY));\n        if (!m_win_version.IsWindows11OrLater())\n            CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_SHOW_CPU_MEMORY, FALSE, GetMenuIcon(IDI_MORE));\n        if (!m_win_version.IsWindows11OrLater())\n            CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_SHOW_TASK_BAR_WND, FALSE, GetMenuIcon(IDI_TASKBAR_WINDOW));\n        if (!m_win_version.IsWindows11OrLater())\n            CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_SHOW_MAIN_WND, FALSE, GetMenuIcon(IDI_MAIN_WINDOW));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_CHANGE_SKIN, FALSE, GetMenuIcon(IDI_SKIN));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_CHANGE_NOTIFY_ICON, FALSE, GetMenuIcon(IDI_NOTIFY));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_TRAFFIC_HISTORY, FALSE, GetMenuIcon(IDI_STATISTICS));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_PLUGIN_MANAGE, FALSE, GetMenuIcon(IDI_PLUGINS));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_OPTIONS, FALSE, GetMenuIcon(IDI_SETTINGS));\n        CMenuIcon::AddIconToMenuItem(menu.GetSubMenu(0)->GetSafeHmenu(), 14, TRUE, GetMenuIcon(IDI_HELP));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_HELP, FALSE, GetMenuIcon(IDI_HELP));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_APP_ABOUT, FALSE, GetMenuIcon(IDR_MAINFRAME));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_APP_EXIT, FALSE, GetMenuIcon(IDI_EXIT));\n    };\n    //主窗口右键菜单\n    addIconsForMainWindowMenu(m_main_menu);\n    addIconsForMainWindowMenu(m_main_menu_plugin);\n\n    //任务栏窗口右键菜单\n    auto addIconsForTaksbarWindowMenu = [&](const CMenu& menu)\n    {\n        CMenuIcon::AddIconToMenuItem(menu.GetSubMenu(0)->GetSafeHmenu(), 0, TRUE, GetMenuIcon(IDI_CONNECTION));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_NETWORK_INFO, FALSE, GetMenuIcon(IDI_INFO));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_TRAFFIC_HISTORY, FALSE, GetMenuIcon(IDI_STATISTICS));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_DISPLAY_SETTINGS, FALSE, GetMenuIcon(IDI_ITEM));\n        //if (!m_win_version.IsWindows11OrLater())\n        //    CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_SHOW_NOTIFY_ICON, FALSE, GetMenuIcon(IDI_NOTIFY));\n        if (!m_win_version.IsWindows11OrLater())\n            CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_SHOW_MAIN_WND, FALSE, GetMenuIcon(IDI_MAIN_WINDOW));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_SHOW_TASK_BAR_WND, FALSE, GetMenuIcon(IDI_CLOSE));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_OPEN_TASK_MANAGER, FALSE, GetMenuIcon(IDI_TASK_MANAGER));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_OPTIONS2, FALSE, GetMenuIcon(IDI_SETTINGS));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_PLUGIN_MANAGE, FALSE, GetMenuIcon(IDI_PLUGINS));\n        CMenuIcon::AddIconToMenuItem(menu.GetSubMenu(0)->GetSafeHmenu(), 13, TRUE, GetMenuIcon(IDI_HELP));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_HELP, FALSE, GetMenuIcon(IDI_HELP));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_APP_ABOUT, FALSE, GetMenuIcon(IDR_MAINFRAME));\n        CMenuIcon::AddIconToMenuItem(menu.GetSafeHmenu(), ID_APP_EXIT, FALSE, GetMenuIcon(IDI_EXIT));\n    };\n    addIconsForTaksbarWindowMenu(m_taskbar_menu);\n    addIconsForTaksbarWindowMenu(m_taskbar_menu_plugin);\n\n#ifdef _DEBUG\n    m_main_menu.GetSubMenu(0)->AppendMenu(MF_BYCOMMAND, ID_CMD_TEST, _T(\"Test Command\"));\n#endif\n}\n\nHICON CTrafficMonitorApp::GetMenuIcon(UINT id)\n{\n    auto iter = m_menu_icons.find(id);\n    if (iter != m_menu_icons.end())\n    {\n        return iter->second;\n    }\n    else\n    {\n        HICON hIcon = CCommon::LoadIconResource(id, DPI(16));\n        m_menu_icons[id] = hIcon;\n        return hIcon;\n    }\n}\n\nvoid CTrafficMonitorApp::AutoSelectNotifyIcon()\n{\n    if (m_win_version.GetMajorVersion() >= 10)\n    {\n        bool light_mode = CWindowsSettingHelper::IsWindows10LightTheme();\n        if (light_mode)     //浅色模式下，如果图标是白色，则改成黑色\n        {\n            if (m_cfg_data.m_notify_icon_selected == 0)\n                m_cfg_data.m_notify_icon_selected = 4;\n            if (m_cfg_data.m_notify_icon_selected == 1)\n                m_cfg_data.m_notify_icon_selected = 5;\n        }\n        else     //深色模式下，如果图标是黑色，则改成白色\n        {\n            if (m_cfg_data.m_notify_icon_selected == 4)\n                m_cfg_data.m_notify_icon_selected = 0;\n            if (m_cfg_data.m_notify_icon_selected == 5)\n                m_cfg_data.m_notify_icon_selected = 1;\n        }\n    }\n}\n\n// 唯一的一个 CTrafficMonitorApp 对象\n\nCTrafficMonitorApp theApp;\n\n\n// CTrafficMonitorApp 初始化\n\nBOOL CTrafficMonitorApp::InitInstance()\n{\n    //替换掉对话框程序的默认类名\n    WNDCLASS wc;\n    ::GetClassInfo(AfxGetInstanceHandle(), _T(\"#32770\"), &wc);       //MFC默认的所有对话框的类名为#32770\n    wc.lpszClassName = APP_CLASS_NAME;      //将对话框的类名修改为新类名\n    AfxRegisterClass(&wc);\n\n    //设置配置文件的路径\n    wchar_t path[MAX_PATH];\n    GetModuleFileNameW(NULL, path, MAX_PATH);\n    m_module_path = path;\n    if (m_module_path.find(L' ') != wstring::npos)\n    {\n        //如果路径中有空格，则在程序路径前后添加双引号\n        m_module_path_reg = L'\\\"';\n        m_module_path_reg += m_module_path;\n        m_module_path_reg += L'\\\"';\n    }\n    else\n    {\n        m_module_path_reg = m_module_path;\n    }\n    m_module_dir = CCommon::GetModuleDir();\n    m_system_dir = CCommon::GetSystemDir();\n    m_appdata_dir = CCommon::GetAppDataConfigDir();\n\n    LoadGlobalConfig();\n\n#ifdef _DEBUG\n    m_config_dir = L\".\\\\\";\n    m_skin_path = L\".\\\\skins\\\\\";\n#else\n    if (m_general_data.portable_mode)\n        m_config_dir = m_module_dir;\n    else\n        m_config_dir = m_appdata_dir;\n    m_skin_path = m_module_dir + L\"skins\\\\\";\n#endif\n    //AppData里面的程序配置文件路径\n    m_config_path = m_config_dir + L\"config.ini\";\n    m_history_traffic_path = m_config_dir + L\"history_traffic.dat\";\n    m_log_path = m_config_dir + L\"error.log\";\n\n    //#ifndef _DEBUG\n    //  //原来的、程序所在目录下的配置文件的路径\n    //  wstring config_path_old = m_module_dir + L\"config.ini\";\n    //  wstring history_traffic_path_old = m_module_dir + L\"history_traffic.dat\";\n    //  wstring log_path_old = m_module_dir + L\"error.log\";\n    //  //如果程序所在目录下含有配置文件，则将其移动到AppData对应的目录下面\n    //  CCommon::MoveAFile(config_path_old.c_str(), m_config_path.c_str());\n    //  CCommon::MoveAFile(history_traffic_path_old.c_str(), m_history_traffic_path.c_str());\n    //  CCommon::MoveAFile(log_path_old.c_str(), m_log_path.c_str());\n    //#endif // !_DEBUG\n\n    LoadLanguageConfig();\n\n    //初始化界面语言\n    CCommon::SetThreadLanguage(m_general_data.language);\n\n    //初始化字符串资源\n    m_str_table.Init();\n\n    //载入插件\n    LoadPluginDisabledSettings();\n    m_plugins.LoadPlugins();\n\n    //从ini文件载入设置\n    LoadConfig();\n\n    //检查是否已有实例正在运行\n    LPCTSTR mutex_name{};\n#ifdef _DEBUG\n    mutex_name = _T(\"TrafficMonitor-e8Ahk24HP6JC8hDy\");\n#else\n    mutex_name = _T(\"TrafficMonitor-1419J3XLKL1w8OZc\");\n#endif\n    HANDLE hMutex = ::CreateMutex(NULL, TRUE, mutex_name);\n    if (hMutex != NULL)\n    {\n        if (GetLastError() == ERROR_ALREADY_EXISTS)\n        {\n            //char buff[128];\n            //string cmd_line_str{ CCommon::UnicodeToStr(cmd_line.c_str()) };\n            //sprintf_s(buff, \"when_start=%d, m_no_multistart_warning=%d, cmd_line=%s\", when_start, m_no_multistart_warning, cmd_line_str.c_str());\n            //CCommon::WriteLog(buff, _T(\".\\\\start.log\"));\n            if (!m_no_multistart_warning)\n            {\n                //查找已存在TrafficMonitor进程的主窗口的句柄\n                HWND exist_handel = ::FindWindow(APP_CLASS_NAME, NULL);\n                if (exist_handel != NULL)\n                {\n                    //弹出“TrafficMonitor已在运行”对话框\n                    CAppAlreadyRuningDlg dlg(exist_handel);\n                    dlg.DoModal();\n                }\n                else\n                {\n                    AfxMessageBox(CCommon::LoadText(IDS_AN_INSTANCE_RUNNING));\n                }\n            }\n            return FALSE;\n        }\n    }\n\n    m_taskbar_default_style.LoadConfig();\n\n    //SaveConfig();\n\n    // 如果一个运行在 Windows XP 上的应用程序清单指定要\n    // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式，\n    //则需要 InitCommonControlsEx()。  否则，将无法创建窗口。\n    INITCOMMONCONTROLSEX InitCtrls;\n    InitCtrls.dwSize = sizeof(InitCtrls);\n    // 将它设置为包括所有要在应用程序中使用的\n    // 公共控件类。\n    InitCtrls.dwICC = ICC_WIN95_CLASSES;\n    InitCommonControlsEx(&InitCtrls);\n\n    CWinApp::InitInstance();\n\n\n    AfxEnableControlContainer();\n\n    // 创建 shell 管理器，以防对话框包含\n    // 任何 shell 树视图控件或 shell 列表视图控件。\n    CShellManager* pShellManager = new CShellManager;\n\n    // 激活“Windows Native”视觉管理器，以便在 MFC 控件中启用主题\n    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));\n\n    // 标准初始化\n    // 如果未使用这些功能并希望减小\n    // 最终可执行文件的大小，则应移除下列\n    // 不需要的特定初始化例程\n    // 更改用于存储设置的注册表项\n    // TODO: 应适当修改该字符串，\n    // 例如修改为公司或组织名\n    //SetRegistryKey(_T(\"应用程序向导生成的本地应用程序\"));        //暂不使用注册表保存数据\n\n    //启动时检查更新\n    if (m_general_data.check_update_when_start)\n    {\n        CheckUpdateInThread(false);\n    }\n\n#ifndef WITHOUT_TEMPERATURE\n    //检测是否安装.net framework 4.5\n    if (!CWindowsSettingHelper::IsDotNetFramework4Point5Installed())\n    {\n        if (theApp.m_show_dot_net_notinstalled_tip)\n        {\n            if (AfxMessageBox(CCommon::LoadText(IDS_DOTNET_NOT_INSTALLED_TIP), MB_OKCANCEL | MB_ICONWARNING) == IDCANCEL)       //点击“取消”不再提示\n            {\n                theApp.m_show_dot_net_notinstalled_tip = false;\n                SaveConfig();\n            }\n        }\n    }\n    else\n    {\n        //如果没有开启任何一项的硬件监控，则不初始化OpenHardwareMonitor\n        if (theApp.m_general_data.IsHardwareEnable(HI_CPU) || theApp.m_general_data.IsHardwareEnable(HI_GPU)\n            || theApp.m_general_data.IsHardwareEnable(HI_HDD) || theApp.m_general_data.IsHardwareEnable(HI_MBD))\n        {\n            //启动初始化OpenHardwareMonitor的线程。由于OpenHardwareMonitor初始化需要一定的时间，为了防止启动时程序卡顿，将其放到后台线程中处理\n            InitOpenHardwareLibInThread();\n        }\n    }\n#endif\n\n    //执行测试代码\n#ifdef _DEBUG\n    CTest::Test();\n#endif\n\n    //初始化GDI+\n    Gdiplus::GdiplusStartupInput gdiplusStartupInput;\n    GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);\n\n    SendSettingsToPlugin();\n\n    CTrafficMonitorDlg dlg;\n    m_pMainWnd = &dlg;\n    INT_PTR nResponse = dlg.DoModal();\n    if (nResponse == IDOK)\n    {\n        // TODO: 在此放置处理何时用\n        //  “确定”来关闭对话框的代码\n    }\n    else if (nResponse == IDCANCEL)\n    {\n        // TODO: 在此放置处理何时用\n        //  “取消”来关闭对话框的代码\n    }\n    else if (nResponse == -1)\n    {\n        TRACE(traceAppMsg, 0, \"警告: 对话框创建失败，应用程序将意外终止。\\n\");\n        TRACE(traceAppMsg, 0, \"警告: 如果您在对话框上使用 MFC 控件，则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\\n\");\n    }\n\n    // 删除上面创建的 shell 管理器。\n    if (pShellManager != NULL)\n    {\n        delete pShellManager;\n    }\n\n#ifndef _AFXDLL\n    ControlBarCleanUp();\n#endif\n\n    // 由于对话框已关闭，所以将返回 FALSE 以便退出应用程序，\n    //  而不是启动应用程序的消息泵。\n    return FALSE;\n}\n\nvoid CTrafficMonitorApp::InitOpenHardwareLibInThread()\n{\n#ifndef WITHOUT_TEMPERATURE\n    AfxBeginThread(InitOpenHardwareMonitorLibThreadFunc, NULL);\n#endif\n}\n\n\nvoid CTrafficMonitorApp::UpdateOpenHardwareMonitorEnableState()\n{\n#ifndef WITHOUT_TEMPERATURE\n    if (m_pMonitor != nullptr)\n    {\n        CSingleLock sync(&theApp.m_minitor_lib_critical, TRUE);\n        m_pMonitor->SetCpuEnable(m_general_data.IsHardwareEnable(HI_CPU));\n        m_pMonitor->SetGpuEnable(m_general_data.IsHardwareEnable(HI_GPU));\n        m_pMonitor->SetHddEnable(m_general_data.IsHardwareEnable(HI_HDD));\n        m_pMonitor->SetMainboardEnable(m_general_data.IsHardwareEnable(HI_MBD));\n    }\n#endif\n}\n\n//void CTrafficMonitorApp::UpdateTaskbarWndMenu()\n//{\n//    //获取“显示设置”子菜单\n//    CMenu* pMenu = m_taskbar_menu.GetSubMenu(0)->GetSubMenu(5);\n//    ASSERT(pMenu != nullptr);\n//    if (pMenu != nullptr)\n//    {\n//        //将ID_SHOW_MEMORY_USAGE后面的所有菜单项删除\n//        if (pMenu->GetMenuItemCount() > 4)\n//        {\n//            int start_pos = CCommon::GetMenuItemPosition(pMenu, ID_SHOW_MEMORY_USAGE) + 1;\n//            while (pMenu->GetMenuItemCount() > start_pos)\n//            {\n//                pMenu->DeleteMenu(start_pos, MF_BYPOSITION);\n//            }\n//        }\n//\n//        //添加温度相关菜单项\n//#ifndef WITHOUT_TEMPERATURE\n//        if (m_general_data.IsHardwareEnable(HI_GPU))\n//            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_GPU, CCommon::LoadText(IDS_GPU_USAGE));\n//        if (m_general_data.IsHardwareEnable(HI_CPU))\n//            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_CPU_TEMPERATURE, CCommon::LoadText(IDS_CPU_TEMPERATURE));\n//        if (m_general_data.IsHardwareEnable(HI_GPU))\n//            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_GPU_TEMPERATURE, CCommon::LoadText(IDS_GPU_TEMPERATURE));\n//        if (m_general_data.IsHardwareEnable(HI_HDD))\n//            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_HDD_TEMPERATURE, CCommon::LoadText(IDS_HDD_TEMPERATURE));\n//        if (m_general_data.IsHardwareEnable(HI_MBD))\n//            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_MAIN_BOARD_TEMPERATURE, CCommon::LoadText(IDS_MAINBOARD_TEMPERATURE));\n//        if (m_general_data.IsHardwareEnable(HI_HDD))\n//            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_HDD, CCommon::LoadText(IDS_HDD_USAGE));\n//#endif\n//\n//        pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_TOTAL_SPEED, CCommon::LoadText(IDS_TOTAL_NET_SPEED));\n//\n//        //添加插件菜单项\n//        if (!m_plugins.GetPluginItems().empty())\n//            pMenu->AppendMenu(MF_SEPARATOR);\n//        int plugin_index = 0;\n//        for (const auto& plugin_item : m_plugins.GetPluginItems())\n//        {\n//            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SHOW_PLUGIN_ITEM_START + plugin_index, plugin_item->GetItemName());\n//            plugin_index++;\n//        }\n//    }\n//}\n\nbool CTrafficMonitorApp::IsForceShowNotifyIcon()\n{\n    return ((!m_cfg_data.m_show_task_bar_wnd /*|| m_win_version.IsWindows11OrLater()*/)\n        && (m_cfg_data.m_hide_main_window || m_main_wnd_data.m_mouse_penetrate));    //如果没有显示任务栏窗口，且隐藏了主窗口或设置了鼠标穿透，则禁用“显示通知区图标”菜单项\n}\n\nstd::wstring CTrafficMonitorApp::GetPlauginTooltipInfo() const\n{\n    std::wstring tip_info;\n    for (const auto& item : m_plugins.GetPlugins())\n    {\n        if (item.plugin != nullptr && item.plugin->GetAPIVersion() >= 2)\n        {\n            std::wstring plugin_tooltip = item.plugin->GetTooltipInfo();\n            CCommon::StringNormalize(plugin_tooltip);\n            if (!plugin_tooltip.empty())\n            {\n                tip_info += L\"\\r\\n\";\n                tip_info += plugin_tooltip.c_str();\n            }\n        }\n    }\n    return tip_info;\n}\n\nbool CTrafficMonitorApp::IsTaksbarItemDisplayed(CommonDisplayItem item) const\n{\n    if (item.IsPlugin())\n    {\n        if (item.PluginItem() != nullptr)\n            return m_taskbar_data.plugin_display_item.Contains(item.PluginItem()->GetItemId());\n    }\n    else\n    {\n        return m_taskbar_data.display_item.Contains(item.ItemType());\n    }\n    return false;\n}\n\nvoid CTrafficMonitorApp::SendSettingsToPlugin()\n{\n    for (const auto& plugin_info : m_plugins.GetPlugins())\n    {\n        if (plugin_info.plugin != nullptr && plugin_info.plugin->GetAPIVersion() >= 2)\n        {\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_NAIN_WND_NET_SPEED_SHORT_MODE, std::to_wstring(m_main_wnd_data.speed_short_mode).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_MAIN_WND_SPERATE_WITH_SPACE, std::to_wstring(m_main_wnd_data.separate_value_unit_with_space).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_MAIN_WND_UNIT_BYTE, std::to_wstring(m_main_wnd_data.unit_byte).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_MAIN_WND_UNIT_SELECT, std::to_wstring(static_cast<int>(m_main_wnd_data.speed_unit)).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_MAIN_WND_NOT_SHOW_UNIT, std::to_wstring(m_main_wnd_data.hide_unit).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_MAIN_WND_NOT_SHOW_PERCENT, std::to_wstring(m_main_wnd_data.hide_percent).c_str());\n\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_NET_SPEED_SHORT_MODE, std::to_wstring(m_taskbar_data.speed_short_mode).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_SPERATE_WITH_SPACE, std::to_wstring(m_taskbar_data.separate_value_unit_with_space).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_VALUE_RIGHT_ALIGN, std::to_wstring(m_taskbar_data.value_right_align).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_NET_SPEED_WIDTH, std::to_wstring(m_taskbar_data.digits_number).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_UNIT_BYTE, std::to_wstring(m_taskbar_data.unit_byte).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_UNIT_SELECT, std::to_wstring(static_cast<int>(m_taskbar_data.speed_unit)).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_NOT_SHOW_UNIT, std::to_wstring(m_taskbar_data.hide_unit).c_str());\n            plugin_info.plugin->OnExtenedInfo(ITMPlugin::EI_TASKBAR_WND_NOT_SHOW_PERCENT, std::to_wstring(m_taskbar_data.hide_percent).c_str());\n        }\n    }\n}\n\nvoid CTrafficMonitorApp::UpdatePluginMenu(CMenu* pMenu, ITMPlugin* plugin, int plugin_cmd_start_index)\n{\n    if (pMenu != nullptr)\n    {\n        //删除菜单已经存在的插件命令\n        while (pMenu->GetMenuItemCount() > plugin_cmd_start_index)\n        {\n            if (!pMenu->DeleteMenu(pMenu->GetMenuItemCount() - 1, MF_BYPOSITION))\n                break;\n        }\n        //添加插件命令\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 5)\n        {\n            int plugin_cmd_count = plugin->GetCommandCount();\n            //添加分隔符\n            if (plugin_cmd_count > 0)\n                pMenu->AppendMenu(MF_SEPARATOR);\n            for (int i = 0; i < plugin_cmd_count; i++)\n            {\n                const wchar_t* cmd_name = plugin->GetCommandName(i);\n                if (cmd_name != nullptr)\n                {\n                    pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_PLUGIN_COMMAND_START + i, cmd_name);\n                    //添加命令图标\n                    HICON cmd_icon = (HICON)plugin->GetCommandIcon(i);\n                    CMenuIcon::AddIconToMenuItem(pMenu->GetSafeHmenu(), ID_PLUGIN_COMMAND_START + i, FALSE, cmd_icon);\n                }\n            }\n        }\n    }\n}\n\nvoid CTrafficMonitorApp::CheckWindows11Taskbar()\n{\n    // 在“Shell_TrayWnd”的子窗口找到类名为“Windows.UI.Composition.DesktopWindowContentBridge”的窗口则认为是Windows11的任务栏\n    if (m_win_version.IsWindows11OrLater())\n    {\n        HWND hTaskbar = ::FindWindow(L\"Shell_TrayWnd\", NULL);\n        m_is_windows11_taskbar = (::FindWindowExW(hTaskbar, 0, L\"Windows.UI.Composition.DesktopWindowContentBridge\", NULL) != NULL);\n    }\n    else\n    {\n        m_is_windows11_taskbar = false;\n    }\n}\n\nbool CTrafficMonitorApp::DPIFromRect(const RECT& rect, UINT* out_dpi_x, UINT* out_dpi_y)\n{\n    HMONITOR h_current_monitor = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);\n    HRESULT hr = m_dll_functions.GetDpiForMonitor(h_current_monitor, MDT_EFFECTIVE_DPI, out_dpi_x, out_dpi_y);\n    return hr == S_OK;\n}\n\nunsigned int CTrafficMonitorApp::GetThemeColor() const\n{\n    return m_theme_color;\n}\n\nvoid CTrafficMonitorApp::SetThemeColor(COLORREF color)\n{\n    m_theme_color = color;\n}\n\nvoid CTrafficMonitorApp::OnHelp()\n{\n    // TODO: 在此添加命令处理程序代码\n    CString help_url;\n    if (m_str_table.IsSimplifiedChinese())\n        help_url = _T(\"https://github.com/zhongyang219/TrafficMonitor/wiki\");\n    else\n        help_url = _T(\"https://github.com/zhongyang219/TrafficMonitor/wiki/Home_en\");\n    ShellExecute(NULL, _T(\"open\"), help_url, NULL, NULL, SW_SHOW);\n}\n\n\nvoid CTrafficMonitorApp::OnFrequentyAskedQuestions()\n{\n    // TODO: 在此添加命令处理程序代码\n    CString url_domain;\n    if (static_cast<CUpdateHelper::UpdateSource>(m_general_data.update_source) == CUpdateHelper::UpdateSource::GiteeSource)\n        url_domain = _T(\"gitee.com\");\n    else\n        url_domain = _T(\"github.com\");\n    CString file_name;\n    if (m_str_table.IsSimplifiedChinese())\n        file_name = _T(\"Help.md\");\n    else\n        file_name = _T(\"Help_en-us.md\");\n    CString url;\n    url.Format(_T(\"https://%s/zhongyang219/TrafficMonitor/blob/master/%s\"), url_domain.GetString(), file_name.GetString());\n    ShellExecute(NULL, _T(\"open\"), url, NULL, NULL, SW_SHOW);\n}\n\n\nvoid CTrafficMonitorApp::OnUpdateLog()\n{\n    // TODO: 在此添加命令处理程序代码\n    CString url_domain;\n    if (static_cast<CUpdateHelper::UpdateSource>(m_general_data.update_source) == CUpdateHelper::UpdateSource::GiteeSource)\n        url_domain = _T(\"gitee.com\");\n    else\n        url_domain = _T(\"github.com\");\n    wstring language_tag = m_str_table.GetLanguageInfo().bcp_47;\n    CString file_name;\n    if (language_tag == L\"zh-CN\")\n        file_name = _T(\"update_log.md\");\n    else if (language_tag == L\"zh-TW\")\n        file_name = _T(\"update_log_zh-tw.md\");\n    else\n        file_name = _T(\"update_log_en-us.md\");\n    CString url;\n    url.Format(_T(\"https://%s/zhongyang219/TrafficMonitor/blob/master/UpdateLog/%s\"), url_domain.GetString(), file_name.GetString());\n    ShellExecute(NULL, _T(\"open\"), url, NULL, NULL, SW_SHOW);\n}\n\n\nint CTrafficMonitorApp::ExitInstance()\n{\n    // 释放GDI+\n    Gdiplus::GdiplusShutdown(m_gdiplusToken);\n\n    return CWinApp::ExitInstance();\n}\n\nint CTrafficMonitorApp::GetAPIVersion()\n{\n    return 0;\n}\n\nconst wchar_t* CTrafficMonitorApp::GetVersion()\n{\n    return VERSION;\n}\n\ndouble CTrafficMonitorApp::GetMonitorValue(MonitorItem item)\n{\n    switch (item)\n    {\n    case MI_UP: return m_out_speed;\n    case MI_DOWN: return m_in_speed;\n    case MI_CPU: return m_cpu_usage;\n    case MI_MEMORY: return m_memory_usage;\n    case MI_GPU_USAGE: return m_gpu_usage;\n    case MI_CPU_TEMP: return m_cpu_temperature;\n    case MI_GPU_TEMP: return m_gpu_temperature;\n    case MI_HDD_TEMP: return m_hdd_temperature;\n    case MI_MAIN_BOARD_TEMP: return m_main_board_temperature;\n    case MI_HDD_USAGE: return m_hdd_usage;\n    case MI_CPU_FREQ: return m_cpu_freq;\n    case MI_TODAY_UP_TRAFFIC: return m_today_up_traffic;\n    case MI_TODAY_DOWN_TRAFFIC: return m_today_down_traffic;\n    }\n    return 0.0;\n}\n\nconst wchar_t* CTrafficMonitorApp::GetMonitorValueString(MonitorItem item, int is_main_window)\n{\n    static CString str_value;\n    if (item == MI_TODAY_UP_TRAFFIC)\n    {\n        str_value = CCommon::KBytesToString(theApp.m_today_up_traffic / 1024u);\n    }\n    else if (item == MI_TODAY_DOWN_TRAFFIC)\n    {\n        str_value = CCommon::KBytesToString(theApp.m_today_down_traffic / 1024u);\n    }\n    else\n    {\n        DisplayItem display_item{};\n        switch (item)\n        {\n        case MI_UP: display_item = DisplayItem::TDI_UP; break;\n        case MI_DOWN: display_item = DisplayItem::TDI_DOWN; break;\n        case MI_CPU: display_item = DisplayItem::TDI_CPU; break;\n        case MI_MEMORY: display_item = DisplayItem::TDI_MEMORY; break;\n        case MI_GPU_USAGE: display_item = DisplayItem::TDI_GPU_USAGE; break;\n        case MI_CPU_TEMP: display_item = DisplayItem::TDI_CPU_TEMP; break;\n        case MI_GPU_TEMP: display_item = DisplayItem::TDI_GPU_TEMP; break;\n        case MI_HDD_TEMP: display_item = DisplayItem::TDI_HDD_TEMP; break;\n        case MI_MAIN_BOARD_TEMP: display_item = DisplayItem::TDI_MAIN_BOARD_TEMP; break;\n        case MI_HDD_USAGE: display_item = DisplayItem::TDI_HDD_USAGE; break;\n        case MI_CPU_FREQ: display_item = DisplayItem::TDI_CPU_FREQ; break;\n        }\n        str_value = CommonDisplayItem(display_item).GetItemValueText(is_main_window);\n    }\n    return str_value.GetString();\n}\n\nvoid CTrafficMonitorApp::ShowNotifyMessage(const wchar_t* strMsg)\n{\n    CTrafficMonitorDlg* pMainWnd = dynamic_cast<CTrafficMonitorDlg*>(m_pMainWnd);\n    if (pMainWnd != nullptr)\n    {\n        pMainWnd->ShowNotifyTip(CCommon::LoadText(IDS_TRAFFICMONITOR_PLUGIN_NITIFICATION), strMsg);\n    }\n}\n\nunsigned short CTrafficMonitorApp::GetLanguageId() const\n{\n    return m_general_data.language;\n}\n\nconst wchar_t* CTrafficMonitorApp::GetPluginConfigDir() const\n{\n    static std::wstring config_dir;\n    config_dir = m_config_dir;\n    config_dir += L\"plugins\\\\\";\n    return config_dir.c_str();\n}\n\nint CTrafficMonitorApp::GetDPI(DPIType type) const\n{\n    CTrafficMonitorDlg* pMainWnd = dynamic_cast<CTrafficMonitorDlg*>(m_pMainWnd);\n    switch (type)\n    {\n    case DPI_MAIN_WND:\n        return m_dpi;\n    case DPI_TASKBAR:\n        if (pMainWnd != nullptr)\n        {\n            if (pMainWnd->IsTaskbarWndValid())\n                return pMainWnd->GetTaskbarWindow()->GetDPI();\n        }\n        return m_dpi;\n    }\n    return 0;\n}\n\nconst wchar_t* CTrafficMonitorApp::GetStringRes(const wchar_t* key, const wchar_t* section)\n{\n    return m_str_table.LoadText(key, section).c_str();\n}\n"
  },
  {
    "path": "TrafficMonitor/TrafficMonitor.h",
    "content": "﻿\n// TrafficMonitor.h : PROJECT_NAME 应用程序的主头文件\n//\n\n#pragma once\n\n#ifndef __AFXWIN_H__\n#error \"在包含此文件之前包含“stdafx.h”以生成 PCH 文件\"\n#endif\n\n#include \"resource.h\"       // 主符号\n#include \"Common.h\"\n#include \"WinVersionHelper.h\"\n#include \"SimpleXML.h\"\n#include \"TaskbarDefaultStyle.h\"\n#include <map>\n#include \"OpenHardwareMonitor/OpenHardwareMonitorApi.h\"\n#include \"PluginManager.h\"\n#include \"Nullable.hpp\"\n#include \"TaskBarDlgDrawCommon.h\"\n#include \"DllFunctions.h\"\n#include \"StrTable.h\"\n#include \"PluginUpdateHelper.h\"\n#include \"PluginInterface.h\"\n\n// CTrafficMonitorApp:\n// 有关此类的实现，请参阅 TrafficMonitor.cpp\n//\n\n\nclass CTrafficMonitorApp : public CWinApp, public ITrafficMonitor\n{\npublic:\n    //各种路径\n    static CTrafficMonitorApp* self;\n    wstring m_module_dir;       //程序exe文件的目录\n    wstring m_appdata_dir;\n    wstring m_module_path;      //程序exe文件的路径\n    wstring m_module_path_reg;  //用于作为写入注册表开机自项的exe文件的路径（如果路径中有空格，加上引号）\n    wstring m_config_path;\n    wstring m_history_traffic_path;\n    wstring m_log_path;\n    wstring m_skin_path;\n    wstring m_system_dir;\n    wstring m_config_dir;\n\n    //以下数据定义为App类中的公共成员，以便于在主对话框和任务栏窗口中都能访问\n    unsigned __int64 m_in_speed{};      //下载速度\n    unsigned __int64 m_out_speed{};     //上传速度\n    int m_cpu_usage{ -1 };      //CPU利用率\n    int m_memory_usage{ -1 };   //内存利用率\n    int m_used_memory{};    //可用物理内存（单位为KB）\n    int m_total_memory{};   //物理内存总量（单位为KB）\n    float m_cpu_temperature{ -1 };  //CPU温度\n    float m_cpu_freq{ -1 };  //CPU 频率\n    float m_gpu_temperature{ -1 };  //显卡温度\n    float m_hdd_temperature{ -1 };  //硬盘温度\n    float m_main_board_temperature{ -1 };    //主板温度\n    int m_gpu_usage{ -1 };      //显卡利用率\n    int m_hdd_usage{ -1 };      //硬盘利用率\n\n    unsigned __int64 m_today_up_traffic{};  //今天已使用的上传流量\n    unsigned __int64 m_today_down_traffic{};    //今天已使用的下载流量\n\n    bool m_cannot_save_config_warning{ true };  //指示是否会在无法保存设置时弹出提示框\n    bool m_cannot_save_global_config_warning{ true };   //指示是否会在无法保存设置时弹出提示框\n\n    bool m_module_dir_writable{ true };         //指示程序所在目录是否可写\n\n    //选项设置数据\n    MainWndSettingData m_main_wnd_data;\n    TaskBarSettingData m_taskbar_data;\n    GeneralSettingData m_general_data;\n    //其他设置数据\n    MainConfigData m_cfg_data;\n    int m_notify_interval;      //弹出通知消息的时间间隔\n    bool m_debug_log{};\n    bool m_taksbar_transparent_color_enable{};\n    bool m_last_light_mode{};\n    bool m_show_mouse_panetrate_tip{};  //是否显示开启“鼠标穿透”时的提示消息。\n    bool m_show_dot_net_notinstalled_tip{};\n\n    //bool m_is_windows10_fall_creator;\n    CWinVersionHelper m_win_version;        //当前Windows的版本\n\n    HICON m_notify_icons[MAX_NOTIFY_ICON];\n\n    CTaskbarDefaultStyle m_taskbar_default_style;\n    CPluginManager m_plugins;\n    CDllFunctions m_dll_functions;\n    CStrTable m_str_table;\n    CPluginUpdateHelper m_plugin_update;\n\n    CMenu m_main_menu;          //主窗口右键菜单\n    CMenu m_main_menu_plugin;   //右击主窗口插件区域的右键菜单\n    CMenu m_main_menu_plugin_sub_menu;\n    CMenu m_taskbar_menu;       //任务栏窗口右键菜单\n    CMenu m_taskbar_menu_plugin;    //右击任务栏窗口插件区域的右键菜单\n    CMenu m_taskbar_menu_plugin_sub_menu;\n\n#ifndef WITHOUT_TEMPERATURE\n    //OpenHardwareMonitor 接口的指针\n    std::shared_ptr<OpenHardwareMonitorApi::IOpenHardwareMonitor> m_pMonitor{};\n#endif // !WITHOUT_TEMPERATURE\n\n    CCriticalSection m_minitor_lib_critical;        //用于访问OpenHardwareMonitor进行线程同步的临界区对象\n    //CCriticalSection m_lftable_critical;            //用于访问LfTable2进行线程同步的临界区对象\n    CLazyConstructable<class CTaskBarDlgDrawCommonSupport> m_d2d_taskbar_draw_common_support{}; // 当使用D2D渲染时自动初始化的全局依赖\n\npublic:\n    CTrafficMonitorApp();\n\n    void LoadLanguageConfig();\n    void LoadConfig();\n    void SaveConfig();\n    void LoadPluginDisabledSettings();\n\n    void LoadGlobalConfig();\n    void SaveGlobalConfig();\n\n    int DPI(int pixel);\n    void DPI(CRect& rect);\n    void DPIFromWindow(CWnd* pWnd);\n    int GetDpi() const { return m_dpi; }\n    void SetDPI(int dpi) { m_dpi = dpi; }\n\n    void CheckUpdate(bool message);     //检查更新，如果message为true，则在检查时弹出提示信息\n    void CheckUpdateInThread(bool message); //在后台线程中检查更新\n    //启动时检查更新线程函数\n    static UINT CheckUpdateThreadFunc(LPVOID lpParam);\n    static UINT InitOpenHardwareMonitorLibThreadFunc(LPVOID lpParam);\n\n    bool SetAutoRun(bool auto_run);\n    bool GetAutoRun(wstring* auto_run_path);        //判断是否开机自动进行，如果是，将开机自动运行的路径写入auto_run_path\n\n    bool SetAutoRunByRegistry(bool auto_run);       //通过注册表实现开机自启动\n    bool SetAutoRunByTaskScheduler(bool auto_run);  //通过任务计划实现开机自启动\n\n    //获取系统信息文本\n    CString GetSystemInfoString();\n\n    void InitMenuResourse();\n\n    //获取一个图标资源，如果资源还未加载，会自动加载。\n    //由于本函数中使用了CTrafficMonitorApp::DPI函数，因此本函数必须确保在CTrafficMonitorApp::DPIFromWindow之后调用\n    HICON GetMenuIcon(UINT id);\n\n    void AutoSelectNotifyIcon();\n\n    bool IsCheckingForUpdate() const { return m_checking_update; }      //是否正在检查更新\n\n    void InitOpenHardwareLibInThread();     //开启一个后台线程初始化OpenHardwareMonitor\n    void UpdateOpenHardwareMonitorEnableState();    //更新硬件监控的启用/禁用状态\n\n    //void UpdateTaskbarWndMenu();      //更新任务栏窗口右键菜单\n    bool IsForceShowNotifyIcon();       //是否需要强制显示通知区图标\n\n    std::wstring GetPlauginTooltipInfo() const;\n    bool IsTaksbarItemDisplayed(CommonDisplayItem item) const;\n\n    void SendSettingsToPlugin();    //向所有插件发送当前的选项设置\n\n    //更新插件子菜单\n    //plugin_cmd_start_index: 插件命令在菜单中的起始位置\n    static void UpdatePluginMenu(CMenu* pMenu, ITMPlugin* plugin, int plugin_cmd_start_index);\n\n    void CheckWindows11Taskbar();\n    bool IsWindows11Taskbar() const { return m_is_windows11_taskbar; }\n\n    bool DPIFromRect(const RECT& rect, UINT* out_dpi_x, UINT* out_dpi_y);\n\n    virtual unsigned int GetThemeColor() const override;\n    void SetThemeColor(COLORREF color);\n\nprivate:\n    //int m_no_multistart_warning_time{};       //用于设置在开机后多长时间内不弹出“已经有一个程序正在运行”的警告提示\n    bool m_no_multistart_warning{};         //如果为false，则永远都不会弹出“已经有一个程序正在运行”的警告提示\n    bool m_exit_when_start_by_restart_manager{ true };      //如果程序被Windows重启管理器重新启动，则退出程序\n    int m_dpi{ 96 };\n\n    bool m_checking_update{ false };        //是否正在检查更新\n\n    std::map<UINT, HICON> m_menu_icons;      //菜单图标资源。key是图标资源的ID，vlaue是图标的句柄\n\n    ULONG_PTR m_gdiplusToken{};\n\n    bool m_is_windows11_taskbar{ false };  //是否为Windows11的任务栏\n    COLORREF m_theme_color{};\n\n// 重写\npublic:\n    virtual BOOL InitInstance();\n\n    // 实现\n\n    DECLARE_MESSAGE_MAP()\n    afx_msg void OnHelp();\n    afx_msg void OnFrequentyAskedQuestions();\n    afx_msg void OnUpdateLog();\n    virtual int ExitInstance();\n\n    // 通过 ITrafficMonitor 继承\nprivate:\n    virtual int GetAPIVersion() override;\n    virtual const wchar_t* GetVersion() override;\n    double GetMonitorValue(MonitorItem item) override;\n    virtual const wchar_t* GetMonitorValueString(MonitorItem item, int is_main_window = false) override;\n    virtual const wchar_t* GetStringRes(const wchar_t* key, const wchar_t* section) override;\npublic:\n    void ShowNotifyMessage(const wchar_t* strMsg) override;\n    unsigned short GetLanguageId() const override;\n    const wchar_t* GetPluginConfigDir() const override;\n    int GetDPI(DPIType type) const override;\n};\n\nextern CTrafficMonitorApp theApp;\n"
  },
  {
    "path": "TrafficMonitor/TrafficMonitor.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup Label=\"ProjectConfigurations\">\r\n    <ProjectConfiguration Include=\"Debug (lite)|ARM64EC\">\r\n      <Configuration>Debug (lite)</Configuration>\r\n      <Platform>ARM64EC</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug (lite)|Win32\">\r\n      <Configuration>Debug (lite)</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug (lite)|x64\">\r\n      <Configuration>Debug (lite)</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|ARM64EC\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>ARM64EC</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|Win32\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release (lite)|ARM64EC\">\r\n      <Configuration>Release (lite)</Configuration>\r\n      <Platform>ARM64EC</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release (lite)|Win32\">\r\n      <Configuration>Release (lite)</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release (lite)|x64\">\r\n      <Configuration>Release (lite)</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|ARM64EC\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>ARM64EC</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|Win32\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>Win32</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Debug|x64\">\r\n      <Configuration>Debug</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n    <ProjectConfiguration Include=\"Release|x64\">\r\n      <Configuration>Release</Configuration>\r\n      <Platform>x64</Platform>\r\n    </ProjectConfiguration>\r\n  </ItemGroup>\r\n  <PropertyGroup Label=\"Globals\">\r\n    <ProjectGuid>{09483BED-B1E9-4827-8120-A18302C84AA8}</ProjectGuid>\r\n    <RootNamespace>TrafficMonitor</RootNamespace>\r\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\r\n    <Keyword>MFCProj</Keyword>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|Win32'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|ARM64EC'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>true</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|x64'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|ARM64EC'\" Label=\"Configuration\">\r\n    <ConfigurationType>Application</ConfigurationType>\r\n    <UseDebugLibraries>false</UseDebugLibraries>\r\n    <PlatformToolset>v143</PlatformToolset>\r\n    <WholeProgramOptimization>true</WholeProgramOptimization>\r\n    <CharacterSet>Unicode</CharacterSet>\r\n    <UseOfMfc>Dynamic</UseOfMfc>\r\n  </PropertyGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n  <ImportGroup Label=\"ExtensionSettings\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"Shared\">\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|Win32'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|ARM64EC'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|x64'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|ARM64EC'\" Label=\"PropertySheets\">\r\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\r\n  </ImportGroup>\r\n  <PropertyGroup Label=\"UserMacros\" />\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|Win32'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(SolutionDir)Bin\\x64\\$(Configuration)\\;$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|x64'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|ARM64EC'\">\r\n    <LinkIncremental>true</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(SolutionDir)Bin\\x64\\$(Configuration)\\;$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|Win32'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(SolutionDir)Bin\\x64\\$(Configuration)\\;$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|x64'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|ARM64EC'\">\r\n    <LinkIncremental>false</LinkIncremental>\r\n    <ExcludePath />\r\n    <OutDir>$(SolutionDir)Bin\\$(Platform)\\$(Configuration)\\</OutDir>\r\n    <IncludePath>$(ProjectDir);$(ProjectDir)..\\include;$(IncludePath)</IncludePath>\r\n    <LibraryPath>$(SolutionDir)lib\\x64;$(OutDir);$(SolutionDir)Bin\\x64\\$(Configuration)\\;$(LibraryPath)</LibraryPath>\r\n  </PropertyGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <TreatWarningAsError>false</TreatWarningAsError>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <AdditionalDependencies>OpenHardwareMonitorApi.lib;%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|Win32'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions);WITHOUT_TEMPERATURE</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <TreatWarningAsError>false</TreatWarningAsError>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <AdditionalDependencies>%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <AdditionalDependencies>OpenHardwareMonitorApi.lib;%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <AdditionalDependencies>OpenHardwareMonitorApi.lib;%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>\r\n      <DelayLoadDLLs>powrprof.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|x64'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions);WITHOUT_TEMPERATURE</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <AdditionalDependencies>%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|ARM64EC'\">\r\n    <ClCompile>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <Optimization>Disabled</Optimization>\r\n      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions);WITHOUT_TEMPERATURE</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <AdditionalDependencies>%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <DelayLoadDLLs>powrprof.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <AdditionalOptions>$(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>OpenHardwareMonitorApi.lib;%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|Win32'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions);WITHOUT_TEMPERATURE</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <AdditionalOptions>$(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>OpenHardwareMonitorApi.lib;%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>OpenHardwareMonitorApi.lib;%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>\r\n      <DelayLoadDLLs>powrprof.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|x64'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions);WITHOUT_TEMPERATURE</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <DelayLoadDLLs>powrprof.dll;api-ms-win-core-winrt-error-l1-1-1.dll;api-ms-win-core-winrt-l1-1-0.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|ARM64EC'\">\r\n    <ClCompile>\r\n      <WarningLevel>Level3</WarningLevel>\r\n      <PrecompiledHeader>Use</PrecompiledHeader>\r\n      <Optimization>MaxSpeed</Optimization>\r\n      <FunctionLevelLinking>true</FunctionLevelLinking>\r\n      <IntrinsicFunctions>true</IntrinsicFunctions>\r\n      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions);WITHOUT_TEMPERATURE</PreprocessorDefinitions>\r\n      <SDLCheck>true</SDLCheck>\r\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r\n      <LanguageStandard>stdcpp20</LanguageStandard>\r\n    </ClCompile>\r\n    <Link>\r\n      <SubSystem>Windows</SubSystem>\r\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r\n      <OptimizeReferences>true</OptimizeReferences>\r\n      <AdditionalDependencies>%(AdditionalDependencies);pdh.lib;Powrprof.lib;Dwmapi.lib</AdditionalDependencies>\r\n      <DelayLoadDLLs>powrprof.dll</DelayLoadDLLs>\r\n    </Link>\r\n    <Midl>\r\n      <MkTypLibCompatible>false</MkTypLibCompatible>\r\n      <ValidateAllParameters>true</ValidateAllParameters>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n    </Midl>\r\n    <ResourceCompile>\r\n      <Culture>0x0804</Culture>\r\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </ResourceCompile>\r\n    <PreBuildEvent>\r\n      <Command>print_compile_time.bat</Command>\r\n    </PreBuildEvent>\r\n    <FxCompile>\r\n      <AdditionalIncludeDirectories>$(UM_IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r\n    </FxCompile>\r\n    <PreLinkEvent>\r\n      <Command>\r\n      </Command>\r\n      <Message>\r\n      </Message>\r\n    </PreLinkEvent>\r\n  </ItemDefinitionGroup>\r\n  <ItemGroup>\r\n    <Text Include=\"compile_time.txt\" />\r\n    <Text Include=\"ReadMe.txt\" />\r\n    <Text Include=\"res\\Acknowledgement.txt\" />\r\n    <Text Include=\"res\\Acknowledgement_en.txt\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"..\\include\\PluginInterface.h\" />\r\n    <ClInclude Include=\"AboutDlg.h\" />\r\n    <ClInclude Include=\"AdapterCommon.h\" />\r\n    <ClInclude Include=\"AppAlreadyRuningDlg.h\" />\r\n    <ClInclude Include=\"auto_start_helper.h\" />\r\n    <ClInclude Include=\"BaseDialog.h\" />\r\n    <ClInclude Include=\"CalendarHelper.h\" />\r\n    <ClInclude Include=\"CAutoAdaptSettingsDlg.h\" />\r\n    <ClInclude Include=\"ClassicalTaskbarDlg.h\" />\r\n    <ClInclude Include=\"CMFCColorDialogEx.h\" />\r\n    <ClInclude Include=\"ColorSettingListCtrl.h\" />\r\n    <ClInclude Include=\"ComboBox2.h\" />\r\n    <ClInclude Include=\"crashtool.h\" />\r\n    <ClInclude Include=\"CTabCtrlEx.h\" />\r\n    <ClInclude Include=\"CVariant.h\" />\r\n    <ClInclude Include=\"D2D1Support.h\" />\r\n    <ClInclude Include=\"D3D10Support1.h\" />\r\n    <ClInclude Include=\"DCompositionSupport.h\" />\r\n    <ClInclude Include=\"DisplayItem.h\" />\r\n    <ClInclude Include=\"DisplayTextSettingDlg.h\" />\r\n    <ClInclude Include=\"DllFunctions.h\" />\r\n    <ClInclude Include=\"DrawCommonEx.h\" />\r\n    <ClInclude Include=\"DrawCommonFactory.h\" />\r\n    <ClInclude Include=\"DrawTextManager.h\" />\r\n    <ClInclude Include=\"Dxgi1Support2.h\" />\r\n    <ClInclude Include=\"FileDialogEx.h\" />\r\n    <ClInclude Include=\"FilePathHelper.h\" />\r\n    <ClInclude Include=\"HighResolutionTimer.h\" />\r\n    <ClInclude Include=\"HistoryTrafficCalendarDlg.h\" />\r\n    <ClInclude Include=\"HistoryTrafficFile.h\" />\r\n    <ClInclude Include=\"HistoryTrafficListDlg.h\" />\r\n    <ClInclude Include=\"HResultException.h\" />\r\n    <ClInclude Include=\"IDrawCommon.h\" />\r\n    <ClInclude Include=\"Image2DEffect.h\" />\r\n    <ClInclude Include=\"language.h\" />\r\n    <ClInclude Include=\"LinkStatic.h\" />\r\n    <ClInclude Include=\"ColorStatic.h\" />\r\n    <ClInclude Include=\"Common.h\" />\r\n    <ClInclude Include=\"CommonData.h\" />\r\n    <ClInclude Include=\"CSkinPreviewView.h\" />\r\n    <ClInclude Include=\"DrawCommon.h\" />\r\n    <ClInclude Include=\"GeneralSettingsDlg.h\" />\r\n    <ClInclude Include=\"HistoryTrafficDlg.h\" />\r\n    <ClInclude Include=\"IconSelectDlg.h\" />\r\n    <ClInclude Include=\"IniHelper.h\" />\r\n    <ClInclude Include=\"HistoryTrafficListCtrl.h\" />\r\n    <ClInclude Include=\"ListCtrlEx.h\" />\r\n    <ClInclude Include=\"MainWndColorDlg.h\" />\r\n    <ClInclude Include=\"MainWndSettingsDlg.h\" />\r\n    <ClInclude Include=\"MessageDlg.h\" />\r\n    <ClInclude Include=\"NetworkInfoDlg.h\" />\r\n    <ClInclude Include=\"Nullable.hpp\" />\r\n    <ClInclude Include=\"OptionsDlg.h\" />\r\n    <ClInclude Include=\"PdhHardwareQuery\\CPUUsage.h\" />\r\n    <ClInclude Include=\"PdhHardwareQuery\\CpuFreq.h\" />\r\n    <ClInclude Include=\"PdhHardwareQuery\\GpuUsage.h\" />\r\n    <ClInclude Include=\"PdhHardwareQuery\\DiskUsage.h\" />\r\n    <ClInclude Include=\"PdhHardwareQuery\\PdhQuery.h\" />\r\n    <ClInclude Include=\"PictureStatic.h\" />\r\n    <ClInclude Include=\"PluginInfoDlg.h\" />\r\n    <ClInclude Include=\"PluginManager.h\" />\r\n    <ClInclude Include=\"PluginManagerDlg.h\" />\r\n    <ClInclude Include=\"PluginUpdateHelper.h\" />\r\n    <ClInclude Include=\"RenderAPISupport.h\" />\r\n    <ClInclude Include=\"Resource.h\" />\r\n    <ClInclude Include=\"SelectConnectionsDlg.h\" />\r\n    <ClInclude Include=\"SetItemOrderDlg.h\" />\r\n    <ClInclude Include=\"SettingsHelper.h\" />\r\n    <ClInclude Include=\"SimpleXML.h\" />\r\n    <ClInclude Include=\"SkinAutoAdaptSettingDlg.h\" />\r\n    <ClInclude Include=\"SkinDlg.h\" />\r\n    <ClInclude Include=\"SkinFile.h\" />\r\n    <ClInclude Include=\"SkinManager.h\" />\r\n    <ClInclude Include=\"SpinEdit.h\" />\r\n    <ClInclude Include=\"StaticEx.h\" />\r\n    <ClInclude Include=\"stdafx.h\" />\r\n    <ClInclude Include=\"StrTable.h\" />\r\n    <ClInclude Include=\"SupportedRenderEnums.h\" />\r\n    <ClInclude Include=\"TabDlg.h\" />\r\n    <ClInclude Include=\"targetver.h\" />\r\n    <ClInclude Include=\"TaskbarColorDlg.h\" />\r\n    <ClInclude Include=\"TaskbarDefaultStyle.h\" />\r\n    <ClInclude Include=\"TaskBarDlg.h\" />\r\n    <ClInclude Include=\"TaskBarDlgDrawCommon.h\" />\r\n    <ClInclude Include=\"TaskbarHelper.h\" />\r\n    <ClInclude Include=\"TaskbarItemOrderHelper.h\" />\r\n    <ClInclude Include=\"TaskBarSettingsDlg.h\" />\r\n    <ClInclude Include=\"Test.h\" />\r\n    <ClInclude Include=\"TinyXml2Helper.h\" />\r\n    <ClInclude Include=\"tinyxml2\\tinyxml2.h\" />\r\n    <ClInclude Include=\"TrafficMonitor.h\" />\r\n    <ClInclude Include=\"TrafficMonitorDlg.h\" />\r\n    <ClInclude Include=\"UpdateHelper.h\" />\r\n    <ClInclude Include=\"WIC.h\" />\r\n    <ClInclude Include=\"Win11TaskbarDlg.h\" />\r\n    <ClInclude Include=\"Win11TaskbarSettingDlg.h\" />\r\n    <ClInclude Include=\"WindowsSettingHelper.h\" />\r\n    <ClInclude Include=\"WindowsWebExperienceDetector.h\" />\r\n    <ClInclude Include=\"WineTaskbarDlg.h\" />\r\n    <ClInclude Include=\"WinVersionHelper.h\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"AboutDlg.cpp\" />\r\n    <ClCompile Include=\"AdapterCommon.cpp\" />\r\n    <ClCompile Include=\"AppAlreadyRuningDlg.cpp\" />\r\n    <ClCompile Include=\"auto_start_helper.cpp\" />\r\n    <ClCompile Include=\"BaseDialog.cpp\" />\r\n    <ClCompile Include=\"CalendarHelper.cpp\" />\r\n    <ClCompile Include=\"CAutoAdaptSettingsDlg.cpp\" />\r\n    <ClCompile Include=\"ClassicalTaskbarDlg.cpp\" />\r\n    <ClCompile Include=\"CMFCColorDialogEx.cpp\" />\r\n    <ClCompile Include=\"ColorSettingListCtrl.cpp\" />\r\n    <ClCompile Include=\"ComboBox2.cpp\" />\r\n    <ClCompile Include=\"CommonData.cpp\" />\r\n    <ClCompile Include=\"crashtool.cpp\" />\r\n    <ClCompile Include=\"CTabCtrlEx.cpp\" />\r\n    <ClCompile Include=\"CVariant.cpp\" />\r\n    <ClCompile Include=\"D2D1Support.cpp\" />\r\n    <ClCompile Include=\"D3D10Support1.cpp\" />\r\n    <ClCompile Include=\"DCompositionSupport.cpp\" />\r\n    <ClCompile Include=\"DisplayItem.cpp\" />\r\n    <ClCompile Include=\"DisplayTextSettingDlg.cpp\" />\r\n    <ClCompile Include=\"DllFunctions.cpp\" />\r\n    <ClCompile Include=\"DrawCommonEx.cpp\" />\r\n    <ClCompile Include=\"DrawCommonFactory.cpp\" />\r\n    <ClCompile Include=\"DrawTextManager.cpp\" />\r\n    <ClCompile Include=\"Dxgi1Support2.cpp\" />\r\n    <ClCompile Include=\"FileDialogEx.cpp\" />\r\n    <ClCompile Include=\"FilePathHelper.cpp\" />\r\n    <ClCompile Include=\"HistoryTrafficCalendarDlg.cpp\" />\r\n    <ClCompile Include=\"HistoryTrafficFile.cpp\" />\r\n    <ClCompile Include=\"HistoryTrafficListDlg.cpp\" />\r\n    <ClCompile Include=\"HResultException.cpp\" />\r\n    <ClCompile Include=\"Image2DEffect.cpp\" />\r\n    <ClCompile Include=\"LinkStatic.cpp\" />\r\n    <ClCompile Include=\"ColorStatic.cpp\" />\r\n    <ClCompile Include=\"Common.cpp\" />\r\n    <ClCompile Include=\"CSkinPreviewView.cpp\" />\r\n    <ClCompile Include=\"DrawCommon.cpp\" />\r\n    <ClCompile Include=\"GeneralSettingsDlg.cpp\" />\r\n    <ClCompile Include=\"HistoryTrafficDlg.cpp\" />\r\n    <ClCompile Include=\"IconSelectDlg.cpp\" />\r\n    <ClCompile Include=\"IniHelper.cpp\" />\r\n    <ClCompile Include=\"HistoryTrafficListCtrl.cpp\" />\r\n    <ClCompile Include=\"ListCtrlEx.cpp\" />\r\n    <ClCompile Include=\"MainWndColorDlg.cpp\" />\r\n    <ClCompile Include=\"MainWndSettingsDlg.cpp\" />\r\n    <ClCompile Include=\"MessageDlg.cpp\" />\r\n    <ClCompile Include=\"NetworkInfoDlg.cpp\" />\r\n    <ClCompile Include=\"OptionsDlg.cpp\" />\r\n    <ClCompile Include=\"PdhHardwareQuery\\CPUUsage.cpp\" />\r\n    <ClCompile Include=\"PdhHardwareQuery\\CpuFreq.cpp\" />\r\n    <ClCompile Include=\"PdhHardwareQuery\\GpuUsage.cpp\" />\r\n    <ClCompile Include=\"PdhHardwareQuery\\DiskUsage.cpp\" />\r\n    <ClCompile Include=\"PdhHardwareQuery\\PdhQuery.cpp\" />\r\n    <ClCompile Include=\"PictureStatic.cpp\" />\r\n    <ClCompile Include=\"PluginInfoDlg.cpp\" />\r\n    <ClCompile Include=\"PluginManager.cpp\" />\r\n    <ClCompile Include=\"PluginManagerDlg.cpp\" />\r\n    <ClCompile Include=\"PluginUpdateHelper.cpp\" />\r\n    <ClCompile Include=\"SelectConnectionsDlg.cpp\" />\r\n    <ClCompile Include=\"SetItemOrderDlg.cpp\" />\r\n    <ClCompile Include=\"SettingsHelper.cpp\" />\r\n    <ClCompile Include=\"SimpleXML.cpp\" />\r\n    <ClCompile Include=\"SkinAutoAdaptSettingDlg.cpp\" />\r\n    <ClCompile Include=\"SkinDlg.cpp\" />\r\n    <ClCompile Include=\"SkinFile.cpp\" />\r\n    <ClCompile Include=\"SkinManager.cpp\" />\r\n    <ClCompile Include=\"SpinEdit.cpp\" />\r\n    <ClCompile Include=\"StaticEx.cpp\" />\r\n    <ClCompile Include=\"stdafx.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|Win32'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|ARM64EC'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|Win32'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|x64'\">Create</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|ARM64EC'\">Create</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"StrTable.cpp\" />\r\n    <ClCompile Include=\"SupportedRenderEnums.cpp\" />\r\n    <ClCompile Include=\"TabDlg.cpp\" />\r\n    <ClCompile Include=\"TaskbarColorDlg.cpp\" />\r\n    <ClCompile Include=\"TaskbarDefaultStyle.cpp\" />\r\n    <ClCompile Include=\"TaskBarDlg.cpp\" />\r\n    <ClCompile Include=\"TaskBarDlgDrawCommon.cpp\" />\r\n    <ClCompile Include=\"TaskbarHelper.cpp\" />\r\n    <ClCompile Include=\"TaskbarItemOrderHelper.cpp\" />\r\n    <ClCompile Include=\"TaskBarSettingsDlg.cpp\" />\r\n    <ClCompile Include=\"Test.cpp\" />\r\n    <ClCompile Include=\"TinyXml2Helper.cpp\" />\r\n    <ClCompile Include=\"tinyxml2\\tinyxml2.cpp\">\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|Win32'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|Win32'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM64EC'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Debug (lite)|ARM64EC'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM64EC'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|x64'\">NotUsing</PrecompiledHeader>\r\n      <PrecompiledHeader Condition=\"'$(Configuration)|$(Platform)'=='Release (lite)|ARM64EC'\">NotUsing</PrecompiledHeader>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TrafficMonitor.cpp\" />\r\n    <ClCompile Include=\"TrafficMonitorDlg.cpp\" />\r\n    <ClCompile Include=\"UpdateHelper.cpp\" />\r\n    <ClCompile Include=\"WIC.cpp\" />\r\n    <ClCompile Include=\"Win11TaskbarDlg.cpp\" />\r\n    <ClCompile Include=\"Win11TaskbarSettingDlg.cpp\" />\r\n    <ClCompile Include=\"WindowsSettingHelper.cpp\" />\r\n    <ClCompile Include=\"WindowsWebExperienceDetector.cpp\" />\r\n    <ClCompile Include=\"WineTaskbarDlg.cpp\" />\r\n    <ClCompile Include=\"WinVersionHelper.cpp\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"TrafficMonitor.rc\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"..\\LICENSE\" />\r\n    <None Include=\"..\\LICENSE_CN\" />\r\n    <None Include=\"language\\English.ini\" />\r\n    <None Include=\"language\\Simplified_Chinese.ini\" />\r\n    <None Include=\"language\\Traditional_Chinese.ini\" />\r\n    <None Include=\"res\\TrafficMonitor.rc2\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Image Include=\"res\\about_background.bmp\" />\r\n    <Image Include=\"res\\about_background_hd.bmp\" />\r\n    <Image Include=\"res\\bitmap3.bmp\" />\r\n    <Image Include=\"res\\menu_icon\\close.ico\" />\r\n    <Image Include=\"res\\menu_icon\\connection.ico\" />\r\n    <Image Include=\"res\\menu_icon\\exit.ico\" />\r\n    <Image Include=\"res\\menu_icon\\function.ico\" />\r\n    <Image Include=\"res\\menu_icon\\help.ico\" />\r\n    <Image Include=\"res\\menu_icon\\info.ico\" />\r\n    <Image Include=\"res\\menu_icon\\item.ico\" />\r\n    <Image Include=\"res\\menu_icon\\lock.ico\" />\r\n    <Image Include=\"res\\menu_icon\\main_window.ico\" />\r\n    <Image Include=\"res\\menu_icon\\more.ico\" />\r\n    <Image Include=\"res\\menu_icon\\mouse.ico\" />\r\n    <Image Include=\"res\\menu_icon\\notify.ico\" />\r\n    <Image Include=\"res\\menu_icon\\pin.ico\" />\r\n    <Image Include=\"res\\menu_icon\\plugins.ico\" />\r\n    <Image Include=\"res\\menu_icon\\plugin_disabled.ico\" />\r\n    <Image Include=\"res\\menu_icon\\setting.ico\" />\r\n    <Image Include=\"res\\menu_icon\\skn.ico\" />\r\n    <Image Include=\"res\\menu_icon\\statistics.ico\" />\r\n    <Image Include=\"res\\menu_icon\\taskbar_window.ico\" />\r\n    <Image Include=\"res\\menu_icon\\task_manager.ico\" />\r\n    <Image Include=\"res\\notifyicon.ico\" />\r\n    <Image Include=\"res\\notifyicon2.ico\" />\r\n    <Image Include=\"res\\notifyicon3.ico\" />\r\n    <Image Include=\"res\\notifyicon4.ico\" />\r\n    <Image Include=\"res\\notifyicon5.ico\" />\r\n    <Image Include=\"res\\notify_preview.bmp\" />\r\n    <Image Include=\"res\\notify_preview_light.bmp\" />\r\n    <Image Include=\"res\\TrafficMonitor.ico\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n  <ImportGroup Label=\"ExtensionTargets\">\r\n  </ImportGroup>\r\n  <ProjectExtensions>\r\n    <VisualStudio>\r\n      <UserProperties RESOURCE_FILE=\"TrafficMonitor.rc\" />\r\n    </VisualStudio>\r\n  </ProjectExtensions>\r\n</Project>"
  },
  {
    "path": "TrafficMonitor/TrafficMonitor.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <ItemGroup>\r\n    <Filter Include=\"资源文件\">\r\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\r\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\">\r\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\r\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\">\r\n      <UniqueIdentifier>{296f91e9-59c8-4e1c-9281-b3a5aad240d8}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\">\r\n      <UniqueIdentifier>{ccda107e-9fc9-493f-991e-b5a9f7dfe2f5}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\StaticEx\">\r\n      <UniqueIdentifier>{4745c17a-24c6-46a2-a075-b93654aae464}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\TaskBarDlg\">\r\n      <UniqueIdentifier>{19e2ade9-e461-4885-aa2e-7774b60ebc42}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\TrafficMonitor\">\r\n      <UniqueIdentifier>{3a1e6295-c622-4708-b984-c5e7d05db5df}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\TrafficMonitorDlg\">\r\n      <UniqueIdentifier>{22456594-86cd-4c0e-8ab9-e45cc6d78121}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\stdafx\">\r\n      <UniqueIdentifier>{ee6e7f72-a080-4020-92ff-432b8dcdad2f}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\选项设置对话框\">\r\n      <UniqueIdentifier>{98909116-8f3b-47d0-8e3f-ef90b29a2acc}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\HistoryTrafficDlg\">\r\n      <UniqueIdentifier>{feb21fbc-174b-4c26-aaa7-9f4b5e6ddd99}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\NetworkInfoDlg\">\r\n      <UniqueIdentifier>{cb7cc4d3-21ca-46e1-ab0e-a35ca66a5603}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\SkinDlg\">\r\n      <UniqueIdentifier>{79053472-785c-4667-a4f9-8b06a83ef04f}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\头文件\">\r\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\r\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\">\r\n      <UniqueIdentifier>{5db79e4d-ccae-4347-8e35-bea54fc5a0a7}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\IconSelectDlg\">\r\n      <UniqueIdentifier>{eedf8a29-f4cb-4c66-a019-593c9dfd81ae}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\PictureStatic\">\r\n      <UniqueIdentifier>{adb67f17-86da-401c-981c-c6f49a1f52ac}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\Common\">\r\n      <UniqueIdentifier>{7f523bbb-ec3f-4626-b1d8-ad45c2467dd0}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\DrawCommon\">\r\n      <UniqueIdentifier>{c4eace17-d9e5-43bf-8e13-30680c7c80be}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\SpinEdit\">\r\n      <UniqueIdentifier>{e63367cf-7c0d-4822-ac30-0f484e65f26d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\TabDlg\">\r\n      <UniqueIdentifier>{5d1d612c-7ef4-498c-9d8f-ad11555faa80}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\ColorStatic\">\r\n      <UniqueIdentifier>{1c3d2e37-c54d-429a-ac6f-efe82f02902c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\IniHelper\">\r\n      <UniqueIdentifier>{974cdadc-b70f-420b-b28b-c09a0686077c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\颜色设置对话框\">\r\n      <UniqueIdentifier>{66fdf1ef-3bc4-445a-b08e-4cd121d3455a}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\LinkStatic\">\r\n      <UniqueIdentifier>{6fce899f-3e92-40c2-a69b-ffcfb4a4c19f}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\CalendarHelper\">\r\n      <UniqueIdentifier>{9fa66474-d19b-4357-9813-e511bb20c722}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\AdapterCommon\">\r\n      <UniqueIdentifier>{75cd7f4d-06b2-467e-9960-994560da6e7b}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\WinVersionHelper\">\r\n      <UniqueIdentifier>{dd5aaacf-0f59-47ca-a738-250b15c6bbbb}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\AboutDlg\">\r\n      <UniqueIdentifier>{1f240f1b-347d-4281-a4cf-18bfebfacb6b}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\SimpleXML\">\r\n      <UniqueIdentifier>{8c35a0e3-e526-4f2f-9bc2-ed74dd37b238}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\颜色设置对话框\\MFCColorDialogEx\">\r\n      <UniqueIdentifier>{dd737159-8653-44d0-bf51-f0e3afad4e5c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\CTabCtrlEx\">\r\n      <UniqueIdentifier>{e5835851-f8d8-47dd-9669-f70b6f424386}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\CrashTool\">\r\n      <UniqueIdentifier>{12448ccc-0fa7-4f50-8261-dcb04f068e39}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\MessageDlg\">\r\n      <UniqueIdentifier>{645d28e7-da22-44f8-8e33-894109dde4b0}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\CVariant\">\r\n      <UniqueIdentifier>{1ca17ad5-07ba-4361-bbeb-fdc5047697fc}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\UpdateHelper\">\r\n      <UniqueIdentifier>{2b0e9f5d-dbce-4ba7-a158-7d9b705fcc02}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\BaseDialog\">\r\n      <UniqueIdentifier>{6f91f987-8834-4e89-b14e-d3ae15040848}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\TaskbarDefaultStyle\">\r\n      <UniqueIdentifier>{d2389f34-94a7-409a-97d0-47890e629c20}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\选项设置对话框\\AutoAdaptSettingsDlg\">\r\n      <UniqueIdentifier>{2393c651-03a5-467c-a927-a3e99fdc48c4}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\HistoryTrafficFile\">\r\n      <UniqueIdentifier>{5bf9c8c3-2115-4e6d-897c-432303615271}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"测试\">\r\n      <UniqueIdentifier>{df6d5fed-e1e8-4538-b028-f046ac67ad3f}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\WIC\">\r\n      <UniqueIdentifier>{2f6c60c6-eed6-4cad-8a1f-8759efb79d1d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\选项设置对话框\\DisplayTextSettingDlg\">\r\n      <UniqueIdentifier>{b6c785d6-4031-46d1-b224-4dd87a34404e}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\HistoryTrafficListCtrl\">\r\n      <UniqueIdentifier>{74012c97-afb7-4e09-8b11-4e2945c37449}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\ListCtrlEx\">\r\n      <UniqueIdentifier>{44872bda-27ce-407a-b5a7-fa9524bfb83c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\SkinFile\">\r\n      <UniqueIdentifier>{f2a40ca2-c391-46a6-8508-b2f8c30c68a2}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\TinyXml2Helper\">\r\n      <UniqueIdentifier>{ece2a796-fdd6-49e1-987e-11968b3f56a6}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\FilePathHelper\">\r\n      <UniqueIdentifier>{2ee3ad9e-4dc0-4ca4-91b1-2c6225bebd63}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\auto_start_helper\">\r\n      <UniqueIdentifier>{20b159a6-36ec-4d11-97c3-86e7c1501088}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\ColorSettingListCtrl\">\r\n      <UniqueIdentifier>{68b8c93d-e1b6-4d3d-a8af-5a19d413a96e}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\派生的控件类\\CComboBox2\">\r\n      <UniqueIdentifier>{abe84b35-de18-4853-9545-65354fb3d22f}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\HighResolutionTimer\">\r\n      <UniqueIdentifier>{c164ccd7-eb7c-465c-8828-d7a38eab573c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\tinyxml2\">\r\n      <UniqueIdentifier>{24b802e1-bc90-4f4c-8862-0ba6310f05f1}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\TaskbarItemOrderHelper\">\r\n      <UniqueIdentifier>{22cfb8c5-2d79-4f91-add4-fb393e20475e}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\选项设置对话框\\SetItemOrderDlg\">\r\n      <UniqueIdentifier>{bc164584-be21-4a91-9af5-772d61ed9529}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\PluginManager\">\r\n      <UniqueIdentifier>{f7dd3288-085a-4de2-9f83-d8ba2f3eff47}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\PluginManagerDlg\">\r\n      <UniqueIdentifier>{dbacfb68-1e03-4bcb-a08b-e87ba558985f}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\CommonData\">\r\n      <UniqueIdentifier>{554c1c22-3662-416f-9a24-ad76bfb5eecd}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\AppAlreadyRuningDlg\">\r\n      <UniqueIdentifier>{cecf73f6-6479-4ce2-aefe-879c9363ab24}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\选项设置对话框\\SelectConnectionsDlg\">\r\n      <UniqueIdentifier>{8a6deeaa-91ab-4c85-b293-ab1844f3ef82}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\WindowsSettingHelper\">\r\n      <UniqueIdentifier>{46dd548a-c66e-4a37-8767-6f9767125287}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\DllFunctions\">\r\n      <UniqueIdentifier>{a106d99c-80bb-4625-a64e-9d1ea24cad7c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\Nullable\">\r\n      <UniqueIdentifier>{f51d70bc-ec1d-45e9-9c57-777da2b6e51d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\DrawTextManager\">\r\n      <UniqueIdentifier>{af0ec00c-027f-4003-890e-7122d0b8df0c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\HResultException\">\r\n      <UniqueIdentifier>{48a72bdd-aca1-4367-9907-4bbb92dea212}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\Image2DEffect\">\r\n      <UniqueIdentifier>{b6684af7-c43e-42f7-9094-9315af53951d}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\RenderAPISupport\">\r\n      <UniqueIdentifier>{9e68f549-1373-437f-89f9-0b976150aa99}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\RenderAPISupport\\D2D1Support\">\r\n      <UniqueIdentifier>{9b93962c-26e9-41d5-a5e3-7dfd90bc5e96}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\RenderAPISupport\\D3D10Support1\">\r\n      <UniqueIdentifier>{f6a75faf-64b5-4f3b-a382-7dfd4a17d61c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\RenderAPISupport\\DCompositionSupport\">\r\n      <UniqueIdentifier>{9d71c24a-4df2-4df5-a536-741d890ada1b}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\RenderAPISupport\\DxgiSupport2\">\r\n      <UniqueIdentifier>{059ab3fb-f8b3-4cae-b5d3-72bd857e5197}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\WindowsWebExperienceDetector\">\r\n      <UniqueIdentifier>{4f233c31-4fef-48c1-8176-845ddd21debb}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\FileDialogEx\">\r\n      <UniqueIdentifier>{0745b192-f366-4a31-b238-d372d5b62492}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"资源文件\\icons\">\r\n      <UniqueIdentifier>{830bdf63-7703-45a3-9e5d-a87cc2f2bb70}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"资源文件\\bitmaps\">\r\n      <UniqueIdentifier>{322d1b74-5d71-43bd-ae50-b33f24b1b31c}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\对话框类\\选项设置对话框\\Win11TaskbarSettingDlg\">\r\n      <UniqueIdentifier>{d048fa7a-2509-4713-9df3-c537c4b35018}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"资源文件\\language\">\r\n      <UniqueIdentifier>{f1f6139c-f164-49f7-86e8-0e5ac6bef657}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\StrTable\">\r\n      <UniqueIdentifier>{357eeb5d-af51-4701-83c9-e13a17c7f771}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\SkinManager\">\r\n      <UniqueIdentifier>{28301057-fd34-4d04-a86a-0520143fdc14}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\PluginUpdateHelper\">\r\n      <UniqueIdentifier>{4d4d9bb2-17eb-4f13-978b-c204a1b227db}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\DisplayItem\">\r\n      <UniqueIdentifier>{4785624f-2ca9-4f92-8cfc-c7a7c3bfba74}</UniqueIdentifier>\r\n    </Filter>\r\n    <Filter Include=\"源文件和头文件\\公共的类\\PdhHardwareQuery\">\r\n      <UniqueIdentifier>{649b4ef9-4692-43a6-9365-c4445ec48c22}</UniqueIdentifier>\r\n    </Filter>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Text Include=\"ReadMe.txt\" />\r\n    <Text Include=\"res\\Acknowledgement.txt\">\r\n      <Filter>资源文件</Filter>\r\n    </Text>\r\n    <Text Include=\"compile_time.txt\" />\r\n    <Text Include=\"res\\Acknowledgement_en.txt\">\r\n      <Filter>资源文件</Filter>\r\n    </Text>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClInclude Include=\"targetver.h\">\r\n      <Filter>源文件和头文件\\头文件</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Resource.h\">\r\n      <Filter>源文件和头文件\\头文件</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"StaticEx.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\StaticEx</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TaskBarDlg.h\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TrafficMonitor.h\">\r\n      <Filter>源文件和头文件\\TrafficMonitor</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TrafficMonitorDlg.h\">\r\n      <Filter>源文件和头文件\\TrafficMonitorDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"stdafx.h\">\r\n      <Filter>源文件和头文件\\stdafx</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"MainWndSettingsDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TaskBarSettingsDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"OptionsDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"GeneralSettingsDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"HistoryTrafficDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\HistoryTrafficDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"NetworkInfoDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\NetworkInfoDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SkinDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\SkinDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"IconSelectDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\IconSelectDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PictureStatic.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\PictureStatic</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CSkinPreviewView.h\">\r\n      <Filter>源文件和头文件\\对话框类\\SkinDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Common.h\">\r\n      <Filter>源文件和头文件\\公共的类\\Common</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DrawCommon.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SpinEdit.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\SpinEdit</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TabDlg.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\TabDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ColorStatic.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\ColorStatic</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"IniHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\IniHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"MainWndColorDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\颜色设置对话框</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"LinkStatic.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\LinkStatic</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TaskbarColorDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\颜色设置对话框</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"HistoryTrafficListDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\HistoryTrafficDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"HistoryTrafficCalendarDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\HistoryTrafficDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CalendarHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\CalendarHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"AdapterCommon.h\">\r\n      <Filter>源文件和头文件\\公共的类\\AdapterCommon</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"WinVersionHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\WinVersionHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"AboutDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\AboutDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SimpleXML.h\">\r\n      <Filter>源文件和头文件\\公共的类\\SimpleXML</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CMFCColorDialogEx.h\">\r\n      <Filter>源文件和头文件\\对话框类\\颜色设置对话框\\MFCColorDialogEx</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CTabCtrlEx.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\CTabCtrlEx</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"crashtool.h\">\r\n      <Filter>源文件和头文件\\公共的类\\CrashTool</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"MessageDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\MessageDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CVariant.h\">\r\n      <Filter>源文件和头文件\\公共的类\\CVariant</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DrawCommonEx.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"UpdateHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\UpdateHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"BaseDialog.h\">\r\n      <Filter>源文件和头文件\\对话框类\\BaseDialog</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TaskbarDefaultStyle.h\">\r\n      <Filter>源文件和头文件\\公共的类\\TaskbarDefaultStyle</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CAutoAdaptSettingsDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\AutoAdaptSettingsDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"HistoryTrafficFile.h\">\r\n      <Filter>源文件和头文件\\公共的类\\HistoryTrafficFile</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Test.h\">\r\n      <Filter>测试</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"WIC.h\">\r\n      <Filter>源文件和头文件\\公共的类\\WIC</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DisplayTextSettingDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\DisplayTextSettingDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"HistoryTrafficListCtrl.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\HistoryTrafficListCtrl</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ListCtrlEx.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\ListCtrlEx</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SkinFile.h\">\r\n      <Filter>源文件和头文件\\公共的类\\SkinFile</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TinyXml2Helper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\TinyXml2Helper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"FilePathHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\FilePathHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"auto_start_helper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\auto_start_helper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ColorSettingListCtrl.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\ColorSettingListCtrl</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ComboBox2.h\">\r\n      <Filter>源文件和头文件\\派生的控件类\\CComboBox2</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"HighResolutionTimer.h\">\r\n      <Filter>源文件和头文件\\公共的类\\HighResolutionTimer</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"tinyxml2\\tinyxml2.h\">\r\n      <Filter>源文件和头文件\\公共的类\\tinyxml2</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TaskbarItemOrderHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\TaskbarItemOrderHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SetItemOrderDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\SetItemOrderDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"..\\include\\PluginInterface.h\">\r\n      <Filter>源文件和头文件\\头文件</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PluginManager.h\">\r\n      <Filter>源文件和头文件\\公共的类\\PluginManager</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PluginManagerDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\PluginManagerDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PluginInfoDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\PluginManagerDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"CommonData.h\">\r\n      <Filter>源文件和头文件\\公共的类\\CommonData</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"AppAlreadyRuningDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\AppAlreadyRuningDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SelectConnectionsDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\SelectConnectionsDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"WindowsSettingHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\WindowsSettingHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DllFunctions.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DllFunctions</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"D2D1Support.h\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\D2D1Support</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Nullable.hpp\">\r\n      <Filter>源文件和头文件\\公共的类\\Nullable</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DrawTextManager.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawTextManager</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"HResultException.h\">\r\n      <Filter>源文件和头文件\\公共的类\\HResultException</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"D3D10Support1.h\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\D3D10Support1</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Image2DEffect.h\">\r\n      <Filter>源文件和头文件\\公共的类\\Image2DEffect</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"IDrawCommon.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DrawCommonFactory.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"RenderAPISupport.h\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DCompositionSupport.h\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\DCompositionSupport</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Dxgi1Support2.h\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\DxgiSupport2</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TaskBarDlgDrawCommon.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SupportedRenderEnums.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"WindowsWebExperienceDetector.h\">\r\n      <Filter>源文件和头文件\\公共的类\\WindowsWebExperienceDetector</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SkinAutoAdaptSettingDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\SkinDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Win11TaskbarSettingDlg.h\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\Win11TaskbarSettingDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"FileDialogEx.h\">\r\n      <Filter>源文件和头文件\\公共的类\\FileDialogEx</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"StrTable.h\">\r\n      <Filter>源文件和头文件\\公共的类\\StrTable</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"language.h\">\r\n      <Filter>源文件和头文件\\头文件</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"ClassicalTaskbarDlg.h\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"Win11TaskbarDlg.h\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"TaskbarHelper.h\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SkinManager.h\">\r\n      <Filter>源文件和头文件\\公共的类\\SkinManager</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"SettingsHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\IniHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PluginUpdateHelper.h\">\r\n      <Filter>源文件和头文件\\公共的类\\PluginUpdateHelper</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"DisplayItem.h\">\r\n      <Filter>源文件和头文件\\公共的类\\DisplayItem</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"WineTaskbarDlg.h\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PdhHardwareQuery\\CPUUsage.h\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PdhHardwareQuery\\CpuFreq.h\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PdhHardwareQuery\\GpuUsage.h\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PdhHardwareQuery\\PdhQuery.h\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClInclude>\r\n    <ClInclude Include=\"PdhHardwareQuery\\DiskUsage.h\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClInclude>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ClCompile Include=\"StaticEx.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\StaticEx</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TaskBarDlg.cpp\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TrafficMonitor.cpp\">\r\n      <Filter>源文件和头文件\\TrafficMonitor</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TrafficMonitorDlg.cpp\">\r\n      <Filter>源文件和头文件\\TrafficMonitorDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"stdafx.cpp\">\r\n      <Filter>源文件和头文件\\stdafx</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"GeneralSettingsDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"MainWndSettingsDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TaskBarSettingsDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"OptionsDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"HistoryTrafficDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\HistoryTrafficDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"NetworkInfoDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\NetworkInfoDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SkinDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\SkinDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"IconSelectDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\IconSelectDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PictureStatic.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\PictureStatic</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CSkinPreviewView.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\SkinDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Common.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\Common</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DrawCommon.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SpinEdit.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\SpinEdit</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TabDlg.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\TabDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ColorStatic.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\ColorStatic</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"IniHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\IniHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"MainWndColorDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\颜色设置对话框</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"LinkStatic.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\LinkStatic</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TaskbarColorDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\颜色设置对话框</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"HistoryTrafficListDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\HistoryTrafficDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"HistoryTrafficCalendarDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\HistoryTrafficDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CalendarHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\CalendarHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"AdapterCommon.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\AdapterCommon</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"WinVersionHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\WinVersionHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"AboutDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\AboutDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SimpleXML.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\SimpleXML</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CMFCColorDialogEx.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\颜色设置对话框\\MFCColorDialogEx</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CTabCtrlEx.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\CTabCtrlEx</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"crashtool.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\CrashTool</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"MessageDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\MessageDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CVariant.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\CVariant</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DrawCommonEx.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"UpdateHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\UpdateHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"BaseDialog.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\BaseDialog</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TaskbarDefaultStyle.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\TaskbarDefaultStyle</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CAutoAdaptSettingsDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\AutoAdaptSettingsDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"HistoryTrafficFile.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\HistoryTrafficFile</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Test.cpp\">\r\n      <Filter>测试</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"WIC.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\WIC</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DisplayTextSettingDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\DisplayTextSettingDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"HistoryTrafficListCtrl.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\HistoryTrafficListCtrl</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ListCtrlEx.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\ListCtrlEx</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SkinFile.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\SkinFile</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TinyXml2Helper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\TinyXml2Helper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"FilePathHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\FilePathHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"auto_start_helper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\auto_start_helper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ColorSettingListCtrl.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\ColorSettingListCtrl</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ComboBox2.cpp\">\r\n      <Filter>源文件和头文件\\派生的控件类\\CComboBox2</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"tinyxml2\\tinyxml2.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\tinyxml2</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TaskbarItemOrderHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\TaskbarItemOrderHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SetItemOrderDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\SetItemOrderDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PluginManager.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\PluginManager</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PluginManagerDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\PluginManagerDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PluginInfoDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\PluginManagerDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"CommonData.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\CommonData</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"AppAlreadyRuningDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\AppAlreadyRuningDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SelectConnectionsDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\SelectConnectionsDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"WindowsSettingHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\WindowsSettingHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DllFunctions.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DllFunctions</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D2D1Support.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\D2D1Support</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DrawTextManager.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawTextManager</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"HResultException.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\HResultException</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"D3D10Support1.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\D3D10Support1</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Image2DEffect.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\Image2DEffect</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DrawCommonFactory.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DCompositionSupport.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\DCompositionSupport</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Dxgi1Support2.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\RenderAPISupport\\DxgiSupport2</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TaskBarDlgDrawCommon.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SupportedRenderEnums.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DrawCommon</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"WindowsWebExperienceDetector.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\WindowsWebExperienceDetector</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SkinAutoAdaptSettingDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\SkinDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Win11TaskbarSettingDlg.cpp\">\r\n      <Filter>源文件和头文件\\对话框类\\选项设置对话框\\Win11TaskbarSettingDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"FileDialogEx.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\FileDialogEx</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"StrTable.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\StrTable</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"ClassicalTaskbarDlg.cpp\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"Win11TaskbarDlg.cpp\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"TaskbarHelper.cpp\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SkinManager.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\SkinManager</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"SettingsHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\IniHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PluginUpdateHelper.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\PluginUpdateHelper</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"DisplayItem.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\DisplayItem</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"WineTaskbarDlg.cpp\">\r\n      <Filter>源文件和头文件\\TaskBarDlg</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PdhHardwareQuery\\CPUUsage.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PdhHardwareQuery\\CpuFreq.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PdhHardwareQuery\\GpuUsage.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PdhHardwareQuery\\PdhQuery.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClCompile>\r\n    <ClCompile Include=\"PdhHardwareQuery\\DiskUsage.cpp\">\r\n      <Filter>源文件和头文件\\公共的类\\PdhHardwareQuery</Filter>\r\n    </ClCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <ResourceCompile Include=\"TrafficMonitor.rc\">\r\n      <Filter>资源文件</Filter>\r\n    </ResourceCompile>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"res\\TrafficMonitor.rc2\">\r\n      <Filter>资源文件</Filter>\r\n    </None>\r\n    <None Include=\"..\\LICENSE\" />\r\n    <None Include=\"..\\LICENSE_CN\" />\r\n    <None Include=\"language\\Simplified_Chinese.ini\">\r\n      <Filter>资源文件\\language</Filter>\r\n    </None>\r\n    <None Include=\"language\\Traditional_Chinese.ini\">\r\n      <Filter>资源文件\\language</Filter>\r\n    </None>\r\n    <None Include=\"language\\English.ini\">\r\n      <Filter>资源文件\\language</Filter>\r\n    </None>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Image Include=\"res\\menu_icon\\close.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\connection.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\exit.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\function.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\help.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\info.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\item.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\lock.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\main_window.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\more.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\mouse.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\notify.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\notifyicon.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\notifyicon2.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\notifyicon3.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\notifyicon4.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\notifyicon5.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\pin.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\plugin_disabled.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\plugins.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\setting.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\skn.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\statistics.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\task_manager.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\menu_icon\\taskbar_window.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\TrafficMonitor.ico\">\r\n      <Filter>资源文件\\icons</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\about_background.bmp\">\r\n      <Filter>资源文件\\bitmaps</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\about_background_hd.bmp\">\r\n      <Filter>资源文件\\bitmaps</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\bitmap3.bmp\">\r\n      <Filter>资源文件\\bitmaps</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\notify_preview.bmp\">\r\n      <Filter>资源文件\\bitmaps</Filter>\r\n    </Image>\r\n    <Image Include=\"res\\notify_preview_light.bmp\">\r\n      <Filter>资源文件\\bitmaps</Filter>\r\n    </Image>\r\n  </ItemGroup>\r\n</Project>"
  },
  {
    "path": "TrafficMonitor/TrafficMonitorDlg.cpp",
    "content": "﻿\n// TrafficMonitorDlg.cpp : 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"TrafficMonitorDlg.h\"\n#include \"afxdialogex.h\"\n#include \"Test.h\"\n#include \"PluginManagerDlg.h\"\n#include \"SetItemOrderDlg.h\"\n#include \"WindowsSettingHelper.h\"\n#include \"PluginInfoDlg.h\"\n#include \"WIC.h\"\n#include \"SupportedRenderEnums.h\"\n#include \"ClassicalTaskbarDlg.h\"\n#include \"Win11TaskbarDlg.h\"\n#include \"WineTaskbarDlg.h\"\n#include \"TaskbarHelper.h\"\n#include \"SkinManager.h\"\n\n#ifdef _DEBUG\n#define new DEBUG_NEW\n#endif\n\n\n\n// CTrafficMonitorDlg 对话框\n\n//静态成员初始化\nunsigned int CTrafficMonitorDlg::m_WM_TASKBARCREATED{ ::RegisterWindowMessage(_T(\"TaskbarCreated\")) };  //注册任务栏建立的消息\n\nCTrafficMonitorDlg::CTrafficMonitorDlg(CWnd* pParent /*=NULL*/)\n    : CDialog(IDD_TRAFFICMONITOR_DIALOG, pParent)\n{\n    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);\n    m_desktop_dc = ::GetDC(NULL);\n}\n\nCTrafficMonitorDlg::~CTrafficMonitorDlg()\n{\n    free(m_pIfTable);\n\n    if (m_tBarDlg != nullptr)\n    {\n        delete m_tBarDlg;\n        m_tBarDlg = nullptr;\n    }\n\n    ::ReleaseDC(NULL, m_desktop_dc);\n}\n\nCTaskBarDlg* CTrafficMonitorDlg::GetTaskbarWindow() const\n{\n    if (IsTaskbarWndValid())\n        return m_tBarDlg;\n    else\n        return nullptr;\n}\n\nCTrafficMonitorDlg* CTrafficMonitorDlg::Instance()\n{\n    return dynamic_cast<CTrafficMonitorDlg*>(theApp.m_pMainWnd);\n}\n\nvoid CTrafficMonitorDlg::DoDataExchange(CDataExchange* pDX)\n{\n    CDialog::DoDataExchange(pDX);\n}\n\nBEGIN_MESSAGE_MAP(CTrafficMonitorDlg, CDialog)\n    ON_WM_QUERYDRAGICON()\n    ON_WM_TIMER()\n    ON_WM_RBUTTONUP()\n    ON_WM_LBUTTONDOWN()\n    ON_COMMAND(ID_NETWORK_INFO, &CTrafficMonitorDlg::OnNetworkInfo)\n    ON_COMMAND(ID_ALWAYS_ON_TOP, &CTrafficMonitorDlg::OnAlwaysOnTop)\n    ON_WM_INITMENUPOPUP()\n    ON_COMMAND(ID_TRANSPARENCY_100, &CTrafficMonitorDlg::OnTransparency100)\n    ON_COMMAND(ID_TRANSPARENCY_80, &CTrafficMonitorDlg::OnTransparency80)\n    ON_COMMAND(ID_TRANSPARENCY_60, &CTrafficMonitorDlg::OnTransparency60)\n    ON_COMMAND(ID_TRANSPARENCY_40, &CTrafficMonitorDlg::OnTransparency40)\n    ON_WM_CLOSE()\n    ON_WM_INITMENU()\n    ON_COMMAND(ID_LOCK_WINDOW_POS, &CTrafficMonitorDlg::OnLockWindowPos)\n    ON_WM_MOVE()\n    ON_MESSAGE(MY_WM_NOTIFYICON, &CTrafficMonitorDlg::OnNotifyIcon)\n    ON_COMMAND(ID_SHOW_NOTIFY_ICON, &CTrafficMonitorDlg::OnShowNotifyIcon)\n    ON_WM_DESTROY()\n    ON_COMMAND(ID_SHOW_CPU_MEMORY, &CTrafficMonitorDlg::OnShowCpuMemory)\n    ON_COMMAND(ID_MOUSE_PENETRATE, &CTrafficMonitorDlg::OnMousePenetrate)\n    ON_COMMAND(ID_SHOW_TASK_BAR_WND, &CTrafficMonitorDlg::OnShowTaskBarWnd)\n    ON_COMMAND(ID_APP_ABOUT, &CTrafficMonitorDlg::OnAppAbout)\n    ON_COMMAND(ID_SHOW_CPU_MEMORY2, &CTrafficMonitorDlg::OnShowCpuMemory2)\n    ON_COMMAND(ID_SHOW_MAIN_WND, &CTrafficMonitorDlg::OnShowMainWnd)\n    ON_COMMAND(ID_CHANGE_SKIN, &CTrafficMonitorDlg::OnChangeSkin)\n    ON_REGISTERED_MESSAGE(m_WM_TASKBARCREATED, &CTrafficMonitorDlg::OnTaskBarCreated)\n    ON_COMMAND(ID_TRAFFIC_HISTORY, &CTrafficMonitorDlg::OnTrafficHistory)\n    ON_WM_MOUSEMOVE()\n    ON_WM_LBUTTONDBLCLK()\n    ON_COMMAND(ID_OPTIONS, &CTrafficMonitorDlg::OnOptions)\n    ON_COMMAND(ID_OPTIONS2, &CTrafficMonitorDlg::OnOptions2)\n    ON_MESSAGE(WM_EXITMENULOOP, &CTrafficMonitorDlg::OnExitmenuloop)\n    ON_COMMAND(ID_CHANGE_NOTIFY_ICON, &CTrafficMonitorDlg::OnChangeNotifyIcon)\n    ON_COMMAND(ID_ALOW_OUT_OF_BORDER, &CTrafficMonitorDlg::OnAlowOutOfBorder)\n    ON_COMMAND(ID_CHECK_UPDATE, &CTrafficMonitorDlg::OnCheckUpdate)\n    ON_MESSAGE(WM_TASKBAR_MENU_POPED_UP, &CTrafficMonitorDlg::OnTaskbarMenuPopedUp)\n    ON_COMMAND(ID_SHOW_NET_SPEED, &CTrafficMonitorDlg::OnShowNetSpeed)\n    ON_WM_QUERYENDSESSION()\n    ON_WM_PAINT()\n    ON_MESSAGE(WM_DPICHANGED, &CTrafficMonitorDlg::OnDpichanged)\n    ON_MESSAGE(WM_TASKBAR_WND_CLOSED, &CTrafficMonitorDlg::OnTaskbarWndClosed)\n    ON_MESSAGE(WM_MONITOR_INFO_UPDATED, &CTrafficMonitorDlg::OnMonitorInfoUpdated)\n    ON_MESSAGE(WM_DISPLAYCHANGE, &CTrafficMonitorDlg::OnDisplaychange)\n    ON_WM_EXITSIZEMOVE()\n    ON_COMMAND(ID_PLUGIN_MANAGE, &CTrafficMonitorDlg::OnPluginManage)\n    ON_MESSAGE(WM_REOPEN_TASKBAR_WND, &CTrafficMonitorDlg::OnReopenTaksbarWnd)\n    ON_COMMAND(ID_OPEN_TASK_MANAGER, &CTrafficMonitorDlg::OnOpenTaskManager)\n    ON_MESSAGE(WM_SETTINGS_APPLIED, &CTrafficMonitorDlg::OnSettingsApplied)\n    ON_COMMAND(ID_DISPLAY_SETTINGS, &CTrafficMonitorDlg::OnDisplaySettings)\n    ON_WM_LBUTTONUP()\n    ON_COMMAND(ID_REFRESH_CONNECTION_LIST, &CTrafficMonitorDlg::OnRefreshConnectionList)\n    ON_MESSAGE(WM_TABLET_QUERYSYSTEMGESTURESTATUS, &CTrafficMonitorDlg::OnTabletQuerysystemgesturestatus)\n    ON_COMMAND(ID_PLUGIN_OPTIONS, &CTrafficMonitorDlg::OnPluginOptions)\n    ON_COMMAND(ID_PLUGIN_DETAIL, &CTrafficMonitorDlg::OnPluginDetail)\n    ON_COMMAND(ID_PLUGIN_OPTIONS_TASKBAR, &CTrafficMonitorDlg::OnPluginOptionsTaksbar)\n    ON_COMMAND(ID_PLUGIN_DETAIL_TASKBAR, &CTrafficMonitorDlg::OnPluginDetailTaksbar)\n    ON_WM_POWERBROADCAST()\n    ON_WM_DWMCOLORIZATIONCOLORCHANGED()\nEND_MESSAGE_MAP()\n\n\nCString CTrafficMonitorDlg::GetMouseTipsInfo()\n{\n    CString tip_info;\n    CString temp;\n    temp.Format(_T(\"%s: %s\\r\\n (%s: %s/%s: %s)\"), CCommon::LoadText(IDS_TRAFFIC_USED_TODAY),\n        CCommon::KBytesToString((theApp.m_today_up_traffic + theApp.m_today_down_traffic) / 1024u),\n        CCommon::LoadText(IDS_UPLOAD), CCommon::KBytesToString(theApp.m_today_up_traffic / 1024u),\n        CCommon::LoadText(IDS_DOWNLOAD), CCommon::KBytesToString(theApp.m_today_down_traffic / 1024u)\n    );\n    tip_info += temp;\n    const CSkinFile::Layout& skin_layout{ theApp.m_cfg_data.m_show_more_info ? m_skin.GetLayoutInfo().layout_l : m_skin.GetLayoutInfo().layout_s }; //当前的皮肤布局\n    if (!skin_layout.GetItem(TDI_UP).show)      //如果主窗口中没有显示上传速度，则在提示信息中显示上传速度\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/s\"), CCommon::LoadText(IDS_UPLOAD),\n            CCommon::DataSizeToString(theApp.m_out_speed, theApp.m_main_wnd_data));\n        tip_info += temp;\n    }\n    if (!skin_layout.GetItem(TDI_DOWN).show)\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/s\"), CCommon::LoadText(IDS_DOWNLOAD),\n            CCommon::DataSizeToString(theApp.m_in_speed, theApp.m_main_wnd_data));\n        tip_info += temp;\n    }\n    if (!skin_layout.GetItem(TDI_CPU).show)\n    {\n        temp.Format(_T(\"\\r\\n%s: %d %%\"), CCommon::LoadText(IDS_CPU_USAGE), theApp.m_cpu_usage);\n        tip_info += temp;\n    }\n    if (!skin_layout.GetItem(TDI_MEMORY).show)\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/%s (%d %%)\"), CCommon::LoadText(IDS_MEMORY_USAGE),\n            CCommon::KBytesToString(theApp.m_used_memory),\n            CCommon::KBytesToString(theApp.m_total_memory), theApp.m_memory_usage);\n        tip_info += temp;\n    }\n    else\n    {\n        temp.Format(_T(\"\\r\\n%s: %s/%s\"), CCommon::LoadText(IDS_MEMORY_USAGE),\n            CCommon::KBytesToString(theApp.m_used_memory),\n            CCommon::KBytesToString(theApp.m_total_memory));\n        tip_info += temp;\n    }\n    if (!skin_layout.GetItem(TDI_CPU_FREQ).show && theApp.m_cpu_freq >= 0)\n    {\n        temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_CPU_FREQ), CCommon::FreqToString(theApp.m_cpu_freq, theApp.m_main_wnd_data));\n        tip_info += temp;\n    }\n    if (!skin_layout.GetItem(TDI_GPU_USAGE).show && theApp.m_gpu_usage >= 0)\n    {\n        temp.Format(_T(\"\\r\\n%s: %d %%\"), CCommon::LoadText(IDS_GPU_USAGE), theApp.m_gpu_usage);\n        tip_info += temp;\n    }\n#ifndef WITHOUT_TEMPERATURE\n    if (IsTemperatureNeeded())\n    {\n        if (theApp.m_general_data.IsHardwareEnable(HI_CPU) && !skin_layout.GetItem(TDI_CPU_TEMP).show && theApp.m_cpu_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_CPU_TEMPERATURE), CCommon::TemperatureToString(theApp.m_cpu_temperature, theApp.m_main_wnd_data));\n            tip_info += temp;\n        }\n        if (theApp.m_general_data.IsHardwareEnable(HI_GPU) && !skin_layout.GetItem(TDI_GPU_TEMP).show && theApp.m_gpu_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_GPU_TEMPERATURE), CCommon::TemperatureToString(theApp.m_gpu_temperature, theApp.m_main_wnd_data));\n            tip_info += temp;\n        }\n        if (theApp.m_general_data.IsHardwareEnable(HI_HDD) && !skin_layout.GetItem(TDI_HDD_TEMP).show && theApp.m_hdd_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_HDD_TEMPERATURE), CCommon::TemperatureToString(theApp.m_hdd_temperature, theApp.m_main_wnd_data));\n            tip_info += temp;\n        }\n        if (theApp.m_general_data.IsHardwareEnable(HI_MBD) && !skin_layout.GetItem(TDI_MAIN_BOARD_TEMP).show && theApp.m_main_board_temperature > 0)\n        {\n            temp.Format(_T(\"\\r\\n%s: %s\"), CCommon::LoadText(IDS_MAINBOARD_TEMPERATURE), CCommon::TemperatureToString(theApp.m_main_board_temperature, theApp.m_main_wnd_data));\n            tip_info += temp;\n        }\n    }\n#endif\n    if (!skin_layout.GetItem(TDI_HDD_USAGE).show && theApp.m_hdd_usage >= 0)\n    {\n        temp.Format(_T(\"\\r\\n%s: %d %%\"), CCommon::LoadText(IDS_HDD_USAGE), theApp.m_hdd_usage);\n        tip_info += temp;\n}\n\n    //添加插件项目的鼠标提示\n    tip_info += theApp.GetPlauginTooltipInfo().c_str();\n\n    //if (IsTaskbarWndValid())\n    //{\n    //    tip_info += L\"\\r\\n\";\n    //    tip_info += m_tBarDlg->GetTaskbarDebugString().c_str();\n    //}\n\n    return tip_info;\n}\n\nvoid CTrafficMonitorDlg::SetTransparency()\n{\n    SetTransparency(theApp.m_cfg_data.m_transparency);\n}\n\nvoid CTrafficMonitorDlg::SetTransparency(int transparency)\n{\n    SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);\n    if (m_skin.IsPNG())\n    {\n        m_skin.SetAlpha(transparency * 255 / 100);\n    }\n    else\n    {\n        SetLayeredWindowAttributes(0, transparency * 255 / 100, LWA_ALPHA);  //透明度取值范围为0~255\n    }\n}\n\nvoid CTrafficMonitorDlg::SetAlwaysOnTop()\n{\n    //if (!m_is_foreground_fullscreen || (m_is_foreground_fullscreen && !theApp.m_main_wnd_data.hide_main_wnd_when_fullscreen))\n    //{\n    //  if (m_always_on_top)\n    //      SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);         //设置置顶\n    //  else\n    //      SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);       //取消置顶\n    //}\n    if (theApp.m_cfg_data.m_hide_main_window)\n        return;\n    else if (theApp.m_main_wnd_data.hide_main_wnd_when_fullscreen && m_is_foreground_fullscreen)        //当设置有程序全屏时隐藏悬浮窗且有程序在全屏运行时，不执行置顶操作\n        return;\n\n    if (theApp.m_main_wnd_data.m_always_on_top)\n        SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);         //设置置顶\n    else\n        SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);       //取消置顶\n\n}\n\nvoid CTrafficMonitorDlg::SetMousePenetrate()\n{\n    if (theApp.m_main_wnd_data.m_mouse_penetrate)\n    {\n        SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT);     //设置鼠标穿透\n    }\n    else\n    {\n        SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) & (~WS_EX_TRANSPARENT));      //取消鼠标穿透\n    }\n}\n\nPOINT CTrafficMonitorDlg::CalculateWindowMoveOffset(CRect rect, bool screen_changed)\n{\n    POINT mov{};    // 所需偏移量\n    if (m_screen_rects.size() != 0)\n    {\n        // 确保窗口完整在一个监视器内并且可见，判断移动距离并向所需移动距离较小的方向移动\n        LONG mov_xy = 0;          // 记录移动距离\n        int i = 0;\n        for (auto& a : m_screen_rects)\n        {\n            LONG x = 0, y = 0;\n            if (rect.left < a.left)                 // 需要向右移动\n                x = a.left - rect.left;\n            if (rect.top < a.top)                   // 需要向下移动\n                y = a.top - rect.top;\n\n            //防止连接新屏幕时 m_last_screen_rects 的数量小于 m_screen_rects 的数量导致访问到过大的索引\n            if (i >= m_last_screen_rects.size())\n            {\n                break;\n            }\n            CRect last_screen_rect = m_last_screen_rects[i];\n            if (screen_changed && a != last_screen_rect)\n            {\n                float proportion_width = (float)rect.left / (last_screen_rect.right - rect.Width());\n                float proportion_height = (float)rect.top / (last_screen_rect.bottom - rect.Height());\n                x = (a.right - rect.Width()) * proportion_width - rect.left;\n                y = (a.bottom - rect.Height()) * proportion_height - rect.top;\n            }\n            else\n            {\n                if (rect.right > a.right)          // 需要向左移动\n                    x = a.right - rect.right;\n                if (rect.bottom > a.bottom)        // 需要向上移动\n                    y = a.bottom - rect.bottom;\n            }\n            if (x == 0 && y == 0)           // 窗口已在一个监视器内\n            {\n                mov.x = 0;\n                mov.y = 0;\n                break;\n            }\n            else if (abs(x) + abs(y) < mov_xy || mov_xy == 0)\n            {\n                mov.x = x;\n                mov.y = y;\n                mov_xy = abs(x) + abs(y);\n            }\n            i++;\n        }\n    }\n    return mov;\n}\n\nvoid CTrafficMonitorDlg::CheckWindowPos(bool screen_changed)\n{\n    if (!theApp.m_main_wnd_data.m_alow_out_of_border)\n    {\n        CRect rect;\n        GetWindowRect(rect);\n        MoveWindow(rect + CalculateWindowMoveOffset(rect, screen_changed));\n    }\n}\n\nvoid CTrafficMonitorDlg::GetScreenSize()\n{\n    m_screen_size.cx = GetSystemMetrics(SM_CXSCREEN);\n    m_screen_size.cy = GetSystemMetrics(SM_CYSCREEN);\n\n    //::SystemParametersInfo(SPI_GETWORKAREA, 0, &m_screen_rect, 0);   // 获得工作区大小\n\n    //获取所有屏幕工作区的大小\n    m_last_screen_rects = m_screen_rects;\n    m_screen_rects.clear();\n    Monitors monitors;\n    for (auto& a : monitors.monitorinfos)\n    {\n        m_screen_rects.push_back(a.rcWork);\n    }\n}\n\n\nvoid CTrafficMonitorDlg::AutoSelect()\n{\n    unsigned __int64 max_in_out_bytes{};\n    unsigned __int64 in_out_bytes;\n    //m_connection_selected = m_connections[0].index;\n    m_connection_selected = 0;\n    //自动选择连接时，查找已发送和已接收字节数之和最多的那个连接，并将其设置为当前查看的连接\n    for (size_t i{}; i < m_connections.size(); i++)\n    {\n        auto table = GetConnectIfTable(i);\n        if (table.dwOperStatus == IF_OPER_STATUS_OPERATIONAL)     //只选择网络状态为正常的连接\n        {\n            in_out_bytes = table.dwInOctets + table.dwOutOctets;\n            if (in_out_bytes > max_in_out_bytes)\n            {\n                max_in_out_bytes = in_out_bytes;\n                m_connection_selected = i;\n            }\n        }\n    }\n    theApp.m_cfg_data.m_connection_name = GetConnection(m_connection_selected).description_2;\n    m_connection_change_flag = true;\n}\n\nvoid CTrafficMonitorDlg::IniConnection()\n{\n    //为m_pIfTable开辟所需大小的内存\n    free(m_pIfTable);\n    m_dwSize = sizeof(MIB_IFTABLE);\n    m_pIfTable = (MIB_IFTABLE*)malloc(m_dwSize);\n    int rtn;\n    rtn = GetIfTable(m_pIfTable, &m_dwSize, FALSE);\n    if (rtn == ERROR_INSUFFICIENT_BUFFER)\t//如果函数返回值为ERROR_INSUFFICIENT_BUFFER，说明m_pIfTable的大小不够\n    {\n        free(m_pIfTable);\n        m_pIfTable = (MIB_IFTABLE*)malloc(m_dwSize);\t//用新的大小重新开辟一块内存\n    }\n    GetIfTable(m_pIfTable, &m_dwSize, FALSE);\n\n    //获取当前所有的连接，并保存到m_connections容器中\n    if (!theApp.m_general_data.show_all_interface)\n    {\n        m_connections.clear();\n        vector<NetWorkConection> connections;\n        CAdapterCommon::GetAdapterInfo(connections);\n        for (const auto& item : connections)\n        {\n            if (!theApp.m_general_data.connections_hide.Contains(CCommon::StrToUnicode(item.description.c_str())))\n                m_connections.push_back(item);\n        }\n        CAdapterCommon::GetIfTableInfo(m_connections, m_pIfTable);\n    }\n    else\n    {\n        CAdapterCommon::GetAllIfTableInfo(m_connections, m_pIfTable);\n    }\n\n    //如果在设置了“显示所有网络连接”时设置了“选择全部”，则改为“自动选择”\n    if (theApp.m_general_data.show_all_interface && theApp.m_cfg_data.m_select_all)\n    {\n        theApp.m_cfg_data.m_select_all = false;\n        theApp.m_cfg_data.m_auto_select = true;\n    }\n\n    //写入调试日志\n    if (theApp.m_debug_log)\n    {\n        CString log_str;\n        log_str += _T(\"正在初始化网络连接...\\n\");\n        log_str += _T(\"连接列表：\\n\");\n        for (size_t i{}; i < m_connections.size(); i++)\n        {\n            log_str += m_connections[i].description.c_str();\n            log_str += _T(\", \");\n            log_str += CCommon::IntToString(m_connections[i].index);\n            log_str += _T(\"\\n\");\n        }\n        log_str += _T(\"IfTable:\\n\");\n        for (size_t i{}; i < m_pIfTable->dwNumEntries; i++)\n        {\n            log_str += CCommon::IntToString(i);\n            log_str += _T(\" \");\n            log_str += (const char*)m_pIfTable->table[i].bDescr;\n            log_str += _T(\"\\n\");\n        }\n        CCommon::WriteLog(log_str, (theApp.m_config_dir + L\".\\\\connections.log\").c_str());\n    }\n\n    //if (m_connection_selected < 0 || m_connection_selected >= m_connections.size() || m_auto_select)\n    //  AutoSelect();\n    //选择网络连接\n    if (theApp.m_cfg_data.m_auto_select)    //自动选择\n    {\n        if (m_restart_cnt != -1)    //当m_restart_cnt不等于-1时，即不是第一次初始化时，需要延时5秒再重新初始化连接\n        {\n            KillTimer(DELAY_TIMER);\n            SetTimer(DELAY_TIMER, 5000, NULL);\n        }\n        else\n        {\n            AutoSelect();\n        }\n    }\n    else        //查找网络名为上次选择的连接\n    {\n        m_connection_selected = 0;\n        for (size_t i{}; i < m_connections.size(); i++)\n        {\n            if (m_connections[i].description_2 == m_connection_name_preferd)\n                m_connection_selected = i;\n        }\n    }\n    if (m_connection_selected < 0 || m_connection_selected >= m_connections.size())\n        m_connection_selected = 0;\n    theApp.m_cfg_data.m_connection_name = GetConnection(m_connection_selected).description_2;\n\n    //根据已获取到的连接在菜单中添加相应项目\n    IniConnectionMenu(theApp.m_main_menu.GetSubMenu(0)->GetSubMenu(0));      //向“选择网络连接”子菜单项添加项目\n    IniConnectionMenu(theApp.m_main_menu_plugin.GetSubMenu(0)->GetSubMenu(0));      //向“选择网络连接”子菜单项添加项目\n\n    IniTaskBarConnectionMenu();     //初始化任务栏窗口中的“选择网络连接”子菜单项\n\n    m_restart_cnt++;    //记录初始化次数\n    m_connection_change_flag = true;\n}\n\nMIB_IFROW CTrafficMonitorDlg::GetConnectIfTable(int connection_index)\n{\n    if (connection_index >= 0 && connection_index < static_cast<int>(m_connections.size()))\n    {\n        int index = m_connections[connection_index].index;\n        if (m_pIfTable != nullptr && index >= 0 && index < m_pIfTable->dwNumEntries)\n            return m_pIfTable->table[index];\n    }\n    return MIB_IFROW();\n}\n\nNetWorkConection CTrafficMonitorDlg::GetConnection(int connection_index)\n{\n    if (connection_index >= 0 && connection_index < static_cast<int>(m_connections.size()))\n        return m_connections[connection_index];\n    else\n        return NetWorkConection();\n}\n\nvoid CTrafficMonitorDlg::IniConnectionMenu(CMenu* pMenu)\n{\n    ASSERT(pMenu != nullptr);\n    if (pMenu != nullptr)\n    {\n        //先将ID_SELECT_ALL_CONNECTION后面的所有菜单项删除\n        int start_pos = CCommon::GetMenuItemPosition(pMenu, ID_SELECT_ALL_CONNECTION) + 1;\n        while (pMenu->GetMenuItemCount() > start_pos)\n        {\n            pMenu->DeleteMenu(start_pos, MF_BYPOSITION);\n        }\n\n        CString connection_descr;\n        for (size_t i{}; i < m_connections.size(); i++)\n        {\n            connection_descr = CCommon::StrToUnicode(m_connections[i].description.c_str()).c_str();\n            pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_SELECT_ALL_CONNECTION + i + 1, connection_descr);\n        }\n\n        //添加“刷新网络列表”命令\n        pMenu->AppendMenu(MF_SEPARATOR);\n        pMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_REFRESH_CONNECTION_LIST, CCommon::LoadText(IDS_REFRESH_CONNECTION_LIST));\n    }\n}\n\nvoid CTrafficMonitorDlg::IniTaskBarConnectionMenu()\n{\n    //向“选择网络连接”子菜单项添加项目\n    IniConnectionMenu(theApp.m_taskbar_menu.GetSubMenu(0)->GetSubMenu(0));\n    IniConnectionMenu(theApp.m_taskbar_menu_plugin.GetSubMenu(0)->GetSubMenu(0));\n}\n\nvoid CTrafficMonitorDlg::SetConnectionMenuState(CMenu* pMenu)\n{\n    if (theApp.m_cfg_data.m_select_all)\n        pMenu->CheckMenuRadioItem(0, m_connections.size() + 1, 1, MF_BYPOSITION | MF_CHECKED);\n    else if (theApp.m_cfg_data.m_auto_select)       //m_auto_select为true时为自动选择，选中菜单的第1项\n        pMenu->CheckMenuRadioItem(0, m_connections.size() + 1, 0, MF_BYPOSITION | MF_CHECKED);\n    else        //m_auto_select为false时非自动选择，根据m_connection_selected的值选择对应的项\n        pMenu->CheckMenuRadioItem(0, m_connections.size() + 1, m_connection_selected + 2, MF_BYPOSITION | MF_CHECKED);\n\n    //没有设置为“选择全部”时，将当前选择项设置为默认菜单项（加粗显示）\n    if (!theApp.m_cfg_data.m_select_all)\n        pMenu->SetDefaultItem(m_connection_selected + 2, TRUE);\n    else\n        pMenu->SetDefaultItem(-1, TRUE);\n}\n\nvoid CTrafficMonitorDlg::CloseTaskBarWnd()\n{\n    if (m_tBarDlg != nullptr)\n    {\n        if (IsTaskbarWndValid())\n            m_tBarDlg->OnCancel();\n        delete m_tBarDlg;\n        m_tBarDlg = nullptr;\n        theApp.m_taskbar_data.update_layered_window_error_code = 0;\n    }\n}\n\nvoid CTrafficMonitorDlg::OpenTaskBarWnd()\n{\n    // 强制初始化theApp.m_is_windows11_taskbar的值\n    theApp.CheckWindows11Taskbar();\n    if (theApp.m_win_version.IsWine())\n        m_tBarDlg = new CWineTaskbarDlg();\n    else if (theApp.IsWindows11Taskbar())\n        m_tBarDlg = new CWin11TaskbarDlg();\n    else\n        m_tBarDlg = new CClassicalTaskbarDlg();\n\n    CSupportedRenderEnums supported_render_enums{};\n    CTaskBarDlg::DisableRenderFeatureIfNecessary(supported_render_enums);\n    auto render_type = supported_render_enums.GetAutoFitEnum();\n    // WS_EX_LAYERED 和 WS_EX_NOREDIRECTIONBITMAP 可以共存，见微软示例代码\n    // https://github.com/microsoft/Windows-classic-samples/blob/7cbd99ac1d2b4a0beffbaba29ea63d024ceff700/Samples/DynamicDPI/cpp/SampleDesktopWindow.cpp#L179\n    // 但是WS_EX_NOREDIRECTIONBITMAP似乎会导致UpdateLayeredWindowIndirect失败\n    switch (render_type)\n    {\n        using namespace DrawCommonHelper;\n    case RenderType::D2D1_WITH_DCOMPOSITION:\n        m_tBarDlg->Create(IDD_TASK_BAR_DIALOG_NOREDIRECTIONBITMAP, this);\n        break;\n    // 包括RenderType::D2D1在内的其他值\n    default:\n        m_tBarDlg->Create(IDD_TASK_BAR_DIALOG, this);\n        break;\n    }\n    m_tBarDlg->ShowWindow(SW_SHOW);\n    //m_tBarDlg->ShowInfo();\n    //IniTaskBarConnectionMenu();\n}\n\nvoid CTrafficMonitorDlg::AddNotifyIcon()\n{\n    if (theApp.m_cfg_data.m_show_task_bar_wnd)\n        CloseTaskBarWnd();\n    //添加通知栏图标\n    ::Shell_NotifyIcon(NIM_ADD, &m_ntIcon);\n    if (theApp.m_cfg_data.m_show_task_bar_wnd)\n        OpenTaskBarWnd();\n}\n\nvoid CTrafficMonitorDlg::DeleteNotifyIcon()\n{\n    if (theApp.m_cfg_data.m_show_task_bar_wnd)\n        CloseTaskBarWnd();\n    //删除通知栏图标\n    ::Shell_NotifyIcon(NIM_DELETE, &m_ntIcon);\n    if (theApp.m_cfg_data.m_show_task_bar_wnd)\n        OpenTaskBarWnd();\n}\n\nvoid CTrafficMonitorDlg::ShowNotifyTip(const wchar_t* title, const wchar_t* message)\n{\n    //要显示通知区提示，必须先将通知区图标显示出来\n    if (!theApp.m_general_data.show_notify_icon)\n    {\n        //添加通知栏图标\n        AddNotifyIcon();\n    }\n    //显示通知提示\n    m_ntIcon.uFlags |= NIF_INFO;\n    //wcscpy_s(m_ntIcon.szInfo, message ? message : _T(\"\"));\n    //wcscpy_s(m_ntIcon.szInfoTitle, title ? title : _T(\"\"));\n    CCommon::WStringCopy(m_ntIcon.szInfo, 256, message);\n    CCommon::WStringCopy(m_ntIcon.szInfoTitle, 64, title);\n    ::Shell_NotifyIcon(NIM_MODIFY, &m_ntIcon);\n    m_ntIcon.uFlags &= ~NIF_INFO;\n\n    //如果不显示通知区域图标，则在弹出通知的一段时间后删除通知区图标\n    if (!theApp.m_general_data.show_notify_icon)\n    {\n        //延迟一定时间后删除通知区图标\n        KillTimer(DELETE_NOTIFY_ICON_TIMER);\n        SetTimer(DELETE_NOTIFY_ICON_TIMER, 8000, NULL);\n    }\n}\n\nvoid CTrafficMonitorDlg::UpdateNotifyIconTip()\n{\n    CString strTip;         //鼠标指向图标时显示的提示\n#ifdef _DEBUG\n    strTip = CCommon::LoadText(IDS_TRAFFICMONITOR, _T(\" (Debug)\"));\n#else\n    strTip = CCommon::LoadText(IDS_TRAFFICMONITOR);\n#endif\n\n    CString in_speed = CCommon::DataSizeToString(theApp.m_in_speed);\n    CString out_speed = CCommon::DataSizeToString(theApp.m_out_speed);\n\n    strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%>/s\"), { CCommon::LoadText(IDS_UPLOAD), out_speed });\n    strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%>/s\"), { CCommon::LoadText(IDS_DOWNLOAD), in_speed });\n    strTip += CCommon::StringFormat(_T(\"\\r\\nCPU: <%1%> %\"), { theApp.m_cpu_usage });\n    strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%> %\"), { CCommon::LoadText(IDS_MEMORY), theApp.m_memory_usage });\n    if (IsTemperatureNeeded())\n    {\n        if (theApp.m_general_data.IsHardwareEnable(HI_GPU) && theApp.m_gpu_usage >= 0)\n            strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%> %\"), { CCommon::LoadText(IDS_GPU_USAGE), theApp.m_gpu_usage });\n        if (theApp.m_general_data.IsHardwareEnable(HI_CPU) && theApp.m_cpu_temperature > 0)\n            strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%> °C\"), { CCommon::LoadText(IDS_CPU_TEMPERATURE), static_cast<int>(theApp.m_cpu_temperature) });\n        if (theApp.m_general_data.IsHardwareEnable(HI_GPU) && theApp.m_gpu_temperature > 0)\n            strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%> °C\"), { CCommon::LoadText(IDS_GPU_TEMPERATURE), static_cast<int>(theApp.m_gpu_temperature) });\n        if (theApp.m_general_data.IsHardwareEnable(HI_HDD) && theApp.m_hdd_temperature > 0)\n            strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%> °C\"), { CCommon::LoadText(IDS_HDD_TEMPERATURE), static_cast<int>(theApp.m_hdd_temperature) });\n        if (theApp.m_general_data.IsHardwareEnable(HI_MBD) && theApp.m_main_board_temperature > 0)\n            strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%> °C\"), { CCommon::LoadText(IDS_MAINBOARD_TEMPERATURE), static_cast<int>(theApp.m_main_board_temperature) });\n        if (theApp.m_general_data.IsHardwareEnable(HI_HDD) && theApp.m_hdd_usage >= 0)\n            strTip += CCommon::StringFormat(_T(\"\\r\\n<%1%>: <%2%> %\"), { CCommon::LoadText(IDS_HDD_USAGE), theApp.m_hdd_usage });\n    }\n\n    CCommon::WStringCopy(m_ntIcon.szTip, 128, strTip);\n    ::Shell_NotifyIcon(NIM_MODIFY, &m_ntIcon);\n\n}\n\nvoid CTrafficMonitorDlg::SaveHistoryTraffic()\n{\n    m_history_traffic.Save();\n}\n\nvoid CTrafficMonitorDlg::LoadHistoryTraffic()\n{\n    m_history_traffic.Load();\n    CHistoryTrafficFile backup_file(theApp.m_history_traffic_path + L\".bak\");\n    backup_file.LoadSize();     //读取备份文件中流量记录的数量\n    if (backup_file.Size() > m_history_traffic.Size())      //如果备份文件中流量记录的数量大于当前的数量，则从备份文件中恢复\n    {\n        backup_file.Load();\n        size_t size_before = m_history_traffic.Size();\n        m_history_traffic.Merge(backup_file, true);\n        CString log_info = CCommon::LoadTextFormat(IDS_HISTORY_TRAFFIC_LOST_ERROR_LOG, { size_before, backup_file.Size() });\n        CCommon::WriteLog(log_info, theApp.m_log_path.c_str());\n    }\n\n    theApp.m_today_up_traffic = m_history_traffic.GetTodayUpTraffic();\n    theApp.m_today_down_traffic = m_history_traffic.GetTodayDownTraffic();\n}\n\nvoid CTrafficMonitorDlg::BackupHistoryTrafficFile()\n{\n    CHistoryTrafficFile backup_file(theApp.m_history_traffic_path + L\".bak\");\n    CHistoryTrafficFile latest_file(theApp.m_history_traffic_path);\n    backup_file.LoadSize();\n    latest_file.LoadSize();\n    if (backup_file.Size() < latest_file.Size())\n    {\n        CopyFile(latest_file.GetFilePath().c_str(), backup_file.GetFilePath().c_str(), FALSE);\n    }\n}\n\nvoid CTrafficMonitorDlg::_OnOptions(int tab, CWnd* pParent)\n{\n    COptionsDlg optionsDlg(tab, pParent);\n\n    //将选项设置数据传递给选项设置对话框\n    if (COptionsDlg::GetUniqueHandel(OPTION_DLG_NAME) == NULL)     //确保此时选项设置对话框已经关闭\n    {\n        optionsDlg.m_tab1_dlg.m_data = theApp.m_main_wnd_data;\n        optionsDlg.m_tab2_dlg.m_data = theApp.m_taskbar_data;\n        optionsDlg.m_tab3_dlg.m_data = theApp.m_general_data;\n        optionsDlg.m_tab1_dlg.m_text_disable = m_skin.GetLayoutInfo().no_label;\n    }\n\n    if (optionsDlg.DoModal() == IDOK)\n    {\n        ApplySettings(optionsDlg);\n    }\n}\n\nvoid CTrafficMonitorDlg::ApplySettings(COptionsDlg& optionsDlg)\n{\n    bool is_hardware_monitor_item_changed = (optionsDlg.m_tab3_dlg.m_data.hardware_monitor_item != theApp.m_general_data.hardware_monitor_item);\n    bool is_always_on_top_changed = (optionsDlg.m_tab1_dlg.m_data.m_always_on_top != theApp.m_main_wnd_data.m_always_on_top);\n    bool is_mouse_penerate_changed = (optionsDlg.m_tab1_dlg.m_data.m_mouse_penetrate != theApp.m_main_wnd_data.m_mouse_penetrate);\n    bool is_alow_out_of_border_changed = (optionsDlg.m_tab1_dlg.m_data.m_alow_out_of_border != theApp.m_main_wnd_data.m_alow_out_of_border);\n    bool is_show_notify_icon_changed = (optionsDlg.m_tab3_dlg.m_data.show_notify_icon != theApp.m_general_data.show_notify_icon);\n    bool is_connections_hide_changed = (optionsDlg.m_tab3_dlg.m_data.connections_hide.data() != theApp.m_general_data.connections_hide.data());\n    bool d2d_turned_on = (theApp.m_taskbar_data.disable_d2d && !optionsDlg.m_tab2_dlg.m_data.disable_d2d);\n    //需要重新关闭再打开任务栏窗口的情况\n    bool taskbar_changed = (theApp.m_taskbar_data.show_taskbar_wnd_in_secondary_display != optionsDlg.m_tab2_dlg.m_data.show_taskbar_wnd_in_secondary_display\n        || theApp.m_taskbar_data.secondary_display_index != optionsDlg.m_tab2_dlg.m_data.secondary_display_index\n        || theApp.m_taskbar_data.disable_d2d != optionsDlg.m_tab2_dlg.m_data.disable_d2d\n        || theApp.m_taskbar_data.IsTaskbarTransparent() != optionsDlg.m_tab2_dlg.m_data.IsTaskbarTransparent()\n        || theApp.m_taskbar_data.auto_set_background_color != optionsDlg.m_tab2_dlg.m_data.auto_set_background_color\n        );\n    bool is_skin_data_changed = (theApp.m_main_wnd_data.ToSkinSettingData() != optionsDlg.m_tab1_dlg.m_data.ToSkinSettingData());\n\n    theApp.m_main_wnd_data = optionsDlg.m_tab1_dlg.m_data;\n    theApp.m_taskbar_data = optionsDlg.m_tab2_dlg.m_data;\n    theApp.m_general_data = optionsDlg.m_tab3_dlg.m_data;\n    theApp.SendSettingsToPlugin();\n\n    CGeneralSettingsDlg::CheckTaskbarDisplayItem();\n\n    SetTextFont();\n\n    //打开了D2D渲染后自动开启“背景透明”并关闭“根据任务栏颜色自动设置背景色”\n    if (d2d_turned_on)\n    {\n        theApp.m_taskbar_data.SetTaskabrTransparent(true);\n        theApp.m_taskbar_data.auto_set_background_color = false;\n    }\n\n    //CTaskBarDlg::SaveConfig();\n    if (IsTaskbarWndValid())\n    {\n        m_tBarDlg->ApplySettings();\n        //如果更改了任务栏窗口字体或显示的文本，则任务栏窗口可能要变化，于是关闭再打开任务栏窗口\n        if (taskbar_changed)\n        {\n            CloseTaskBarWnd();\n            OpenTaskBarWnd();\n        }\n        else\n        {\n            m_tBarDlg->WidthChanged();\n        }\n        m_tBarDlg->ApplyWindowTransparentColor();\n    }\n\n    if (optionsDlg.m_tab3_dlg.IsAutoRunModified())\n    {\n        if (!theApp.SetAutoRun(theApp.m_general_data.auto_run))\n            MessageBox(CCommon::LoadText(IDS_SET_AUTO_RUN_FAILED_WARNING), NULL, MB_ICONWARNING | MB_OK);\n    }\n\n    if (optionsDlg.m_tab3_dlg.IsShowAllInterfaceModified() || is_connections_hide_changed)\n        IniConnection();\n\n    if (optionsDlg.m_tab3_dlg.IsMonitorTimeSpanModified())      //如果监控时间间隔改变了，则重设定时器\n    {\n        KillTimer(MONITOR_TIMER);\n        SetTimer(MONITOR_TIMER, theApp.m_general_data.monitor_time_span, NULL);\n    }\n\n    //设置获取CPU利用率的方式\n    m_cpu_usage_helper.SetUseCPUTimes(theApp.m_general_data.cpu_usage_acquire_method != GeneralSettingData::CA_PDH);\n\n#ifndef WITHOUT_TEMPERATURE\n    if (is_hardware_monitor_item_changed)\n    {\n        //如果关闭了硬件监控，则析构硬件监控类\n        if (theApp.m_general_data.hardware_monitor_item == 0)\n        {\n            CSingleLock sync(&theApp.m_minitor_lib_critical, TRUE);\n            theApp.m_pMonitor.reset();\n        }\n        else if (theApp.m_pMonitor != nullptr)\n        {\n            theApp.UpdateOpenHardwareMonitorEnableState();\n        }\n        else if (IsTemperatureNeeded())\n        {\n            theApp.InitOpenHardwareLibInThread();\n        }\n        //更新任务栏窗口右键菜单\n        //theApp.UpdateTaskbarWndMenu();\n    }\n#endif\n\n    if (is_always_on_top_changed)\n    {\n        SetAlwaysOnTop();\n    }\n\n    if (is_mouse_penerate_changed)\n    {\n        SetMousePenetrate();\n        if (!theApp.m_general_data.show_notify_icon && theApp.IsForceShowNotifyIcon())   //鼠标穿透时，如果通知图标没有显示，则将它显示出来，否则无法呼出右键菜单\n        {\n            //添加通知栏图标\n            AddNotifyIcon();\n            theApp.m_general_data.show_notify_icon = true;\n        }\n    }\n\n    if (is_alow_out_of_border_changed)\n    {\n        CheckWindowPos();\n    }\n\n    if (is_show_notify_icon_changed)\n    {\n        if (theApp.IsForceShowNotifyIcon())\n            theApp.m_general_data.show_notify_icon = true;\n        if (theApp.m_general_data.show_notify_icon)\n            AddNotifyIcon();\n        else\n            DeleteNotifyIcon();\n    }\n\n    if (is_skin_data_changed)\n    {\n        //将当前皮肤设置保存到SkinManager\n        SkinSettingData skin_data = theApp.m_main_wnd_data.ToSkinSettingData();\n        CSkinManager::Instance().AddSkinSettingData(theApp.m_cfg_data.m_skin_name, skin_data);\n        CSkinManager::Instance().Save();\n    }\n\n    theApp.SaveConfig();\n    theApp.SaveGlobalConfig();\n}\n\nvoid CTrafficMonitorDlg::SetItemPosition()\n{\n    if (theApp.m_cfg_data.m_show_more_info)\n    {\n        SetWindowPos(nullptr, 0, 0, m_skin.GetLayoutInfo().layout_l.width, m_skin.GetLayoutInfo().layout_l.height, SWP_NOMOVE | SWP_NOZORDER);\n    }\n    else\n    {\n        SetWindowPos(nullptr, 0, 0, m_skin.GetLayoutInfo().layout_s.width, m_skin.GetLayoutInfo().layout_s.height, SWP_NOMOVE | SWP_NOZORDER);\n    }\n}\n\nbool CTrafficMonitorDlg::LoadSkinLayout()\n{\n    bool rtn = m_skin.Load(CSkinManager::Instance().GetSkinName(m_skin_selected));\n    if (m_skin.GetLayoutInfo().no_label)        //如果皮肤布局不显示文本，则不允许交换上传和下载的位置，因为上传和下载的位置已经固定在皮肤中了\n        theApp.m_main_wnd_data.swap_up_down = false;\n    return rtn;\n}\n\nvoid CTrafficMonitorDlg::LoadBackGroundImage()\n{\n    CImage img_tmp;\n    CSize image_size;\n    if (theApp.m_cfg_data.m_show_more_info)\n    {\n        image_size.SetSize(m_skin.GetLayoutInfo().layout_l.width, m_skin.GetLayoutInfo().layout_l.height);\n    }\n    else\n    {\n        image_size.SetSize(m_skin.GetLayoutInfo().layout_s.width, m_skin.GetLayoutInfo().layout_s.height);\n    }\n\n    //创建窗口区域\n    CImage img_mask;\n    //载入掩码图片\n    if (theApp.m_cfg_data.m_show_more_info)\n        img_tmp.Load((theApp.m_skin_path + CSkinManager::Instance().GetSkinName(m_skin_selected) + BACKGROUND_MASK_L).c_str());\n    else\n        img_tmp.Load((theApp.m_skin_path + CSkinManager::Instance().GetSkinName(m_skin_selected) + BACKGROUND_MASK_S).c_str());\n    CRgn wnd_rgn;\n    if (!img_tmp.IsNull())\n    {\n        CDrawCommon::BitmapStretch(&img_tmp, &img_mask, image_size);        //拉伸掩码图片\n        CBitmap bitmap;\n        bitmap.Attach(img_mask);\n        CDrawCommon::GetRegionFromImage(wnd_rgn, bitmap, 128);      //从掩码图片获得窗口的区域\n        bitmap.Detach();\n    }\n    else\n    {\n        wnd_rgn.CreateRectRgnIndirect(CRect(CPoint(0, 0), image_size));     //载入掩码图片失败，则使用窗口大小作为窗口区域\n    }\n    //避免获取到的窗口区域为空\n    CRgn empty_rgn;\n    empty_rgn.CreateRectRgnIndirect(CRect{});   //创建一个空的CRgn对象\n    if (wnd_rgn.EqualRgn(&empty_rgn))\n        wnd_rgn.SetRectRgn(CRect(CPoint(0, 0), image_size));    //如果获取到的窗口区域为空，则使用窗口大小作为窗口区域\n    SetWindowRgn(wnd_rgn, TRUE);        //设置窗口区域\n    wnd_rgn.DeleteObject();\n    empty_rgn.DeleteObject();\n}\n\nvoid CTrafficMonitorDlg::SetTextFont()\n{\n    m_skin.SetSettingData(theApp.m_main_wnd_data.ToSkinSettingData());\n}\n\nbool CTrafficMonitorDlg::IsTaskbarWndValid() const\n{\n    return m_tBarDlg != nullptr && ::IsWindow(m_tBarDlg->GetSafeHwnd());\n}\n\nvoid CTrafficMonitorDlg::TaskbarShowHideItem(DisplayItem type)\n{\n    if (IsTaskbarWndValid())\n    {\n        bool show = (theApp.m_taskbar_data.display_item.Contains(type));\n        if (show)\n        {\n            theApp.m_taskbar_data.display_item.Remove(type);\n        }\n        else\n        {\n            theApp.m_taskbar_data.display_item.Add(type);\n        }\n        //CloseTaskBarWnd();\n        //OpenTaskBarWnd();\n        m_tBarDlg->WidthChanged();\n    }\n}\n\nvoid CTrafficMonitorDlg::CheckClickedItem(CPoint point)\n{\n    const CSkinFile::Layout& skin_layout{ theApp.m_cfg_data.m_show_more_info ? m_skin.GetLayoutInfo().layout_l : m_skin.GetLayoutInfo().layout_s }; //当前的皮肤布局\n    for (const auto& layout_item : skin_layout.layout_items)\n    {\n        CRect rect(CPoint(layout_item.second.x, layout_item.second.y), CSize(layout_item.second.width, m_skin.GetLayoutInfo().text_height));\n        if (rect.PtInRect(point))\n        {\n            m_clicked_item = layout_item.first;\n            break;\n        }\n    }\n}\n\nvoid CTrafficMonitorDlg::ApplySkin(int skin_index)\n{\n    if (skin_index < 0 || skin_index >= CSkinManager::Instance().Size())\n        return;\n    m_skin_selected = skin_index;\n    theApp.m_cfg_data.m_skin_name = CSkinManager::Instance().GetSkinName(m_skin_selected);\n    //获取皮肤布局\n    LoadSkinLayout();\n    //载入背景图片\n    LoadBackGroundImage();\n    //获取皮肤设置\n    SkinSettingData cur_skin_data;\n    if (!CSkinManager::Instance().GetSkinSettingDataByIndex(m_skin_selected, cur_skin_data))\n    {\n        CSkinManager::SkinSettingDataFronSkin(cur_skin_data, m_skin);\n    }\n    theApp.m_main_wnd_data.FormSkinSettingData(cur_skin_data);\n    SetTextFont();\n    SetItemPosition();\n    Invalidate(FALSE);      //更换皮肤后立即刷新窗口信息\n    //重新设置WS_EX_LAYERED样式，以解决在png皮肤和bmp皮肤之间切换时显示不正常的问题\n    //清除窗口的分层样式\n    SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);\n    //重新设置透明度\n    SetTransparency();\n\n    theApp.SaveConfig();\n}\n\nbool CTrafficMonitorDlg::IsTemperatureNeeded() const\n{\n    //判断是否需要从OpenHardwareMonitor获取信息。\n    ////只有主窗口和任务栏窗口中CPU温度、显卡利用率、显卡温度、硬盘温度和主板温度中至少有一个要显示，才返回true\n    //bool needed = false;\n    //if (theApp.m_cfg_data.m_show_task_bar_wnd && IsTaskbarWndValid())\n    //{\n    //    needed |= m_tBarDlg->IsShowCpuTemperature();\n    //    needed |= m_tBarDlg->IsShowGpu();\n    //    needed |= m_tBarDlg->IsShowGpuTemperature();\n    //    needed |= m_tBarDlg->IsShowHddTemperature();\n    //    needed |= m_tBarDlg->IsShowMainboardTemperature();\n    //    needed |= (::IsWindow(m_tBarDlg->m_tool_tips.GetSafeHwnd()) && m_tBarDlg->m_tool_tips.IsWindowVisible());\n    //}\n\n    //if (!theApp.m_cfg_data.m_hide_main_window)\n    //{\n    //    const CSkinFile::Layout& skin_layout{ theApp.m_cfg_data.m_show_more_info ? m_skin.GetLayoutInfo().layout_l : m_skin.GetLayoutInfo().layout_s }; //当前的皮肤布局\n    //    needed |= skin_layout.GetItem(TDI_CPU_TEMP).show;\n    //    needed |= skin_layout.GetItem(TDI_GPU_USAGE).show;\n    //    needed |= skin_layout.GetItem(TDI_GPU_TEMP).show;\n    //    needed |= skin_layout.GetItem(TDI_HDD_TEMP).show;\n    //    needed |= skin_layout.GetItem(TDI_MAIN_BOARD_TEMP).show;\n    //    needed |= (::IsWindow(m_tool_tips.GetSafeHwnd()) && m_tool_tips.IsWindowVisible());\n    //}\n    //return needed;\n\n    return theApp.m_general_data.IsHardwareEnable(HI_CPU) || theApp.m_general_data.IsHardwareEnable(HI_GPU)\n        || theApp.m_general_data.IsHardwareEnable(HI_HDD) || theApp.m_general_data.IsHardwareEnable(HI_MBD);\n}\n\n// CTrafficMonitorDlg 消息处理程序\n\nBOOL CTrafficMonitorDlg::OnInitDialog()\n{\n    CDialog::OnInitDialog();\n\n    // 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动\n    //  执行此操作\n    SetIcon(m_hIcon, TRUE);         // 设置大图标\n    SetIcon(m_hIcon, FALSE);        // 设置小图标\n\n    // TODO: 在此添加额外的初始化代码\n    SetWindowText(APP_NAME);\n    //设置隐藏任务栏图标\n    ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);\n\n    theApp.DPIFromWindow(this);\n    //获取屏幕大小\n    GetScreenSize();\n    m_last_screen_rects = m_screen_rects;\n    //::SystemParametersInfo(SPI_GETWORKAREA, 0, &m_screen_rect, 0);   // 获得工作区大小\n\n    //初始化菜单\n    theApp.InitMenuResourse();\n    //theApp.UpdateTaskbarWndMenu();\n\n    //初始化皮肤\n    CSkinManager::Instance().Init();\n    m_skin_selected = CSkinManager::Instance().FindSkinIndex(theApp.m_cfg_data.m_skin_name);\n\n    //根据当前选择的皮肤获取布局数据\n    if (LoadSkinLayout())\n    {\n        //从SkinManager中获取当前皮肤的设置\n        SkinSettingData cur_skin_data;\n        CSkinManager::SkinSettingDataFronSkin(cur_skin_data, m_skin);   //获取皮肤的默认设置\n        CSkinManager::Instance().GetSkinSettingDataByIndex(m_skin_selected, cur_skin_data); //获取皮肤的用户保存的数据\n        theApp.m_main_wnd_data.FormSkinSettingData(cur_skin_data);\n    }\n\n    //设置窗口透明度\n    SetTransparency();\n\n    IniConnection();    //初始化连接\n\n    //如果启动时设置了鼠标穿透或隐藏主窗口，并且没有显示任务栏窗口，则显示通知区图标\n    if ((theApp.m_main_wnd_data.m_mouse_penetrate || theApp.m_cfg_data.m_hide_main_window) && !theApp.m_cfg_data.m_show_task_bar_wnd)\n        theApp.m_general_data.show_notify_icon = true;\n\n    //载入通知区图标\n    theApp.m_notify_icons[0] = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_NOFITY_ICON), IMAGE_ICON, theApp.DPI(16), theApp.DPI(16), LR_DEFAULTCOLOR | LR_CREATEDIBSECTION);\n    theApp.m_notify_icons[1] = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_NOFITY_ICON2), IMAGE_ICON, theApp.DPI(16), theApp.DPI(16), LR_DEFAULTCOLOR | LR_CREATEDIBSECTION);\n    theApp.m_notify_icons[2] = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_NOFITY_ICON3), IMAGE_ICON, theApp.DPI(16), theApp.DPI(16), LR_DEFAULTCOLOR | LR_CREATEDIBSECTION);\n    theApp.m_notify_icons[3] = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, theApp.DPI(16), theApp.DPI(16), LR_DEFAULTCOLOR | LR_CREATEDIBSECTION);\n    theApp.m_notify_icons[4] = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_NOFITY_ICON4), IMAGE_ICON, theApp.DPI(16), theApp.DPI(16), LR_DEFAULTCOLOR | LR_CREATEDIBSECTION);\n    theApp.m_notify_icons[5] = (HICON)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_NOTIFY_ICON5), IMAGE_ICON, theApp.DPI(16), theApp.DPI(16), LR_DEFAULTCOLOR | LR_CREATEDIBSECTION);\n\n    //设置通知区域图标\n    m_ntIcon.cbSize = sizeof(NOTIFYICONDATA);   //该结构体变量的大小\n    if (theApp.m_cfg_data.m_notify_icon_selected < 0 || theApp.m_cfg_data.m_notify_icon_selected >= MAX_NOTIFY_ICON)\n        theApp.m_cfg_data.m_notify_icon_selected = 0;\n    m_ntIcon.hIcon = theApp.m_notify_icons[theApp.m_cfg_data.m_notify_icon_selected];       //设置图标\n    m_ntIcon.hWnd = this->m_hWnd;               //接收托盘图标通知消息的窗口句柄\n    CString atip;           //鼠标指向图标时显示的提示\n#ifdef _DEBUG\n    atip = CCommon::LoadText(IDS_TRAFFICMONITOR, _T(\" (Debug)\"));\n#else\n    atip = CCommon::LoadText(IDS_TRAFFICMONITOR);\n#endif\n    //wcscpy_s(m_ntIcon.szTip, 128, strTip);\n    CCommon::WStringCopy(m_ntIcon.szTip, 128, atip.GetString());\n    m_ntIcon.uCallbackMessage = MY_WM_NOTIFYICON;   //应用程序定义的消息ID号\n    m_ntIcon.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; //图标的属性：设置成员uCallbackMessage、hIcon、szTip有效\n    if (theApp.m_general_data.show_notify_icon)\n        ::Shell_NotifyIcon(NIM_ADD, &m_ntIcon); //在系统通知区域增加这个图标\n\n    //载入流量历史记录\n    LoadHistoryTraffic();\n\n    //设置1000毫秒触发的定时器\n    SetTimer(MAIN_TIMER, 1000, NULL);\n\n    SetTimer(MONITOR_TIMER, theApp.m_general_data.monitor_time_span, NULL);\n    AfxBeginThread(MonitorThreadCallback, (LPVOID)this);\n\n    //初始化窗口位置\n    SetItemPosition();\n    if (theApp.m_cfg_data.m_position_x != -1 && theApp.m_cfg_data.m_position_y != -1)\n        SetWindowPos(nullptr, theApp.m_cfg_data.m_position_x, theApp.m_cfg_data.m_position_y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);\n    CheckWindowPos();\n\n    //载入背景图片\n    LoadBackGroundImage();\n\n    //设置字体\n    SetTextFont();\n\n    //获取启动时的时间\n    GetLocalTime(&m_start_time);\n\n    //初始化鼠标提示\n    m_tool_tips.Create(this, TTS_ALWAYSTIP);\n    m_tool_tips.SetMaxTipWidth(600);\n    m_tool_tips.AddTool(this, _T(\"\"));\n\n    //设置获取CPU利用率的方式\n    m_cpu_usage_helper.SetUseCPUTimes(theApp.m_general_data.cpu_usage_acquire_method != GeneralSettingData::CA_PDH);\n\n    //如果程序启动时设置了隐藏主窗口，或窗口的位置在左上角，则先将其不透明度设为0\n    if (theApp.m_cfg_data.m_hide_main_window || (theApp.m_cfg_data.m_position_x == 0 && theApp.m_cfg_data.m_position_y == 0))\n        SetTransparency(0);\n\n    SetTimer(TASKBAR_TIMER, 100, NULL);\n\n    return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE\n}\n\n\n//当用户拖动最小化窗口时系统调用此函数取得光标\n//显示。\nHCURSOR CTrafficMonitorDlg::OnQueryDragIcon()\n{\n    return static_cast<HCURSOR>(m_hIcon);\n}\n\n//计算指定秒数的时间内Monitor定时器会触发的次数\nstatic int GetMonitorTimerCount(int second)\n{\n    int count = second * 1000 / theApp.m_general_data.monitor_time_span;\n    if (count <= 0) count = 1;\n    return count;\n}\n\n\nvoid CTrafficMonitorDlg::DoMonitorAcquisition()\n{\n    //获取网络连接速度\n    int rtn{};\n    auto getLfTable = [&]() {\n        __try\n        {\n            rtn = GetIfTable(m_pIfTable, &m_dwSize, FALSE);\n        }\n        __except (EXCEPTION_EXECUTE_HANDLER)\n        {\n            free(m_pIfTable);\n            m_dwSize = sizeof(MIB_IFTABLE);\n            m_pIfTable = (MIB_IFTABLE*)malloc(m_dwSize);\n            rtn = GetIfTable(m_pIfTable, &m_dwSize, FALSE);\n            if (rtn == ERROR_INSUFFICIENT_BUFFER)\t//如果函数返回值为ERROR_INSUFFICIENT_BUFFER，说明m_pIfTable的大小不够\n            {\n                free(m_pIfTable);\n                m_pIfTable = (MIB_IFTABLE*)malloc(m_dwSize);\t//用新的大小重新开辟一块内存\n            }\n            GetIfTable(m_pIfTable, &m_dwSize, FALSE);\n        }\n    };\n\n    getLfTable();\n\n    if (!theApp.m_cfg_data.m_select_all)        //获取当前选中连接的网速\n    {\n        auto table = GetConnectIfTable(m_connection_selected);\n        m_in_bytes = table.dwInOctets;\n        m_out_bytes = table.dwOutOctets;\n    }\n    else        //获取全部连接的网速\n    {\n        m_in_bytes = 0;\n        m_out_bytes = 0;\n        for (size_t i{}; i < m_connections.size(); i++)\n        {\n            auto table = GetConnectIfTable(i);\n            //if (i > 0 && m_pIfTable->table[m_connections[i].index].dwInOctets == m_pIfTable->table[m_connections[i - 1].index].dwInOctets\n            //  && m_pIfTable->table[m_connections[i].index].dwOutOctets == m_pIfTable->table[m_connections[i - 1].index].dwOutOctets)\n            //  continue;       //连接列表中可能会有相同的连接，统计所有连接的网速时，忽略掉已发送和已接收字节数完全相同的连接\n            m_in_bytes += table.dwInOctets;\n            m_out_bytes += table.dwOutOctets;\n        }\n    }\n\n    unsigned __int64 cur_in_speed{}, cur_out_speed{};       //本次监控时间间隔内的上传和下载速度\n\n    //如果发送和接收的字节数为0或上次发送和接收的字节数为0或当前连接已改变时，网速无效\n    if ((m_in_bytes == 0 && m_out_bytes == 0) || (m_last_in_bytes == 0 && m_last_out_bytes == 0) || m_connection_change_flag\n        || m_last_in_bytes > m_in_bytes || m_last_out_bytes > m_out_bytes)\n    {\n        cur_in_speed = 0;\n        cur_out_speed = 0;\n    }\n    else\n    {\n        cur_in_speed = m_in_bytes - m_last_in_bytes;\n        cur_out_speed = m_out_bytes - m_last_out_bytes;\n    }\n    ////如果大于1GB/s，说明可能产生了异常，网速无效\n    //if (cur_in_speed > 1073741824)\n    //  cur_in_speed = 0;\n    //if (cur_out_speed > 1073741824)\n    //  cur_out_speed = 0;\n\n    //计算两次获取网速的时间间隔\n    static ULONGLONG last_net_speed_time = 0;\n    ULONGLONG net_speed_time = CCommon::GetCurrentTimeSinceEpochMilliseconds();\n    int time_span = theApp.m_general_data.monitor_time_span;\n    if (last_net_speed_time != 0)\n        time_span = static_cast<int>(net_speed_time - last_net_speed_time);\n    last_net_speed_time = net_speed_time;\n\n    //将当前监控时间间隔的流量转换成每秒时间间隔内的流量\n    theApp.m_in_speed = static_cast<unsigned __int64>(cur_in_speed * 1000 / time_span);\n    theApp.m_out_speed = static_cast<unsigned __int64>(cur_out_speed * 1000 / time_span);\n\n    m_connection_change_flag = false;    //清除连接发生变化的标志\n\n    m_last_in_bytes = m_in_bytes;\n    m_last_out_bytes = m_out_bytes;\n\n    //处于自动选择状态时，如果连续30秒没有网速，则可能自动选择的网络不对，此时执行一次自动选择\n    if (theApp.m_cfg_data.m_auto_select)\n    {\n        if (cur_in_speed == 0 && cur_out_speed == 0)\n            m_zero_speed_cnt++;\n        else\n            m_zero_speed_cnt = 0;\n        if (m_zero_speed_cnt >= GetMonitorTimerCount(30))\n        {\n            AutoSelect();\n            m_zero_speed_cnt = 0;\n        }\n    }\n\n    //检测当前日期是否改变，如果已改变，就向历史流量列表插入一个新的日期\n    SYSTEMTIME current_time;\n    GetLocalTime(&current_time);\n    if (m_history_traffic.GetTraffics()[0].day != current_time.wDay)\n    {\n        HistoryTraffic traffic;\n        traffic.year = current_time.wYear;\n        traffic.month = current_time.wMonth;\n        traffic.day = current_time.wDay;\n        traffic.mixed = false;\n        m_history_traffic.GetTraffics().push_front(traffic);\n        theApp.m_today_up_traffic = 0;\n        theApp.m_today_down_traffic = 0;\n    }\n\n    //统计今天已使用的流量\n    theApp.m_today_up_traffic += cur_out_speed;\n    theApp.m_today_down_traffic += cur_in_speed;\n    m_history_traffic.GetTraffics()[0].up_kBytes = theApp.m_today_up_traffic / 1024u;\n    m_history_traffic.GetTraffics()[0].down_kBytes = theApp.m_today_down_traffic / 1024u;\n    //每隔30秒保存一次流量历史记录\n    if (m_monitor_time_cnt % GetMonitorTimerCount(30) == GetMonitorTimerCount(30) - 1)\n    {\n        static unsigned __int64 last_today_kbytes;\n        if (m_history_traffic.GetTraffics()[0].kBytes() - last_today_kbytes >= 100u) //只有当流量变化超过100KB时才保存历史流量记录，防止磁盘写入过于频繁\n        {\n            SaveHistoryTraffic();\n            last_today_kbytes = m_history_traffic.GetTraffics()[0].kBytes();\n        }\n    }\n\n    if (rtn == ERROR_INSUFFICIENT_BUFFER)\n    {\n        IniConnection();\n        CString info = CCommon::LoadText(IDS_INSUFFICIENT_BUFFER);\n        info.Replace(_T(\"<%cnt%>\"), CCommon::IntToString(m_restart_cnt));\n        CCommon::WriteLog(info, theApp.m_log_path.c_str());\n    }\n\n    if (m_monitor_time_cnt % GetMonitorTimerCount(3) == GetMonitorTimerCount(3) - 1)\n    {\n        //重新获取当前连接数量\n        static DWORD last_interface_num = -1;\n        DWORD interface_num;\n        GetNumberOfInterfaces(&interface_num);\n        if (last_interface_num != -1 && interface_num != last_interface_num)    //如果连接数发生变化，则重新初始化连接\n        {\n            if (theApp.m_debug_log)\n            {\n                CString info = CCommon::LoadText(IDS_CONNECTION_NUM_CHANGED);\n                info.Replace(_T(\"<%before%>\"), CCommon::IntToString(last_interface_num));\n                info.Replace(_T(\"<%after%>\"), CCommon::IntToString(interface_num));\n                info.Replace(_T(\"<%cnt%>\"), CCommon::IntToString(m_restart_cnt + 1));\n                CCommon::WriteLog(info, theApp.m_log_path.c_str());\n            }\n            IniConnection();\n            last_interface_num = interface_num;\n        }\n\n        string descr;\n        descr = (const char*)GetConnectIfTable(m_connection_selected).bDescr;\n        if (descr != theApp.m_cfg_data.m_connection_name)\n        {\n            //写入额外的调试信息\n            if (theApp.m_debug_log)\n            {\n                CString log_str;\n                log_str = _T(\"连接名称不匹配：\\r\\n\");\n                log_str += _T(\"IfTable description: \");\n                log_str += descr.c_str();\n                log_str += _T(\"\\r\\nm_connection_name: \");\n                log_str += theApp.m_cfg_data.m_connection_name.c_str();\n                CCommon::WriteLog(log_str, (theApp.m_config_dir + L\".\\\\connections.log\").c_str());\n            }\n\n            IniConnection();\n            CString info = CCommon::LoadText(IDS_CONNECTION_NOT_MATCH);\n            info.Replace(_T(\"<%cnt%>\"), CCommon::IntToString(m_restart_cnt));\n            CCommon::WriteLog(info, theApp.m_log_path.c_str());\n        }\n    }\n\n    bool lite_version = false;\n#ifdef WITHOUT_TEMPERATURE\n    lite_version = true;\n#endif\n\n    bool cpu_usage_acquired = false;\n    bool cpu_freq_acquired = false;\n    bool gpu_usage_acquired = false;\n    m_get_disk_usage_by_pdh = false;\n\n    theApp.m_cpu_temperature = -1;\n    theApp.m_gpu_temperature = -1;\n    theApp.m_hdd_temperature = -1;\n    theApp.m_main_board_temperature = -1;\n    theApp.m_gpu_usage = -1;\n    theApp.m_hdd_usage = -1;\n\n    //获取CPU使用率\n    if (lite_version || theApp.m_general_data.cpu_usage_acquire_method != GeneralSettingData::CA_HARDWARE_MONITOR || !theApp.m_general_data.IsHardwareEnable(HI_CPU))\n    {\n        theApp.m_cpu_usage = m_cpu_usage_helper.GetCpuUsage();\n        cpu_usage_acquired = true;\n    }\n\n    //获取CPU频率\n    //if (lite_version || is_arm64ec || !theApp.m_general_data.IsHardwareEnable(HI_CPU))\n    //{\n    if (m_cpu_freq_helper.GetCpuFreq(theApp.m_cpu_freq))\n        cpu_freq_acquired = true;\n    //}\n\n    //获取GPU利用率\n    if (lite_version /*|| is_arm64ec*/ || !theApp.m_general_data.IsHardwareEnable(HI_GPU))\n    {\n        if (m_gpu_usage_helper.GetGpuUsage(theApp.m_gpu_usage))\n            gpu_usage_acquired = true;\n    }\n\n    //获取硬盘利用率\n    if (lite_version /*|| is_arm64ec*/ || !theApp.m_general_data.IsHardwareEnable(HI_HDD))\n    {\n        int disk_index = m_disk_usage_helper.FindDiskIndex(theApp.m_general_data.hard_disk_name);\n        //没有找到要监控的硬盘时默认使用总体利用率\n        if (disk_index < 0)\n        {\n            disk_index = m_disk_usage_helper.FindDiskIndex(L\"_Total\");\n            if (disk_index >= 0)\n            {\n                theApp.m_general_data.hard_disk_name = L\"_Total\";\n            }\n            //仍然没有找到使用第1块硬盘\n            else\n            {\n                const auto& disk_names = m_disk_usage_helper.GetDiskNames();\n                if (!disk_names.empty())\n                {\n                    disk_index = 0;\n                    theApp.m_general_data.hard_disk_name = disk_names.front();\n                }\n            }\n        }\n        if (m_disk_usage_helper.GetDiskUsage(disk_index, theApp.m_hdd_usage))\n            m_get_disk_usage_by_pdh = true;\n    }\n\n    //获取内存利用率\n    MEMORYSTATUSEX statex;\n    statex.dwLength = sizeof(statex);\n    GlobalMemoryStatusEx(&statex);\n    theApp.m_memory_usage = statex.dwMemoryLoad;\n    theApp.m_used_memory = static_cast<int>((statex.ullTotalPhys - statex.ullAvailPhys) / 1024);\n    theApp.m_total_memory = static_cast<int>(statex.ullTotalPhys / 1024);\n\n#ifndef WITHOUT_TEMPERATURE\n    //获取温度\n    if (IsTemperatureNeeded() && theApp.m_pMonitor != nullptr)\n    {\n        CSingleLock sync(&theApp.m_minitor_lib_critical, TRUE);\n        CString error_info = CCommon::LoadText(IDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR);\n\n        auto getHardwareInfo = [&]() {\n            __try\n            {\n                theApp.m_pMonitor->GetHardwareInfo();\n            }\n            __except (EXCEPTION_EXECUTE_HANDLER)\n            {\n                AfxMessageBox(error_info, MB_ICONERROR | MB_OK);\n            }\n        };\n\n        getHardwareInfo();\n        auto monitor_error_message{ OpenHardwareMonitorApi::GetErrorMessage() };\n        if (!monitor_error_message.empty())\n        {\n            AfxMessageBox(monitor_error_message.c_str(), MB_ICONERROR | MB_OK);\n        }\n        //theApp.m_cpu_temperature = theApp.m_pMonitor->CpuTemperature();\n        theApp.m_gpu_temperature = theApp.m_pMonitor->GpuTemperature();\n        //theApp.m_hdd_temperature = theApp.m_pMonitor->HDDTemperature();\n        theApp.m_main_board_temperature = theApp.m_pMonitor->MainboardTemperature();\n        if (!gpu_usage_acquired)\n            theApp.m_gpu_usage = theApp.m_pMonitor->GpuUsage();\n        if (!cpu_freq_acquired)\n            theApp.m_cpu_freq = theApp.m_pMonitor->CpuFreq();\n        if (!cpu_usage_acquired)\n            theApp.m_cpu_usage = theApp.m_pMonitor->CpuUsage();\n        //获取CPU温度\n        if (!theApp.m_pMonitor->AllCpuTemperature().empty())\n        {\n            if (theApp.m_general_data.cpu_core_name == CCommon::LoadText(IDS_AVREAGE_TEMPERATURE).GetString())  //如果选择了平均温度\n            {\n                theApp.m_cpu_temperature = theApp.m_pMonitor->CpuTemperature();\n            }\n            else\n            {\n                auto iter = theApp.m_pMonitor->AllCpuTemperature().find(theApp.m_general_data.cpu_core_name);\n                if (iter == theApp.m_pMonitor->AllCpuTemperature().end())\n                {\n                    iter = theApp.m_pMonitor->AllCpuTemperature().begin();\n                    theApp.m_general_data.cpu_core_name = iter->first;\n                }\n                theApp.m_cpu_temperature = iter->second;\n            }\n        }\n        else\n        {\n            theApp.m_cpu_temperature = -1;\n        }\n        //获取硬盘温度\n        if (!theApp.m_pMonitor->AllHDDTemperature().empty())\n        {\n            auto iter = theApp.m_pMonitor->AllHDDTemperature().find(theApp.m_general_data.hard_disk_name);\n            if (iter == theApp.m_pMonitor->AllHDDTemperature().end())\n            {\n                iter = theApp.m_pMonitor->AllHDDTemperature().begin();\n                theApp.m_general_data.hard_disk_name = iter->first;\n            }\n            theApp.m_hdd_temperature = iter->second;\n        }\n        else\n        {\n            theApp.m_hdd_temperature = -1;\n        }\n        //获取硬盘利用率\n        if (!m_get_disk_usage_by_pdh)\n        {\n            if (!theApp.m_pMonitor->AllHDDUsage().empty())\n            {\n                auto iter = theApp.m_pMonitor->AllHDDUsage().find(theApp.m_general_data.hard_disk_name);\n                if (iter == theApp.m_pMonitor->AllHDDUsage().end())\n                {\n                    iter = theApp.m_pMonitor->AllHDDUsage().begin();\n                    theApp.m_general_data.hard_disk_name = iter->first;\n                }\n                theApp.m_hdd_usage = iter->second;\n            }\n            else\n            {\n                theApp.m_hdd_usage = -1;\n            }\n        }\n    }\n#endif\n\n    //通知插件获取数据，以及向插件传递监控数据\n    for (const auto& plugin_info : theApp.m_plugins.GetPlugins())\n    {\n        if (plugin_info.plugin != nullptr)\n        {\n            plugin_info.plugin->DataRequired();\n            ITMPlugin::MonitorInfo monitor_info;\n            monitor_info.up_speed = theApp.m_out_speed;\n            monitor_info.down_speed = theApp.m_in_speed;\n            monitor_info.cpu_usage = theApp.m_cpu_usage;\n            monitor_info.memory_usage = theApp.m_memory_usage;\n            monitor_info.gpu_usage = theApp.m_gpu_usage;\n            monitor_info.hdd_usage = theApp.m_hdd_usage;\n            monitor_info.cpu_temperature = theApp.m_cpu_temperature;\n            monitor_info.gpu_temperature = theApp.m_gpu_temperature;\n            monitor_info.hdd_temperature = theApp.m_hdd_temperature;\n            monitor_info.cpu_freq = theApp.m_cpu_freq;\n            monitor_info.main_board_temperature = theApp.m_main_board_temperature;\n            plugin_info.plugin->OnMonitorInfo(monitor_info);\n        }\n    }\n\n    m_monitor_time_cnt++;\n\n    //发送监控信息更新消息\n    SendMessage(WM_MONITOR_INFO_UPDATED);\n}\n\nUINT CTrafficMonitorDlg::MonitorThreadCallback(LPVOID dwUser)\n{\n    CTrafficMonitorDlg* pThis = (CTrafficMonitorDlg*)dwUser;\n    while (true)\n    {\n        //获取一次监控数据\n        if (pThis->m_monitor_data_required)\n        {\n            pThis->DoMonitorAcquisition();\n            //获取到监控数据后重置flag\n            pThis->m_monitor_data_required = false;\n        }\n        else\n        {\n            Sleep(10);\n        }\n\n        // 检查退出标志\n        if (pThis->m_is_thread_exit)\n        {\n            // 触发事件，通知主线程工作线程已退出\n            pThis->m_threadExitEvent.SetEvent();\n            return 0;\n        }\n    }\n\n    return 0;\n}\n\n\nvoid CTrafficMonitorDlg::ExitMonitorThread()\n{\n    // 通知线程退出\n    m_is_thread_exit = true;\n\n    // 等待线程退出\n    ::WaitForSingleObject(m_threadExitEvent.m_hObject, 1000);\n}\n\n\nvoid CTrafficMonitorDlg::OnTimer(UINT_PTR nIDEvent)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    if (nIDEvent == MONITOR_TIMER)\n    {\n        //通知线程获取监控数据\n        m_monitor_data_required = true;\n    }\n\n    if (nIDEvent == MAIN_TIMER)\n    {\n        m_timer_cnt++;\n        if (m_first_start)      //这个if语句在程序启动后1秒执行\n        {\n            //将设置窗口置顶的处理放在这里是用于解决\n            //放在初始化函数中可能会出现设置置顶无效的问题\n            SetAlwaysOnTop();       //设置窗口置顶\n            SetMousePenetrate();    //设置鼠标穿透\n            if (theApp.m_cfg_data.m_hide_main_window)   //设置隐藏主窗口\n                ShowWindow(SW_HIDE);\n\n            //打开任务栏窗口\n            if (theApp.m_cfg_data.m_show_task_bar_wnd && m_tBarDlg == nullptr)\n                OpenTaskBarWnd();\n\n            //如果窗口的位置为(0, 0)，则在初始化时MoveWindow函数无效，此时再移动一次窗口\n            if (theApp.m_cfg_data.m_position_x == 0 && theApp.m_cfg_data.m_position_y == 0)\n            {\n                SetWindowPos(nullptr, theApp.m_cfg_data.m_position_x, theApp.m_cfg_data.m_position_y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);\n            }\n            SetTransparency();              //重新设置窗口不透明度\n\n            //检查主窗口所在位置的DPI是否变化\n            UINT dpi_x, dpi_y;\n            CRect rect;\n            GetWindowRect(rect);\n            bool rtn = theApp.DPIFromRect(rect, & dpi_x, & dpi_y);\n            int dpi = static_cast<int>(dpi_x);\n            if (rtn && dpi != theApp.GetDpi())\n            {\n                theApp.SetDPI(dpi_x);\n                LoadSkinLayout();   //根据当前选择的皮肤获取布局数据\n                SetItemPosition();  //初始化窗口位置\n                LoadBackGroundImage();\n                SetTextFont();      //重新加载字体\n                Invalidate(FALSE);  //重绘界面\n            }\n\n            m_first_start = false;\n        }\n\n        if (theApp.m_main_wnd_data.m_always_on_top && !theApp.m_cfg_data.m_hide_main_window)\n        {\n            //每隔1秒钟就判断一下前台窗口是否全屏\n            CRect rect;\n            GetWindowRect(rect);\n            HMONITOR h_current_monitor = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);\n            m_is_foreground_fullscreen = CCommon::IsForegroundFullscreen(h_current_monitor);\n            if (theApp.m_main_wnd_data.hide_main_wnd_when_fullscreen)       //当设置了全屏时隐藏悬浮窗时\n            {\n                if (m_is_foreground_fullscreen || theApp.m_cfg_data.m_hide_main_window)\n                    ShowWindow(SW_HIDE);\n                else\n                    ShowWindow(SW_RESTORE);\n            }\n            else            //如果没有设置全屏时隐藏悬浮窗，则如果有程序进入全屏状态，则设置一次窗口置顶\n            {\n                static bool last_foreground_fullscreen;\n                if (!last_foreground_fullscreen && m_is_foreground_fullscreen)\n                {\n                    SetAlwaysOnTop();\n                }\n                last_foreground_fullscreen = m_is_foreground_fullscreen;\n            }\n        }\n\n        if (!m_menu_popuped)\n        {\n            //程序启动后若干秒的时候根据设置重新执行“总是置顶”、“鼠标穿透”和“隐藏主窗口”的操作，防止设置没有生效\n            if (m_timer_cnt == 5 || m_timer_cnt == 9)\n            {\n                if (!theApp.m_cfg_data.m_hide_main_window)\n                {\n                    SetAlwaysOnTop();\n                    SetMousePenetrate();\n                }\n                else\n                {\n                    ShowWindow(SW_HIDE);\n                }\n            }\n\n            if (m_timer_cnt % 300 == 299 && CBaseDialog::IsAllDialogClosed() && !theApp.m_cfg_data.m_hide_main_window && theApp.m_main_wnd_data.m_always_on_top)\n            {\n                SetAlwaysOnTop();       //每5分钟执行一次设置窗口置顶\n            }\n        }\n        else\n        {\n            m_tool_tips.Pop();          //显示了右键菜单时，不显示鼠标提示\n        }\n\n        if (m_timer_cnt % 30 == 26)     //每隔30秒钟检测一次窗口位置，当窗口位置发生变化时保存设置\n        {\n            static int last_pos_x{ -1 }, last_pos_y{ -1 };\n            if (last_pos_x != theApp.m_cfg_data.m_position_x || last_pos_y != theApp.m_cfg_data.m_position_y)\n            {\n                theApp.SaveConfig();\n                last_pos_x = theApp.m_cfg_data.m_position_x;\n                last_pos_y = theApp.m_cfg_data.m_position_y;\n            }\n        }\n\n        if (m_timer_cnt % 2 == 1)       //每隔2秒钟获取一次屏幕区域\n        {\n            GetScreenSize();\n            CheckWindowPos();\n        }\n\n        //只有主窗口和任务栏窗口至少有一个显示时才执行下面的处理\n        if (!theApp.m_cfg_data.m_hide_main_window || theApp.m_cfg_data.m_show_task_bar_wnd)\n        {\n            //每隔10秒钟检测一次是否可以嵌入任务栏\n            if (!theApp.m_win_version.IsWine() && IsTaskbarWndValid() && m_timer_cnt % 10 == 1)\n            {\n                if (m_tBarDlg->GetCannotInsertToTaskBar() && m_insert_to_taskbar_cnt < MAX_INSERT_TO_TASKBAR_CNT)\n                {\n                    CloseTaskBarWnd();\n                    OpenTaskBarWnd();\n                    m_insert_to_taskbar_cnt++;\n                    if (m_tBarDlg->GetCannotInsertToTaskBar() && m_insert_to_taskbar_cnt >= WARN_INSERT_TO_TASKBAR_CNT)\n                    {\n                        //写入错误日志\n                        CString info = CCommon::LoadText(IDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG);\n                        info.Replace(_T(\"<%cnt%>\"), CCommon::IntToString(m_insert_to_taskbar_cnt));\n                        info.Replace(_T(\"<%error_code%>\"), CCommon::IntToString(m_tBarDlg->GetErrorCode()));\n                        CCommon::WriteLog(info, theApp.m_log_path.c_str());\n                        if (m_cannot_insert_to_task_bar_warning)      //确保提示信息只弹出一次\n                        {\n                            //弹出错误信息\n                            m_cannot_insert_to_task_bar_warning = false;\n                            MessageBox(CCommon::LoadText(IDS_CONNOT_INSERT_TO_TASKBAR, CCommon::IntToString(m_tBarDlg->GetErrorCode())), NULL, MB_ICONWARNING);\n                        }\n                    }\n                }\n                if (!m_tBarDlg->GetCannotInsertToTaskBar())\n                {\n                    m_insert_to_taskbar_cnt = 0;\n                }\n            }\n        }\n\n        //检查是否需要弹出鼠标提示\n        //setting_data: 消息提示的设置数据\n        //value: 当前的值\n        //last_value: 传递一个static或可以在此lambda表达式调用结束后继续存在的变量，用于保存上一次的值\n        //notify_time: 传递一个static或可以在此lambda表达式调用结束后继续存在的变量，用于记录上次弹出提示的时间（定时器触发次数）\n        //tip_str: 要提示的消息\n        auto checkNotifyTip = [&](GeneralSettingData::NotifyTipSettings setting_data, int value, int& last_value, int& notify_time, LPCTSTR tip_str)\n        {\n            if (setting_data.enable)\n            {\n                if (last_value < setting_data.tip_value && value >= setting_data.tip_value && (m_timer_cnt - notify_time > static_cast<unsigned int>(theApp.m_notify_interval)))\n                {\n                    ShowNotifyTip(CCommon::LoadText(_T(\"TrafficMonitor \"), IDS_NOTIFY), tip_str);\n                    notify_time = m_timer_cnt;\n                }\n                last_value = value;\n            }\n        };\n\n        //检查是否要弹出内存使用率超出提示\n        CString info;\n        info.Format(CCommon::LoadText(IDS_MEMORY_UDAGE_EXCEED, _T(\" %d%%!\")), theApp.m_memory_usage);\n        static int last_memory_usage;\n        static int memory_usage_notify_time{ -theApp.m_notify_interval };       //记录上次弹出提示时的时间\n        checkNotifyTip(theApp.m_general_data.memory_usage_tip, theApp.m_memory_usage, last_memory_usage, memory_usage_notify_time, info.GetString());\n\n        //检查是否要弹出CPU温度使用率超出提示\n        info.Format(CCommon::LoadText(IDS_CPU_TEMPERATURE_EXCEED, _T(\" %d°C!\")), static_cast<int>(theApp.m_cpu_temperature));\n        static int last_cpu_temp;\n        static int cpu_temp_notify_time{ -theApp.m_notify_interval };       //记录上次弹出提示时的时间\n        checkNotifyTip(theApp.m_general_data.cpu_temp_tip, theApp.m_cpu_temperature, last_cpu_temp, cpu_temp_notify_time, info.GetString());\n\n        //检查是否要弹出显卡温度使用率超出提示\n        info.Format(CCommon::LoadText(IDS_GPU_TEMPERATURE_EXCEED, _T(\" %d°C!\")), static_cast<int>(theApp.m_gpu_temperature));\n        static int last_gpu_temp;\n        static int gpu_temp_notify_time{ -theApp.m_notify_interval };       //记录上次弹出提示时的时间\n        checkNotifyTip(theApp.m_general_data.gpu_temp_tip, theApp.m_gpu_temperature, last_gpu_temp, gpu_temp_notify_time, info.GetString());\n\n        //检查是否要弹出硬盘温度使用率超出提示\n        info.Format(CCommon::LoadText(IDS_HDD_TEMPERATURE_EXCEED, _T(\" %d°C!\")), static_cast<int>(theApp.m_hdd_temperature));\n        static int last_hdd_temp;\n        static int hdd_temp_notify_time{ -theApp.m_notify_interval };       //记录上次弹出提示时的时间\n        checkNotifyTip(theApp.m_general_data.hdd_temp_tip, theApp.m_hdd_temperature, last_hdd_temp, hdd_temp_notify_time, info.GetString());\n\n        //检查是否要弹出主板温度使用率超出提示\n        info.Format(CCommon::LoadText(IDS_MBD_TEMPERATURE_EXCEED, _T(\" %d°C!\")), static_cast<int>(theApp.m_main_board_temperature));\n        static int last_main_board_temp;\n        static int main_board_temp_notify_time{ -theApp.m_notify_interval };        //记录上次弹出提示时的时间\n        checkNotifyTip(theApp.m_general_data.mainboard_temp_tip, theApp.m_main_board_temperature, last_main_board_temp, main_board_temp_notify_time, info.GetString());\n\n\n        //检查是否要弹出流量使用超出提示\n        if (theApp.m_general_data.traffic_tip_enable)\n        {\n            static __int64 last_today_traffic;\n            __int64 traffic_tip_value;\n            if (theApp.m_general_data.traffic_tip_unit == 0)\n                traffic_tip_value = static_cast<__int64>(theApp.m_general_data.traffic_tip_value) * 1024 * 1024;\n            else\n                traffic_tip_value = static_cast<__int64>(theApp.m_general_data.traffic_tip_value) * 1024 * 1024 * 1024;\n\n            __int64 today_traffic = theApp.m_today_up_traffic + theApp.m_today_down_traffic;\n            if (last_today_traffic < traffic_tip_value && today_traffic >= traffic_tip_value)\n            {\n                CString info = CCommon::LoadText(IDS_TODAY_TRAFFIC_EXCEED, CCommon::DataSizeToString(today_traffic));\n                ShowNotifyTip(CCommon::LoadText(_T(\"TrafficMonitor \"), IDS_NOTIFY), info.GetString());\n            }\n            last_today_traffic = today_traffic;\n        }\n\n        CWindowsSettingHelper::CheckWindows10LightTheme();        //每隔1秒钟检查一下当前系统是否为白色主题\n\n        //根据当前Win10颜色模式自动切换任务栏颜色\n        bool light_mode = CWindowsSettingHelper::IsWindows10LightTheme();\n        if (theApp.m_last_light_mode != light_mode)\n        {\n            theApp.m_last_light_mode = light_mode;\n            bool restart_taskbar_dlg{ false };\n            if (theApp.m_taskbar_data.auto_adapt_light_theme)\n            {\n                int style_index = CWindowsSettingHelper::IsWindows10LightTheme() ? theApp.m_taskbar_data.light_default_style : theApp.m_taskbar_data.dark_default_style;\n                theApp.m_taskbar_default_style.ApplyDefaultStyle(style_index, theApp.m_taskbar_data);\n                theApp.SaveConfig();\n                restart_taskbar_dlg = true;\n            }\n            bool is_taskbar_transparent{ theApp.m_taskbar_data.IsTaskbarTransparent()};\n            if (!is_taskbar_transparent)\n            {\n                theApp.m_taskbar_data.SetTaskabrTransparent(false);\n                restart_taskbar_dlg = true;\n            }\n            if (restart_taskbar_dlg && IsTaskbarWndValid())\n            {\n                m_tBarDlg->ApplyWindowTransparentColor();\n                //CloseTaskBarWnd();\n                //OpenTaskBarWnd();\n\n                //写入调试日志\n                if (theApp.m_debug_log)\n                {\n                    CString log_str;\n                    log_str += _T(\"检测到 Windows10 深浅色变化。\\n\");\n                    log_str += _T(\"IsWindows10LightTheme: \");\n                    log_str += std::to_wstring(light_mode).c_str();\n                    log_str += _T(\"\\n\");\n                    log_str += _T(\"auto_adapt_light_theme: \");\n                    log_str += std::to_wstring(theApp.m_taskbar_data.auto_adapt_light_theme).c_str();\n                    log_str += _T(\"\\n\");\n                    log_str += _T(\"is_taskbar_transparent: \");\n                    log_str += std::to_wstring(is_taskbar_transparent).c_str();\n                    log_str += _T(\"\\n\");\n                    log_str += _T(\"taskbar_back_color: \");\n                    log_str += std::to_wstring(theApp.m_taskbar_data.back_color).c_str();\n                    log_str += _T(\"\\n\");\n                    log_str += _T(\"taskbar_transparent_color: \");\n                    log_str += std::to_wstring(theApp.m_taskbar_data.transparent_color).c_str();\n                    log_str += _T(\"\\n\");\n                    log_str += _T(\"taskbar_text_colors: \");\n                    for (const auto& item : theApp.m_taskbar_data.text_colors)\n                    {\n                        log_str += std::to_wstring(item.second.label).c_str();\n                        log_str += _T('|');\n                        log_str += std::to_wstring(item.second.value).c_str();\n                        log_str += _T(\", \");\n                    }\n                    log_str += _T(\"\\n\");\n                    CCommon::WriteLog(log_str, (theApp.m_config_dir + L\".\\\\debug.log\").c_str());\n                }\n            }\n\n            //根据当前Win10颜色模式自动切换通知区图标\n            if (theApp.m_cfg_data.m_notify_icon_auto_adapt)\n            {\n                int notify_icon_selected = theApp.m_cfg_data.m_notify_icon_selected;\n                theApp.AutoSelectNotifyIcon();\n                if (notify_icon_selected != theApp.m_cfg_data.m_notify_icon_selected)\n                {\n                    m_ntIcon.hIcon = theApp.m_notify_icons[theApp.m_cfg_data.m_notify_icon_selected];\n                    if (theApp.m_general_data.show_notify_icon)\n                    {\n                        DeleteNotifyIcon();\n                        AddNotifyIcon();\n                    }\n                }\n            }\n\n            //根据深色/浅色模式自动切换皮肤\n            if (theApp.m_win_version.IsWindows10OrLater() && theApp.m_cfg_data.skin_auto_adapt)\n            {\n                int skin_index = CSkinManager::Instance().FindSkinIndex(light_mode ? theApp.m_cfg_data.skin_name_light_mode : theApp.m_cfg_data.skin_name_dark_mode);\n                ApplySkin(skin_index);\n            }\n        }\n\n        //根据任务栏颜色自动设置任务栏窗口背景色\n        if (theApp.m_taskbar_data.auto_set_background_color && theApp.m_win_version.IsWindows8OrLater()\n            && IsTaskbarWndValid() && theApp.m_taskbar_data.transparent_color != 0\n            && !m_is_foreground_fullscreen && theApp.m_taskbar_data.disable_d2d)\n        {\n            CRect rect;\n            ::GetWindowRect(m_tBarDlg->GetSafeHwnd(), rect);\n            int pointx{ rect.left - 1 };\n            if (theApp.m_taskbar_data.tbar_wnd_on_left && m_tBarDlg->IsTasksbarOnTopOrBottom())\n                pointx = rect.right + 1;\n            int pointy = rect.bottom;\n            if (pointx < 0) pointx = 0;\n            if (pointx >= m_screen_size.cx) pointx = m_screen_size.cx - 1;\n            if (pointy < 0) pointy = 0;\n            if (pointy >= m_screen_size.cy) pointy = m_screen_size.cy - 1;\n            COLORREF color = ::GetPixel(m_desktop_dc, pointx, pointy);        //取任务栏窗口左侧1像素处的颜色作为背景色\n            if (!CCommon::IsColorSimilar(color, theApp.m_taskbar_data.back_color) && (/*CWindowsSettingHelper::IsWindows10LightTheme() ||*/ color != 0))\n            {\n                bool is_taskbar_transparent{ theApp.m_taskbar_data.IsTaskbarTransparent()};\n                theApp.m_taskbar_data.back_color = color;\n                theApp.m_taskbar_data.SetTaskabrTransparent(is_taskbar_transparent);\n                if (is_taskbar_transparent)\n                    m_tBarDlg->ApplyWindowTransparentColor();\n            }\n        }\n\n        //当检测到背景色和文字颜色都为黑色写入错误日志\n        static bool erro_log_write{ false };\n        if (theApp.m_taskbar_data.back_color == 0 && !theApp.m_taskbar_data.text_colors.empty() && theApp.m_taskbar_data.text_colors.begin()->second.label == 0)\n        {\n            if (!erro_log_write)\n            {\n                CString log_str;\n                log_str.Format(_T(\"检查到背景色和文字颜色都为黑色。IsWindows10LightTheme: %d, 系统启动时间：%d/%.2d/%.2d %.2d:%.2d:%.2d\"),\n                    light_mode, m_start_time.wYear, m_start_time.wMonth, m_start_time.wDay, m_start_time.wHour, m_start_time.wMinute, m_start_time.wSecond);\n                CCommon::WriteLog(log_str, theApp.m_log_path.c_str());\n                erro_log_write = true;\n            }\n        }\n        else\n        {\n            erro_log_write = false;\n        }\n\n        UpdateNotifyIconTip();\n\n\n    }\n\n    if (nIDEvent == DELAY_TIMER)\n    {\n        AutoSelect();\n        KillTimer(DELAY_TIMER);\n    }\n\n    if (nIDEvent == TASKBAR_TIMER)\n    {\n        ++m_taskbar_timer_cnt;\n        if (m_taskbar_timer_cnt % 5 == 0 && theApp.m_cfg_data.m_show_task_bar_wnd && theApp.m_taskbar_data.show_taskbar_wnd_in_secondary_display)\n        {\n            static int last_taskbar_num = 0;\n            int taskbar_num = CTaskbarHelper::GetSecondaryTaskbarNum();\n            //如果副显示器的任务栏数量发生变化，则重启任务栏窗口\n            if (last_taskbar_num != taskbar_num)\n            {\n                last_taskbar_num = taskbar_num;\n                //延迟一段时间后重启任务栏窗口\n                KillTimer(RESTART_TASKBAR_TIMER);\n                SetTimer(RESTART_TASKBAR_TIMER, 500, [](HWND, UINT, UINT_PTR, DWORD) {\n                    theApp.m_pMainWnd->SendMessage(WM_REOPEN_TASKBAR_WND);\n                    ::KillTimer(theApp.m_pMainWnd->GetSafeHwnd(), RESTART_TASKBAR_TIMER);\n                });\n            }\n        }\n\n        if (IsTaskbarWndValid())\n        {\n            //启动时就隐藏主窗体的情况下，无法收到dpichange消息，故需要手动检查\n            //每次100ms*10执行一次屏幕DPI检查，并且尽可能少的检查操作系统版本\n            if (m_taskbar_timer_cnt % 10 == 0 && theApp.m_win_version.IsWindows8Point1OrLater())\n            {\n                CTaskBarDlg::CheckWindowMonitorDPIAndHandle(*m_tBarDlg, [p_TaskBarDlg = m_tBarDlg](UINT new_dpi_x, UINT new_dpi_y)\n                                                            {\n                                                                // auto s_dpi = std::to_string(new_dpi_x);\n                                                                // s_dpi += '\\n';\n                                                                // TRACE(s_dpi.c_str());\n                                                                //考虑到任务栏窗口可能和主窗口不在同一个屏幕上，dpi可能不同\n                                                                //设置DPI并刷新窗口\n                                                                p_TaskBarDlg->SetDPI(new_dpi_x);\n                                                                p_TaskBarDlg->SetTextFont();\n                                                                p_TaskBarDlg->CalculateWindowSize(); });\n            }\n\n            m_tBarDlg->AdjustWindowPos();\n            m_tBarDlg->Invalidate(FALSE);\n        }\n    }\n\n    if (nIDEvent == DELETE_NOTIFY_ICON_TIMER)\n    {\n        DeleteNotifyIcon();\n        KillTimer(DELETE_NOTIFY_ICON_TIMER);\n    }\n\n    CDialog::OnTimer(nIDEvent);\n}\n\n\nvoid CTrafficMonitorDlg::OnRButtonUp(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    CheckClickedItem(point);\n    bool is_plugin_item_clicked = (m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr);\n    ITMPlugin* plugin{};\n    if (is_plugin_item_clicked)\n    {\n        plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n        {\n            if (m_clicked_item.PluginItem()->OnMouseEvent(IPluginItem::MT_RCLICKED, point.x, point.y, (void*)GetSafeHwnd(), 0) != 0)\n                return;\n        }\n    }\n    //设置点击鼠标右键弹出菜单\n    CMenu* pContextMenu = (is_plugin_item_clicked ? theApp.m_main_menu_plugin.GetSubMenu(0) : theApp.m_main_menu.GetSubMenu(0));\n    CPoint point1;  //定义一个用于确定光标位置的位置\n    GetCursorPos(&point1);  //获取当前光标的位置，以便使得菜单可以跟随光标\n    //设置默认菜单项\n    switch (theApp.m_main_wnd_data.double_click_action)\n    {\n    case DoubleClickAction::CONNECTION_INFO:\n        pContextMenu->SetDefaultItem(ID_NETWORK_INFO);\n        break;\n        //case DoubleClickAction::HISTORY_TRAFFIC:\n        //  pContextMenu->SetDefaultItem(ID_TRAFFIC_HISTORY);\n        //  break;\n    case DoubleClickAction::SHOW_MORE_INFO:\n        pContextMenu->SetDefaultItem(ID_SHOW_CPU_MEMORY);\n        break;\n    case DoubleClickAction::OPTIONS:\n        pContextMenu->SetDefaultItem(ID_OPTIONS);\n        break;\n        //case DoubleClickAction::CHANGE_SKIN:\n        //  pContextMenu->SetDefaultItem(ID_CHANGE_SKIN);\n        //  break;\n    default:\n        pContextMenu->SetDefaultItem(-1);\n        break;\n    }\n\n    if (plugin != nullptr)\n    {\n        //将右键菜单中插件菜单的显示文本改为插件名\n        pContextMenu->ModifyMenu(17, MF_BYPOSITION, 17, plugin->GetInfo(ITMPlugin::TMI_NAME));\n        //获取插件图标\n        HICON plugin_icon{};\n        if (plugin->GetAPIVersion() >= 5)\n            plugin_icon = (HICON)plugin->GetPluginIcon();\n        //设置插件图标\n        if (plugin_icon != nullptr)\n            CMenuIcon::AddIconToMenuItem(pContextMenu->GetSafeHmenu(), 17, TRUE, plugin_icon);\n    }\n    //更新插件子菜单\n    theApp.UpdatePluginMenu(&theApp.m_main_menu_plugin_sub_menu, plugin, 2);\n\n    pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this); //在指定位置显示弹出菜单\n\n    CDialog::OnRButtonUp(nFlags, point1);\n}\n\n\nvoid CTrafficMonitorDlg::OnLButtonDown(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    CheckClickedItem(point);\n    bool plugin_item_clicked = false;   //是否响应了插件项目的左键点击事件\n    if (m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr)      //点击的是否为插件项目\n    {\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n        {\n            if (m_clicked_item.PluginItem()->OnMouseEvent(IPluginItem::MT_LCLICKED, point.x, point.y, (void*)GetSafeHwnd(), 0) != 0)\n            {\n                plugin_item_clicked = true;\n                Invalidate();\n            }\n        }\n    }\n\n    //在未锁定窗口位置时允许通过点击窗口内部来拖动窗口\n    if (!theApp.m_main_wnd_data.m_lock_window_pos && !plugin_item_clicked)\n        PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));\n    CDialog::OnLButtonDown(nFlags, point);\n}\n\n\nvoid CTrafficMonitorDlg::OnNetworkInfo()\n{\n    // TODO: 在此添加命令处理程序代码\n    //弹出“连接详情”对话框\n    CNetworkInfoDlg aDlg(m_connections, m_pIfTable->table, m_connection_selected);\n    ////向CNetworkInfoDlg类传递自启动以来已发送和接收的字节数\n    //aDlg.m_in_bytes = m_pIfTable->table[m_connections[m_connection_selected].index].dwInOctets - m_connections[m_connection_selected].in_bytes;\n    //aDlg.m_out_bytes = m_pIfTable->table[m_connections[m_connection_selected].index].dwOutOctets - m_connections[m_connection_selected].out_bytes;\n    aDlg.m_start_time = m_start_time;\n    aDlg.DoModal();\n    //SetAlwaysOnTop(); //由于在“连接详情”对话框内设置了取消窗口置顶，所有在对话框关闭后，重新设置窗口置顶\n    if (m_tBarDlg != nullptr)\n        m_tBarDlg->m_tool_tips.SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);  //重新设置任务栏窗口的提示信息置顶\n}\n\n\nvoid CTrafficMonitorDlg::OnAlwaysOnTop()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_main_wnd_data.m_always_on_top = !theApp.m_main_wnd_data.m_always_on_top;\n    SetAlwaysOnTop();\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnTransparency100()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_cfg_data.m_transparency = 100;\n    SetTransparency();\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnTransparency80()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_cfg_data.m_transparency = 80;\n    SetTransparency();\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnTransparency60()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_cfg_data.m_transparency = 60;\n    SetTransparency();\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnTransparency40()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_cfg_data.m_transparency = 40;\n    SetTransparency();\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnClose()\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    theApp.m_cannot_save_config_warning = true;\n    theApp.m_cannot_save_global_config_warning = true;\n    theApp.SaveConfig();    //退出前保存设置到ini文件\n    theApp.SaveGlobalConfig();\n    SaveHistoryTraffic();\n    BackupHistoryTrafficFile();\n\n    if (IsTaskbarWndValid())\n        m_tBarDlg->OnCancel();\n\n    //确保在退出前关闭所有窗口\n    for (const auto& item : CBaseDialog::AllUniqueHandels())\n    {\n        ::SendMessage(item.second, WM_COMMAND, IDCANCEL, 0);\n    }\n\n    CDialog::OnClose();\n}\n\n\nBOOL CTrafficMonitorDlg::OnCommand(WPARAM wParam, LPARAM lParam)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    UINT uMsg = LOWORD(wParam);\n    if (uMsg == ID_SELECT_ALL_CONNECTION)\n    {\n        theApp.m_cfg_data.m_select_all = true;\n        theApp.m_cfg_data.m_auto_select = false;\n        m_connection_change_flag = true;\n    }\n    //选择了“选择网络连接”子菜单中项目时的处理\n    if (uMsg == ID_SELETE_CONNECTION)   //选择了“自动选择”菜单项\n    {\n        AutoSelect();\n        theApp.m_cfg_data.m_auto_select = true;\n        theApp.m_cfg_data.m_select_all = false;\n        theApp.SaveConfig();\n        m_connection_change_flag = true;\n    }\n    if (uMsg > ID_SELECT_ALL_CONNECTION && uMsg <= ID_SELECT_ALL_CONNECTION + m_connections.size()) //选择了一个网络连接\n    {\n        m_connection_selected = uMsg - ID_SELECT_ALL_CONNECTION - 1;\n        theApp.m_cfg_data.m_connection_name = GetConnection(m_connection_selected).description_2;\n        m_connection_name_preferd = theApp.m_cfg_data.m_connection_name;\n        theApp.m_cfg_data.m_auto_select = false;\n        theApp.m_cfg_data.m_select_all = false;\n        theApp.SaveConfig();\n        m_connection_change_flag = true;\n    }\n#ifdef DEBUG\n    if (uMsg == ID_CMD_TEST)\n    {\n        CTest::TestCommand();\n        //ShowNotifyTip(CCommon::LoadText(_T(\"TrafficMonitor \"), IDS_NOTIFY), _T(\"测试通知\"));\n\n    }\n#endif // DEBUG\n    //选择了插件命令\n    if (uMsg >= ID_PLUGIN_COMMAND_START && uMsg <= ID_PLUGIN_COMMAND_MAX)\n    {\n        int index = uMsg - ID_PLUGIN_COMMAND_START;\n        if (m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr)\n        {\n            ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n            if (plugin != nullptr && plugin->GetAPIVersion() >= 5)\n            {\n                plugin->OnPluginCommand(index, (void*)GetSafeHwnd(), nullptr);\n            }\n        }\n    }\n\n\n    return CDialog::OnCommand(wParam, lParam);\n    }\n\n\nvoid CTrafficMonitorDlg::OnInitMenu(CMenu* pMenu)\n{\n    CDialog::OnInitMenu(pMenu);\n\n    // TODO: 在此处添加消息处理程序代码\n    m_menu_popuped = true;\n\n    pMenu->CheckMenuItem(ID_ALWAYS_ON_TOP, MF_BYCOMMAND | (theApp.m_main_wnd_data.m_always_on_top ? MF_CHECKED : MF_UNCHECKED));\n    pMenu->CheckMenuItem(ID_LOCK_WINDOW_POS, MF_BYCOMMAND | (theApp.m_main_wnd_data.m_lock_window_pos ? MF_CHECKED : MF_UNCHECKED));\n    pMenu->CheckMenuItem(ID_SHOW_CPU_MEMORY, MF_BYCOMMAND | (theApp.m_cfg_data.m_show_more_info ? MF_CHECKED : MF_UNCHECKED));\n    pMenu->CheckMenuItem(ID_MOUSE_PENETRATE, MF_BYCOMMAND | (theApp.m_main_wnd_data.m_mouse_penetrate ? MF_CHECKED : MF_UNCHECKED));\n    pMenu->CheckMenuItem(ID_SHOW_TASK_BAR_WND, MF_BYCOMMAND | (theApp.m_cfg_data.m_show_task_bar_wnd ? MF_CHECKED : MF_UNCHECKED));\n    pMenu->CheckMenuItem(ID_SHOW_MAIN_WND, MF_BYCOMMAND | (!theApp.m_cfg_data.m_hide_main_window ? MF_CHECKED : MF_UNCHECKED));\n    pMenu->CheckMenuItem(ID_ALOW_OUT_OF_BORDER, MF_BYCOMMAND | (theApp.m_main_wnd_data.m_alow_out_of_border ? MF_CHECKED : MF_UNCHECKED));\n\n    //设置“选择连接”子菜单项中各单选项的选择状态\n    SetConnectionMenuState(theApp.m_main_menu.GetSubMenu(0)->GetSubMenu(0));\n    SetConnectionMenuState(theApp.m_main_menu_plugin.GetSubMenu(0)->GetSubMenu(0));\n\n    //设置“窗口不透明度”子菜单下各单选项的选择状态\n    switch (theApp.m_cfg_data.m_transparency)\n    {\n    case 100: pMenu->CheckMenuRadioItem(ID_TRANSPARENCY_100, ID_TRANSPARENCY_40, ID_TRANSPARENCY_100, MF_BYCOMMAND | MF_CHECKED); break;\n    case 80: pMenu->CheckMenuRadioItem(ID_TRANSPARENCY_100, ID_TRANSPARENCY_40, ID_TRANSPARENCY_80, MF_BYCOMMAND | MF_CHECKED); break;\n    case 60: pMenu->CheckMenuRadioItem(ID_TRANSPARENCY_100, ID_TRANSPARENCY_40, ID_TRANSPARENCY_60, MF_BYCOMMAND | MF_CHECKED); break;\n    case 40: pMenu->CheckMenuRadioItem(ID_TRANSPARENCY_100, ID_TRANSPARENCY_40, ID_TRANSPARENCY_40, MF_BYCOMMAND | MF_CHECKED); break;\n    default: break;\n    }\n\n    if (theApp.IsForceShowNotifyIcon())    //如果没有显示任务栏窗口，且隐藏了主窗口或设置了鼠标穿透，则禁用“显示通知区图标”菜单项\n        pMenu->EnableMenuItem(ID_SHOW_NOTIFY_ICON, MF_BYCOMMAND | MF_GRAYED);\n    else\n        pMenu->EnableMenuItem(ID_SHOW_NOTIFY_ICON, MF_BYCOMMAND | MF_ENABLED);\n\n    pMenu->EnableMenuItem(ID_SELECT_ALL_CONNECTION, MF_BYCOMMAND | (theApp.m_general_data.show_all_interface ? MF_GRAYED : MF_ENABLED));\n\n    pMenu->EnableMenuItem(ID_CHECK_UPDATE, MF_BYCOMMAND | (theApp.IsCheckingForUpdate() ? MF_GRAYED : MF_ENABLED));\n\n    //设置插件命令的勾选状态\n    ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n    if (plugin != nullptr && plugin->GetAPIVersion() >= 5)\n    {\n        for (int i = ID_PLUGIN_COMMAND_START; i <= ID_PLUGIN_COMMAND_MAX; i++)\n        {\n            bool checked = (plugin->IsCommandChecked(i) != 0);\n            pMenu->CheckMenuItem(i, MF_BYCOMMAND | (checked ? MF_CHECKED : MF_UNCHECKED));\n        }\n    }\n\n    //pMenu->SetDefaultItem(ID_NETWORK_INFO);\n}\n\n\nBOOL CTrafficMonitorDlg::PreTranslateMessage(MSG* pMsg)\n{\n    // TODO: 在此添加专用代码和/或调用基类\n    //屏蔽按回车键和ESC键退出\n    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) return TRUE;\n    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) return TRUE;\n\n    if (theApp.m_main_wnd_data.show_tool_tip && m_tool_tips.GetSafeHwnd())\n    {\n        m_tool_tips.RelayEvent(pMsg);\n    }\n\n    if (pMsg->message == WM_KEYDOWN)\n    {\n        bool ctrl = (GetKeyState(VK_CONTROL) & 0x80);\n        bool shift = (GetKeyState(VK_SHIFT) & 0x8000);\n        bool alt = (GetKeyState(VK_MENU) & 0x8000);\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 4)\n        {\n            if (m_clicked_item.PluginItem()->OnKeboardEvent(pMsg->wParam, ctrl, shift, alt, (void*)GetSafeHwnd(), IPluginItem::KF_TASKBAR_WND) != 0)\n                return TRUE;\n        }\n    }\n\n    return CDialog::PreTranslateMessage(pMsg);\n}\n\n\nvoid CTrafficMonitorDlg::OnLockWindowPos()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_main_wnd_data.m_lock_window_pos = !theApp.m_main_wnd_data.m_lock_window_pos;\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnMove(int x, int y)\n{\n    CDialog::OnMove(x, y);\n\n    // TODO: 在此处添加消息处理程序代码\n\n    if (!m_first_start)\n    {\n        theApp.m_cfg_data.m_position_x = x;\n        theApp.m_cfg_data.m_position_y = y;\n    }\n\n    ////确保窗口不会超出屏幕范围\n    //CheckWindowPos();\n}\n\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)\n{\n    bool dialog_exist{ false };\n    HWND handle{};\n    if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONUP || lParam == WM_LBUTTONDBLCLK)\n    {\n        for (const auto& item : CBaseDialog::AllUniqueHandels())\n        {\n            if (IsWindow(item.second))\n            {\n                dialog_exist = true;\n                handle = item.second;\n                break;\n            }\n        }\n    }\n\n    if (lParam == WM_LBUTTONDOWN)\n    {\n        if (!theApp.m_cfg_data.m_hide_main_window)\n        {\n            if (dialog_exist)       //有打开的对话框时，点击通知区图标后将焦点设置到对话框\n            {\n                ::SetForegroundWindow(handle);\n            }\n            else        //没有打开的对话框时，则显示主窗口\n            {\n                ShowWindow(SW_RESTORE);\n                theApp.m_cfg_data.m_hide_main_window = false;\n                SetForegroundWindow();\n                SetAlwaysOnTop();\n                CheckWindowPos();\n                theApp.SaveConfig();\n            }\n        }\n    }\n    if (lParam == WM_RBUTTONUP)\n    {\n        if (dialog_exist)       //有打开的对话框时，点击通知区图标后将焦点设置到对话框\n        {\n            ::SetForegroundWindow(handle);\n        }\n        else\n        {\n            //在通知区点击右键弹出右键菜单\n            if (IsTaskbarWndValid())        //如果显示了任务栏窗口，则在右击了通知区图标后将焦点设置到任务栏窗口\n                m_tBarDlg->SetForegroundWindow();\n            else                //否则将焦点设置到主窗口\n                SetForegroundWindow();\n            CPoint point1;  //定义一个用于确定光标位置的位置\n            GetCursorPos(&point1);  //获取当前光标的位置，以便使得菜单可以跟随光标\n            theApp.m_main_menu.GetSubMenu(0)->SetDefaultItem(-1);       //设置没有默认菜单项\n            theApp.m_main_menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this); //在指定位置显示弹出菜单\n\n            CheckWindowPos();\n        }\n    }\n    if (lParam == WM_LBUTTONDBLCLK)\n    {\n        if (dialog_exist)       //有打开的对话框时，点击通知区图标后将焦点设置到对话框\n        {\n            ::SetForegroundWindow(handle);\n        }\n        else        //没有打开的对话框时，则显示主窗口\n        {\n            ShowWindow(SW_RESTORE);\n            theApp.m_cfg_data.m_hide_main_window = false;\n            SetForegroundWindow();\n            SetAlwaysOnTop();\n            CheckWindowPos();\n            theApp.SaveConfig();\n        }\n    }\n    return 0;\n}\n\n\nvoid CTrafficMonitorDlg::OnShowNotifyIcon()\n{\n    // TODO: 在此添加命令处理程序代码\n    if (theApp.m_general_data.show_notify_icon)\n    {\n        DeleteNotifyIcon();\n        theApp.m_general_data.show_notify_icon = false;\n    }\n    else\n    {\n        AddNotifyIcon();\n        theApp.m_general_data.show_notify_icon = true;\n    }\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnDestroy()\n{\n    CDialog::OnDestroy();\n\n    //程序退出时删除通知栏图标\n    ::Shell_NotifyIcon(NIM_DELETE, &m_ntIcon);\n\n    // 停止监控线程\n    ExitMonitorThread();\n}\n\n\nvoid CTrafficMonitorDlg::OnShowCpuMemory()\n{\n    // TODO: 在此添加命令处理程序代码\n    CRect rect;\n    GetWindowRect(rect);\n    theApp.m_cfg_data.m_show_more_info = !theApp.m_cfg_data.m_show_more_info;\n    if (theApp.m_cfg_data.m_show_more_info)\n    {\n        rect.right = rect.left + m_skin.GetLayoutInfo().layout_l.width;\n        rect.bottom = rect.top + m_skin.GetLayoutInfo().layout_l.width;\n        MoveWindow(rect);\n        CheckWindowPos();\n    }\n    else\n    {\n        rect.right = rect.left + m_skin.GetLayoutInfo().layout_s.width;\n        rect.bottom = rect.top + m_skin.GetLayoutInfo().layout_s.height;\n        MoveWindow(rect);\n        CheckWindowPos();\n    }\n    LoadBackGroundImage();\n    SetItemPosition();\n    Invalidate(FALSE);\n    theApp.SaveConfig();\n}\n\n\n//任务栏窗口切换显示CPU和内存利用率时的处理\nvoid CTrafficMonitorDlg::OnShowCpuMemory2()\n{\n    // TODO: 在此添加命令处理程序代码\n    if (IsTaskbarWndValid())\n    {\n        bool show_cpu_memory = (theApp.m_taskbar_data.display_item.Contains(TDI_CPU) || theApp.m_taskbar_data.display_item.Contains(TDI_MEMORY));\n        if (show_cpu_memory)\n        {\n            theApp.m_taskbar_data.display_item.Remove(TDI_CPU);\n            theApp.m_taskbar_data.display_item.Remove(TDI_MEMORY);\n        }\n        else\n        {\n            theApp.m_taskbar_data.display_item.Add(TDI_CPU);\n            theApp.m_taskbar_data.display_item.Add(TDI_MEMORY);\n        }\n        //theApp.m_cfg_data.m_tbar_show_cpu_memory = !theApp.m_cfg_data.m_tbar_show_cpu_memory;\n        //切换显示CPU和内存利用率时，删除任务栏窗口，再重新显示\n        //CloseTaskBarWnd();\n        //OpenTaskBarWnd();\n        m_tBarDlg->WidthChanged();\n    }\n}\n\n\nvoid CTrafficMonitorDlg::OnMousePenetrate()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_main_wnd_data.m_mouse_penetrate = !theApp.m_main_wnd_data.m_mouse_penetrate;\n    SetMousePenetrate();\n    if (!theApp.m_general_data.show_notify_icon && theApp.IsForceShowNotifyIcon())   //鼠标穿透时，如果通知图标没有显示，则将它显示出来，否则无法呼出右键菜单\n    {\n        //添加通知栏图标\n        AddNotifyIcon();\n        theApp.m_general_data.show_notify_icon = true;\n    }\n\n    //设置鼠标穿透后，弹出消息提示用户如何关闭鼠标穿透\n    if (theApp.m_main_wnd_data.m_mouse_penetrate && theApp.m_show_mouse_panetrate_tip)\n    {\n        if (MessageBox(CCommon::LoadText(IDS_MOUSE_PENETRATE_TIP_INFO), NULL, MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL)        //点击“取消”后不再提示\n        {\n            theApp.m_show_mouse_panetrate_tip = false;\n        }\n    }\n\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnShowTaskBarWnd()\n{\n    // TODO: 在此添加命令处理程序代码\n    if (m_tBarDlg != nullptr)\n    {\n        CloseTaskBarWnd();\n    }\n    if (!theApp.m_cfg_data.m_show_task_bar_wnd)\n    {\n        theApp.m_cfg_data.m_show_task_bar_wnd = true;\n        OpenTaskBarWnd();\n    }\n    else\n    {\n        theApp.m_cfg_data.m_show_task_bar_wnd = false;\n        //关闭任务栏窗口后，如果没有显示通知区图标，且没有显示主窗口或设置了鼠标穿透，则将通知区图标显示出来\n        if (!theApp.m_general_data.show_notify_icon && theApp.IsForceShowNotifyIcon())\n        {\n            AddNotifyIcon();\n            theApp.m_general_data.show_notify_icon = true;\n        }\n    }\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnAppAbout()\n{\n    // TODO: 在此添加命令处理程序代码\n    //弹出“关于”对话框\n    CAboutDlg aDlg;\n    aDlg.DoModal();\n}\n\n\n//当资源管理器重启时会触发此消息\nLRESULT CTrafficMonitorDlg::OnTaskBarCreated(WPARAM wParam, LPARAM lParam)\n{\n    if (m_tBarDlg != nullptr)\n    {\n        CloseTaskBarWnd();\n        if (theApp.m_general_data.show_notify_icon)\n        {\n            //重新添加通知栏图标\n            ::Shell_NotifyIcon(NIM_ADD, &m_ntIcon);\n        }\n        OpenTaskBarWnd();\n    }\n    else\n    {\n        if (theApp.m_general_data.show_notify_icon)\n            ::Shell_NotifyIcon(NIM_ADD, &m_ntIcon);\n    }\n    return LRESULT();\n}\n\n\nvoid CTrafficMonitorDlg::OnShowMainWnd()\n{\n    // TODO: 在此添加命令处理程序代码\n    if (!theApp.m_cfg_data.m_hide_main_window)\n    {\n        ShowWindow(SW_HIDE);\n        theApp.m_cfg_data.m_hide_main_window = true;\n        //隐藏主窗口后，如果没有显示通知栏图标，则将其显示出来\n        if (!theApp.m_general_data.show_notify_icon && theApp.IsForceShowNotifyIcon())\n        {\n            AddNotifyIcon();\n            theApp.m_general_data.show_notify_icon = true;\n        }\n    }\n    else\n    {\n        ShowWindow(SW_RESTORE);\n        theApp.m_cfg_data.m_hide_main_window = false;\n    }\n    theApp.SaveConfig();\n}\n\n\nvoid CTrafficMonitorDlg::OnChangeSkin()\n{\n    // TODO: 在此添加命令处理程序代码\n    CSkinDlg skinDlg;\n    //初始化CSkinDlg对象的数据\n    skinDlg.m_skin_selected = m_skin_selected;\n    if (skinDlg.DoModal() == IDOK)\n    {\n        ApplySkin(skinDlg.m_skin_selected);\n    }\n}\n\n\n\nvoid CTrafficMonitorDlg::OnTrafficHistory()\n{\n    // TODO: 在此添加命令处理程序代码\n    CHistoryTrafficDlg historyDlg(m_history_traffic.GetTraffics());\n    historyDlg.DoModal();\n}\n\n\nvoid CTrafficMonitorDlg::OnMouseMove(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n\n    CDialog::OnMouseMove(nFlags, point);\n}\n\n\nvoid CTrafficMonitorDlg::OnLButtonDblClk(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    CheckClickedItem(point);\n    if (m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr)\n    {\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n        {\n            if (m_clicked_item.PluginItem()->OnMouseEvent(IPluginItem::MT_DBCLICKED, point.x, point.y, (void*)GetSafeHwnd(), 0) != 0)\n                return;\n        }\n    }\n\n    switch (theApp.m_main_wnd_data.double_click_action)\n    {\n    case DoubleClickAction::CONNECTION_INFO:\n        OnNetworkInfo();            //双击后弹出“连接详情”对话框\n        break;\n    case DoubleClickAction::HISTORY_TRAFFIC:\n        OnTrafficHistory();         //双击后弹出“历史流量统计”对话框\n        break;\n    case DoubleClickAction::SHOW_MORE_INFO:\n        OnShowCpuMemory();          //切换显示CPU和内存利用率\n        break;\n    case DoubleClickAction::OPTIONS:\n        OnOptions();                //双击后弹出“选项设置”对话框\n        break;\n    case DoubleClickAction::TASK_MANAGER:\n        ShellExecuteW(NULL, _T(\"open\"), (theApp.m_system_dir + L\"\\\\Taskmgr.exe\").c_str(), NULL, NULL, SW_NORMAL);       //打开任务管理器\n        break;\n    case DoubleClickAction::SEPCIFIC_APP:\n        ShellExecuteW(NULL, _T(\"open\"), (theApp.m_main_wnd_data.double_click_exe).c_str(), NULL, NULL, SW_NORMAL);  //打开指定程序，默认任务管理器\n        break;\n    case DoubleClickAction::CHANGE_SKIN:\n        OnChangeSkin();             //双击后弹出“更换皮肤”对话框\n        break;\n    default:\n        break;\n    }\n    CDialog::OnLButtonDblClk(nFlags, point);\n}\n\n\nvoid CTrafficMonitorDlg::OnOptions()\n{\n    _OnOptions(0, this);\n}\n\n\n//通过任务栏窗口的右键菜单打开“选项”对话框\nvoid CTrafficMonitorDlg::OnOptions2()\n{\n    CWnd* pParent = this;\n    if (IsTaskbarWndValid())\n        pParent = m_tBarDlg;\n    _OnOptions(1, pParent);\n}\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnExitmenuloop(WPARAM wParam, LPARAM lParam)\n{\n    m_menu_popuped = false;\n    return 0;\n}\n\n\nvoid CTrafficMonitorDlg::OnChangeNotifyIcon()\n{\n    // TODO: 在此添加命令处理程序代码\n    CIconSelectDlg dlg(theApp.m_cfg_data.m_notify_icon_selected);\n    dlg.SetAutoAdaptNotifyIcon(theApp.m_cfg_data.m_notify_icon_auto_adapt);\n    if (dlg.DoModal() == IDOK)\n    {\n        theApp.m_cfg_data.m_notify_icon_selected = dlg.GetIconSelected();\n        theApp.m_cfg_data.m_notify_icon_auto_adapt = dlg.AutoAdaptNotifyIcon();\n        m_ntIcon.hIcon = theApp.m_notify_icons[theApp.m_cfg_data.m_notify_icon_selected];\n        if (theApp.m_cfg_data.m_notify_icon_auto_adapt)\n            theApp.AutoSelectNotifyIcon();\n        if (theApp.m_general_data.show_notify_icon)\n        {\n            DeleteNotifyIcon();\n            AddNotifyIcon();\n        }\n        theApp.SaveConfig();\n    }\n}\n\n\nvoid CTrafficMonitorDlg::OnAlowOutOfBorder()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.m_main_wnd_data.m_alow_out_of_border = !theApp.m_main_wnd_data.m_alow_out_of_border;\n    CheckWindowPos();\n}\n\n\nvoid CTrafficMonitorDlg::OnCheckUpdate()\n{\n    // TODO: 在此添加命令处理程序代码\n    theApp.CheckUpdateInThread(true);\n}\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnTaskbarMenuPopedUp(WPARAM wParam, LPARAM lParam)\n{\n    //设置“选择连接”子菜单项中各单选项的选择状态\n    SetConnectionMenuState(theApp.m_taskbar_menu.GetSubMenu(0)->GetSubMenu(0));\n    SetConnectionMenuState(theApp.m_taskbar_menu_plugin.GetSubMenu(0)->GetSubMenu(0));\n    return 0;\n}\n\n\n//任务栏窗口切换显示网速时的处理\nvoid CTrafficMonitorDlg::OnShowNetSpeed()\n{\n    // TODO: 在此添加命令处理程序代码\n    if (IsTaskbarWndValid())\n    {\n        bool show_net_speed = (theApp.m_taskbar_data.display_item.Contains(TDI_UP) || theApp.m_taskbar_data.display_item.Contains(TDI_DOWN));\n        if (show_net_speed)\n        {\n            theApp.m_taskbar_data.display_item.Remove(TDI_UP);\n            theApp.m_taskbar_data.display_item.Remove(TDI_DOWN);\n        }\n        else\n        {\n            theApp.m_taskbar_data.display_item.Add(TDI_UP);\n            theApp.m_taskbar_data.display_item.Add(TDI_DOWN);\n        }\n        //CloseTaskBarWnd();\n        //OpenTaskBarWnd();\n        m_tBarDlg->WidthChanged();\n    }\n}\n\n\nBOOL CTrafficMonitorDlg::OnQueryEndSession()\n{\n    if (!CDialog::OnQueryEndSession())\n        return FALSE;\n\n    // TODO:  在此添加专用的查询结束会话代码\n    theApp.SaveConfig();\n    theApp.SaveGlobalConfig();\n    SaveHistoryTraffic();\n    BackupHistoryTrafficFile();\n\n    if (theApp.m_debug_log)\n    {\n        CCommon::WriteLog(_T(\"TrafficMonitor进程已被终止，设置已保存。\"), (theApp.m_config_dir + L\".\\\\debug.log\").c_str());\n    }\n\n    return TRUE;\n}\n\n\nvoid CTrafficMonitorDlg::OnPaint()\n{\n    CPaintDC dc(this); // device context for painting\n                       // TODO: 在此处添加消息处理程序代码\n                       // 不为绘图消息调用 CDialog::OnPaint()\n    m_skin.DrawInfo(&dc, theApp.m_cfg_data.m_show_more_info);\n}\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnDpichanged(WPARAM wParam, LPARAM lParam)\n{\n    static int dpi;\n    static CTrafficMonitorDlg* pThis;\n    dpi = LOWORD(wParam);\n    pThis = this;\n\n    //由于当悬浮拖动到不同DPI的显示器上时，会短时间内触发多次DPI更改消息，因此这里在收到消息后延迟一段时间后再处理\n    KillTimer(DPI_CHANGE_TIMER);\n    SetTimer(DPI_CHANGE_TIMER, 500, [](HWND, UINT, UINT_PTR, DWORD) {\n        //根据主窗口的位置获取DPI\n        CRect rect;\n        pThis->GetWindowRect(rect);\n        UINT dpi_x, dpi_y;\n        if (theApp.DPIFromRect(rect, &dpi_x, &dpi_y))   //获取成功，则使用根据主窗口位置得到的dpi\n            dpi = dpi_x;\n        TRACE(\"Dpi changed: %d\\n\", dpi);\n\n        theApp.SetDPI(dpi);\n        //当系统版本小于Windows 8.1时使用原来的行为\n        if (pThis->IsTaskbarWndValid() && !theApp.m_win_version.IsWindows8Point1OrLater())\n        {\n            //为任务栏窗口重新指定DPI\n            pThis->m_tBarDlg->SetDPI(dpi);\n            //根据新的DPI重新设置任务栏窗口字体\n            pThis->m_tBarDlg->SetTextFont();\n        }\n\n        pThis->LoadSkinLayout();   //根据当前选择的皮肤获取布局数据\n        pThis->SetItemPosition();  //初始化窗口位置\n        pThis->LoadBackGroundImage();\n        pThis->SetTextFont();      //重新加载字体\n        pThis->Invalidate(FALSE);  //重绘界面\n\n        pThis->KillTimer(DPI_CHANGE_TIMER);\n    });\n\n    return 0;\n}\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnTaskbarWndClosed(WPARAM wParam, LPARAM lParam)\n{\n    theApp.m_cfg_data.m_show_task_bar_wnd = false;\n    //关闭任务栏窗口后，如果没有显示通知区图标，且没有显示主窗口或设置了鼠标穿透，则将通知区图标显示出来\n    if (!theApp.m_general_data.show_notify_icon && theApp.IsForceShowNotifyIcon())\n    {\n        AddNotifyIcon();\n        theApp.m_general_data.show_notify_icon = true;\n    }\n    return 0;\n}\n\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnMonitorInfoUpdated(WPARAM wParam, LPARAM lParam)\n{\n    Invalidate(FALSE);      //刷新窗口信息\n\n    //更新鼠标提示\n    if (theApp.m_main_wnd_data.show_tool_tip && m_tool_tips.GetSafeHwnd() != NULL)\n    {\n        CString tip_info;\n        tip_info = GetMouseTipsInfo();\n        m_tool_tips.UpdateTipText(tip_info, this);\n    }\n    //更新任务栏窗口鼠标提示\n    if (IsTaskbarWndValid())\n        m_tBarDlg->UpdateToolTips();\n    return 0;\n}\n\n\nLRESULT CTrafficMonitorDlg::OnDisplaychange(WPARAM wParam, LPARAM lParam)\n{\n    GetScreenSize();\n    CheckWindowPos(true);\n    return 0;\n}\n\n\nvoid CTrafficMonitorDlg::OnExitSizeMove()\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    CheckWindowPos();\n\n    CDialog::OnExitSizeMove();\n}\n\n\nvoid CTrafficMonitorDlg::OnPluginManage()\n{\n    // TODO: 在此添加命令处理程序代码\n    CPluginManagerDlg dlg;\n    dlg.DoModal();\n}\n\nLRESULT CTrafficMonitorDlg::OnReopenTaksbarWnd(WPARAM wParam, LPARAM lParam)\n{\n    CloseTaskBarWnd();\n    OpenTaskBarWnd();\n    return 0;\n}\n\n\nvoid CTrafficMonitorDlg::OnOpenTaskManager()\n{\n    ShellExecuteW(NULL, _T(\"open\"), (theApp.m_system_dir + L\"\\\\Taskmgr.exe\").c_str(), NULL, NULL, SW_NORMAL);       //打开任务管理器\n}\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnSettingsApplied(WPARAM wParam, LPARAM lParam)\n{\n    COptionsDlg* pOptionsDlg = (COptionsDlg*)wParam;\n    if (pOptionsDlg != nullptr)\n    {\n        ApplySettings(*pOptionsDlg);\n    }\n    return 0;\n}\n\n\nvoid CTrafficMonitorDlg::OnDisplaySettings()\n{\n    // TODO: 在此添加命令处理程序代码\n    CSetItemOrderDlg dlg;\n    dlg.SetItemOrder(theApp.m_taskbar_data.item_order.GetItemOrderConst());\n    dlg.SetDisplayItem(theApp.m_taskbar_data.display_item);\n    dlg.SetPluginDisplayItem(theApp.m_taskbar_data.plugin_display_item);\n    if (dlg.DoModal() == IDOK)\n    {\n        theApp.m_taskbar_data.item_order.SetOrder(dlg.GetItemOrder());\n        theApp.m_taskbar_data.display_item = dlg.GetDisplayItem();\n        theApp.m_taskbar_data.plugin_display_item = dlg.GetPluginDisplayItem();\n        //CloseTaskBarWnd();\n        //OpenTaskBarWnd();\n        if (IsTaskbarWndValid())\n            m_tBarDlg->WidthChanged();\n    }\n}\n\n\nvoid CTrafficMonitorDlg::OnLButtonUp(UINT nFlags, CPoint point)\n{\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n    //CheckClickedItem(point);\n    //if (m_clicked_item.IsPlugin() && m_clicked_item.PluginItem() != nullptr)\n    //{\n    //    ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n    //    if (plugin != nullptr && plugin->GetAPIVersion() >= 3)\n    //    {\n    //        if (m_clicked_item.PluginItem()->OnMouseEvent(IPluginItem::MT_LCLICKED, point.x, point.y, (void*)GetSafeHwnd(), 0) != 0)\n    //            return;\n    //    }\n    //}\n\n    CDialog::OnLButtonUp(nFlags, point);\n}\n\n\nvoid CTrafficMonitorDlg::OnRefreshConnectionList()\n{\n    IniConnection();\n\n}\n\n\nafx_msg LRESULT CTrafficMonitorDlg::OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam)\n{\n    return 0;\n}\n\n\nvoid CTrafficMonitorDlg::OnPluginOptions()\n{\n    if (m_clicked_item.IsPlugin())\n    {\n        //找到对应的插件\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr)\n        {\n            //显示插件的选项设置\n            auto rtn = plugin->ShowOptionsDialog(GetSafeHwnd());\n            if (rtn == ITMPlugin::OR_OPTION_NOT_PROVIDED)\n                MessageBox(CCommon::LoadText(IDS_PLUGIN_NO_OPTIONS_INFO), nullptr, MB_ICONINFORMATION | MB_OK);\n        }\n    }\n}\n\n\nvoid CTrafficMonitorDlg::OnPluginDetail()\n{\n    if (m_clicked_item.IsPlugin())\n    {\n        //找到对应的插件\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_clicked_item.PluginItem());\n        if (plugin != nullptr)\n        {\n            int index = theApp.m_plugins.GetPluginIndex(plugin);\n            CPluginInfoDlg dlg(index);\n            dlg.DoModal();\n        }\n    }\n}\n\n\nvoid CTrafficMonitorDlg::OnPluginOptionsTaksbar()\n{\n    //判断任务栏窗口中点击的项目是否是插件项目\n    if (IsTaskbarWndValid() && m_tBarDlg->GetClickedItem().IsPlugin())\n    {\n        //找到对应的插件\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_tBarDlg->GetClickedItem().PluginItem());\n        if (plugin != nullptr)\n        {\n            //显示插件的选项设置\n            auto rtn = plugin->ShowOptionsDialog(m_tBarDlg->GetSafeHwnd());\n            if (rtn == ITMPlugin::OR_OPTION_CHANGED)    //选项设置有更改，重新打开任务栏窗口\n            {\n                //CloseTaskBarWnd();\n                //OpenTaskBarWnd();\n                m_tBarDlg->WidthChanged();\n            }\n            if (rtn == ITMPlugin::OR_OPTION_NOT_PROVIDED)\n                MessageBox(CCommon::LoadText(IDS_PLUGIN_NO_OPTIONS_INFO), nullptr, MB_ICONINFORMATION | MB_OK);\n        }\n    }\n}\n\n\nvoid CTrafficMonitorDlg::OnPluginDetailTaksbar()\n{\n    if (IsTaskbarWndValid() && m_tBarDlg->GetClickedItem().IsPlugin())\n    {\n        //找到对应的插件\n        ITMPlugin* plugin = theApp.m_plugins.GetPluginByItem(m_tBarDlg->GetClickedItem().PluginItem());\n        if (plugin != nullptr)\n        {\n            int index = theApp.m_plugins.GetPluginIndex(plugin);\n            CPluginInfoDlg dlg(index);\n            dlg.DoModal();\n        }\n    }\n}\n\n\nUINT CTrafficMonitorDlg::OnPowerBroadcast(UINT nPowerEvent, LPARAM nEventData)\n{\n    // 系统从休眠恢复\n    if (nPowerEvent == PBT_APMRESUMESUSPEND)\n    {\n        //延迟一段时间后重新初始化网络连接\n        KillTimer(INIT_CONNECT_TIMER);\n        static CTrafficMonitorDlg* pThis = this;\n        static int check_times = 0;\n        SetTimer(INIT_CONNECT_TIMER, 10000, [](HWND, UINT, UINT_PTR, DWORD) {\n            pThis->IniConnection();\n            check_times++;\n\n            //写入日志\n            CString info = CCommon::LoadTextFormat(IDS_RESTORE_FROM_SLEEP_LOG, {pThis->m_restart_cnt });\n            CCommon::WriteLog(info, theApp.m_log_path.c_str());\n\n            //如果连接为空，定时器继续运行，每隔一段时间重新初始化连接\n            if (pThis->m_connections.size() == 0)\n            {\n                //超过20次，结束定时器\n                if (check_times >= 20)\n                    pThis->KillTimer(INIT_CONNECT_TIMER);\n            }\n            //成功获取到连接，结束定时器\n            else\n            {\n                pThis->KillTimer(INIT_CONNECT_TIMER);\n                check_times = 0;\n            }\n        });\n    }\n    return CDialog::OnPowerBroadcast(nPowerEvent, nEventData);\n}\n\n\nvoid CTrafficMonitorDlg::OnColorizationColorChanged(DWORD dwColorizationColor, BOOL bOpacity)\n{\n    // 此功能要求 Windows Vista 或更高版本。\n    // _WIN32_WINNT 符号必须 >= 0x0600。\n    // TODO: 在此添加消息处理程序代码和/或调用默认值\n\n    static DWORD last_color;\n    if (last_color != dwColorizationColor)\n    {\n        last_color = dwColorizationColor;\n        BYTE red = (dwColorizationColor >> 16) & 0xFF;\n        BYTE green = (dwColorizationColor >> 8) & 0xFF;\n        BYTE blue = dwColorizationColor & 0xFF;\n        COLORREF theme_color = RGB(red, green, blue);\n        theApp.SetThemeColor(theme_color);\n    }\n    CDialog::OnColorizationColorChanged(dwColorizationColor, bOpacity);\n}\n"
  },
  {
    "path": "TrafficMonitor/TrafficMonitorDlg.h",
    "content": "﻿\n// TrafficMonitorDlg.h : 头文件\n//\n\n#pragma once\n#pragma comment (lib, \"iphlpapi.lib\")\n\n#include \"NetworkInfoDlg.h\"\n#include \"afxwin.h\"\n#include \"StaticEx.h\"\n#include \"Common.h\"\n#include \"TaskBarDlg.h\"\n#include \"SkinDlg.h\"\n#include \"HistoryTrafficDlg.h\"\n#include \"OptionsDlg.h\"\n#include \"PictureStatic.h\"\n#include \"IconSelectDlg.h\"\n#include \"DrawCommon.h\"\n#include \"IniHelper.h\"\n#include \"LinkStatic.h\"\n#include \"AdapterCommon.h\"\n#include \"AboutDlg.h\"\n#include \"PdhHardwareQuery/CPUUsage.h\"\n#include \"PdhHardwareQuery/CpuFreq.h\"\n#include \"PdhHardwareQuery/GpuUsage.h\"\n#include \"PdhHardwareQuery/DiskUsage.h\"\n#include \"HistoryTrafficFile.h\"\n\n// CTrafficMonitorDlg 对话框\nclass CTrafficMonitorDlg : public CDialog\n{\n    // 构造\npublic:\n    CTrafficMonitorDlg(CWnd* pParent = NULL);   // 标准构造函数\n    ~CTrafficMonitorDlg();\n    CTaskBarDlg* GetTaskbarWindow() const;\n\n    static CTrafficMonitorDlg* Instance();\n\n    // 对话框数据\n#ifdef AFX_DESIGN_TIME\n    enum { IDD = IDD_TRAFFICMONITOR_DIALOG };\n#endif\n\n    const CSkinFile& GetCurSkin() const { return m_skin; }\n\n    CPdhDiskUsage& GetPdhDiskUsageHelper() { return m_disk_usage_helper; }\n    bool IsGetDiskUsageByPdh() const { return m_get_disk_usage_by_pdh; }\n\nprotected:\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n\n\n// 实现\nprotected:\n    HICON m_hIcon;\n    NOTIFYICONDATA m_ntIcon;    //通知区域图标\n    CTaskBarDlg* m_tBarDlg{};     //任务栏窗口的指针\n\n    vector<NetWorkConection> m_connections; //保存获取到的要显示到“选择网卡”菜单项中的所有网络连接\n    MIB_IFTABLE* m_pIfTable;\n    DWORD m_dwSize{};\t//m_pIfTable的大小\n    int m_connection_selected{ 0 }; //要显示流量的连接的序号\n    unsigned __int64 m_in_bytes{};        //当前已接收的字节数\n    unsigned __int64 m_out_bytes{};   //当前已发送的字节数\n    unsigned __int64 m_last_in_bytes{}; //上次已接收的字节数\n    unsigned __int64 m_last_out_bytes{};    //上次已发送的字节数\n\n    CCPUUsage m_cpu_usage_helper;\n    CPdhCpuFreq m_cpu_freq_helper;\n    CPdhGPUUsage m_gpu_usage_helper;\n    CPdhDiskUsage m_disk_usage_helper;\n\n    bool m_get_disk_usage_by_pdh{};\n\n    bool m_first_start{ true };     //初始时为true，在定时器第一次启动后置为flase\n\n    // https://www.jianshu.com/p/9d4b68cdbd99\n    struct Monitors\n    {\n        std::vector<MONITORINFO> monitorinfos;\n\n        static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)\n        {\n            MONITORINFO iMonitor;\n            iMonitor.cbSize = sizeof(MONITORINFO);\n            GetMonitorInfo(hMon, &iMonitor);\n\n            Monitors* pThis = reinterpret_cast<Monitors*>(pData);\n            pThis->monitorinfos.push_back(iMonitor);\n            return TRUE;\n        }\n\n        Monitors()\n        {\n            EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);\n        }\n    };\n\n    //CRect m_screen_rect;        //屏幕的范围（不包含任务栏）\n    vector<CRect> m_screen_rects;       //所有屏幕的范围（不包含任务栏）\n    vector<CRect> m_last_screen_rects;       //上一次所有屏幕的范围（不包含任务栏）\n    CSize m_screen_size;        //屏幕的大小（包含任务栏）\n    CSkinFile m_skin;\n    CommonDisplayItem m_clicked_item;           //鼠标点击的项目\n\n    int m_restart_cnt{ -1 };    //重新初始化次数\n    unsigned int m_timer_cnt{};     //定时器触发次数（自程序启动以来的秒数）\n    unsigned int m_taskbar_timer_cnt{0}; //适用于TaskBarDlg的定时器触发次数（自程序启动以来的秒数）\n    unsigned int m_monitor_time_cnt{};\n    int m_zero_speed_cnt{}; //如果检测不到网速，该变量就会自加\n    int m_insert_to_taskbar_cnt{};  //用来统计尝试嵌入任务栏的次数\n    int m_cannot_insert_to_task_bar_warning{ true };   //指示是否会在无法嵌入任务栏时弹出提示框\n\n    static unsigned int m_WM_TASKBARCREATED;    //任务栏重启消息\n\n    int m_skin_selected{};      //选择的皮肤序号\n\n    SYSTEMTIME m_start_time;    //程序启动时的时间\n    CHistoryTrafficFile m_history_traffic{ theApp.m_history_traffic_path }; //储存历史流量\n\n    CToolTipCtrl m_tool_tips;\n\n    bool m_connection_change_flag{ false };     //如果执行过IniConnection()函数，该flag会置为true\n    bool m_is_foreground_fullscreen{ false };   //指示前台窗口是否正在全局显示\n    bool m_menu_popuped{ false };               //指示当前是否有菜单处于弹出状态\n\n    HDC m_desktop_dc;\n\n    string m_connection_name_preferd{ theApp.m_cfg_data.m_connection_name };          //保存用户手动选择的网络连接名称\n\n    void DoMonitorAcquisition();    //获取一次监控信息\n    static UINT MonitorThreadCallback(LPVOID dwUser);   //获取监控信息的线程函数\n    bool m_monitor_data_required{ false };          //线程中需要获取监控数据标志，当需要获取监控数据时置为true，获取到一次监控数据时置为false\n    bool m_is_thread_exit{ false }; //线程退出标志\n    CEvent m_threadExitEvent;       //用于通知主线程工作线程已退出\npublic:\n    void ExitMonitorThread();       //停止监控线程\n\nprotected:\n    CString GetMouseTipsInfo();     //获取鼠标提示信息\n    void SetTransparency();         //根据m_transparency的值设置窗口透明度\n    void SetTransparency(int transparency);\npublic:\n    void SetAlwaysOnTop();          //根据m_always_on_top的值设置窗口置顶\nprotected:\n    void SetMousePenetrate();       //根据m_mouse_penetrate的值设置是否鼠标穿透\n    POINT CalculateWindowMoveOffset(CRect rect, bool screen_changed);  //计算当窗口处于屏幕区域外时，移动到屏幕区域需要移动的位置\n    void CheckWindowPos(bool screen_changed = false);          //测试窗口的位置，如窗口的位置在屏幕外，则移动窗口使其全部都在屏幕内，并返回新位置\n    void GetScreenSize();           //获取屏幕的大小\n\n    void AutoSelect();\n    //void UpdateConnections();\n    //自动选择连接\n    void IniConnection();   //初始化连接\n\n    MIB_IFROW GetConnectIfTable(int connection_index);    //获取当前选择的网络连接的MIB_IFROW对象。connection_index为m_connections中的索引\n    NetWorkConection GetConnection(int connection_index); //获取当前选择的网络连接的NetWorkConection对象。connection_index为m_connections中的索引\n\n    void IniConnectionMenu(CMenu* pMenu);   //初始化“选择网络连接”菜单\n    void IniTaskBarConnectionMenu();        //初始化任务栏窗口的“选择网络连接”菜单\n    void SetConnectionMenuState(CMenu* pMenu);      //设置“选择网络连接”菜单中选中的项目\n\n    void CloseTaskBarWnd(); //关闭任务栏窗口\n    void OpenTaskBarWnd();  //打开任务栏窗口\n\n    void AddNotifyIcon();       //添加通知区图标\n    void DeleteNotifyIcon();\npublic:\n    void ShowNotifyTip(const wchar_t* title, const wchar_t* message);       //显示通知区提示\nprotected:\n    void UpdateNotifyIconTip();     //更新通知区图标的鼠标提示\n\n    void SaveHistoryTraffic();\n    void LoadHistoryTraffic();\n    void BackupHistoryTrafficFile();\n\n    void _OnOptions(int tab, CWnd* pParent);   //打开“选项”对话框的处理，tab：打开时切换的标签\n\n    void ApplySettings(COptionsDlg& optionsDlg);\n\n    void SetItemPosition();     //设置显示的4个项目的位置\n    bool LoadSkinLayout();      //从当前皮肤获取布局数据\n\n    void LoadBackGroundImage();\n    void SetTextFont();\n\npublic:\n    bool IsTaskbarWndValid() const;\nprotected:\n\n    void TaskbarShowHideItem(DisplayItem type);\n\n    //判断一个点在哪个显示项目的区域内，并保存到m_clicked_item\n    void CheckClickedItem(CPoint point);\n\n    //应用一个皮肤\n    void ApplySkin(int skin_index);\n\npublic:\n    //void ApplySettings();\n    bool IsTemperatureNeeded() const;       //判断是否需要显示温度信息\n\nprotected:\n    // 生成的消息映射函数\n    virtual BOOL OnInitDialog();\n    //  afx_msg void OnPaint();\n    afx_msg HCURSOR OnQueryDragIcon();\n    DECLARE_MESSAGE_MAP()\npublic:\n    //  afx_msg LRESULT OnNcHitTest(CPoint point);\n    afx_msg void OnTimer(UINT_PTR nIDEvent);\n    //  afx_msg void OnRButtonDown(UINT nFlags, CPoint point);\n    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);\n    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);\n    afx_msg void OnNetworkInfo();\n    afx_msg void OnAlwaysOnTop();\n    afx_msg void OnTransparency100();\n    afx_msg void OnTransparency80();\n    afx_msg void OnTransparency60();\n    afx_msg void OnTransparency40();\n    afx_msg void OnClose();\n    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);\n    afx_msg void OnInitMenu(CMenu* pMenu);\n    virtual BOOL PreTranslateMessage(MSG* pMsg);\n    afx_msg void OnLockWindowPos();\n    afx_msg void OnMove(int x, int y);\nprotected:\n    afx_msg LRESULT OnNotifyIcon(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnShowNotifyIcon();\n    afx_msg void OnDestroy();\n    afx_msg void OnShowCpuMemory();\n    afx_msg void OnMousePenetrate();\n    //afx_msg void OnTextColor();\n    afx_msg void OnShowTaskBarWnd();\n    afx_msg void OnAppAbout();\n    afx_msg void OnShowCpuMemory2();\n    afx_msg void OnShowMainWnd();\n    afx_msg void OnChangeSkin();\n    afx_msg LRESULT OnTaskBarCreated(WPARAM wParam, LPARAM lParam);\n    //afx_msg void OnSetFont();\n    afx_msg void OnTrafficHistory();\n    afx_msg void OnMouseMove(UINT nFlags, CPoint point);\n    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);\n    afx_msg void OnOptions();\n    afx_msg void OnOptions2();\nprotected:\n    afx_msg LRESULT OnExitmenuloop(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnChangeNotifyIcon();\n    afx_msg void OnAlowOutOfBorder();\n    afx_msg void OnCheckUpdate();\nprotected:\n    afx_msg LRESULT OnTaskbarMenuPopedUp(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnShowNetSpeed();\n    afx_msg BOOL OnQueryEndSession();\n    afx_msg void OnPaint();\nprotected:\n    afx_msg LRESULT OnDpichanged(WPARAM wParam, LPARAM lParam);\n    afx_msg LRESULT OnTaskbarWndClosed(WPARAM wParam, LPARAM lParam);\n    afx_msg LRESULT OnMonitorInfoUpdated(WPARAM wParam, LPARAM lParam);\n    afx_msg LRESULT OnDisplaychange(WPARAM wParam, LPARAM lParam);\n    afx_msg LRESULT OnReopenTaksbarWnd(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnExitSizeMove();\n    afx_msg void OnPluginManage();\n    afx_msg void OnOpenTaskManager();\nprotected:\n    afx_msg LRESULT OnSettingsApplied(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnDisplaySettings();\n    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);\n    afx_msg void OnRefreshConnectionList();\nprotected:\n    afx_msg LRESULT OnTabletQuerysystemgesturestatus(WPARAM wParam, LPARAM lParam);\npublic:\n    afx_msg void OnPluginOptions();\n    afx_msg void OnPluginDetail();\n    afx_msg void OnPluginOptionsTaksbar();\n    afx_msg void OnPluginDetailTaksbar();\n    afx_msg UINT OnPowerBroadcast(UINT nPowerEvent, LPARAM nEventData);\n    afx_msg void OnColorizationColorChanged(DWORD dwColorizationColor, BOOL bOpacity);\n};\n"
  },
  {
    "path": "TrafficMonitor/UpdateHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"UpdateHelper.h\"\n#include \"SimpleXML.h\"\n#include \"Common.h\"\n\n\nCUpdateHelper::CUpdateHelper()\n{\n}\n\n\nCUpdateHelper::~CUpdateHelper()\n{\n}\n\nvoid CUpdateHelper::SetUpdateSource(UpdateSource update_source)\n{\n    m_update_source = update_source;\n}\n\nbool CUpdateHelper::CheckForUpdate()\n{\n    wstring version_info;\n    //使用GitHub更新源\n    if (m_update_source == UpdateSource::GitHubSource)\n    {\n        if (CCommon::GetURL(L\"https://raw.githubusercontent.com/zhongyang219/TrafficMonitor/master/version_utf8.info\", version_info, true))     //获取版本信息\n        {\n            m_row_data = true;\n        }\n        else if (CCommon::GetURL(L\"https://github.com/zhongyang219/TrafficMonitor/blob/master/version_utf8.info\", version_info, true))      //获取版本信息\n        {\n            m_row_data = false;\n        }\n        else\n        {\n            return false;\n        }\n\n        if (!m_row_data)\n        {\n            size_t index = version_info.find(L\"﻿&lt;version&gt;\");\n            if (index != std::wstring::npos)\n                version_info = version_info.substr(index);\n\n            CString str_version_info = version_info.c_str();\n            str_version_info.Replace(L\"&lt;\", L\"<\");\n            str_version_info.Replace(L\"&gt;\", L\">\");\n\n            version_info = str_version_info;\n        }\n    }\n    //使用Gitee更新源\n    else\n    {\n        if (!CCommon::GetURL(L\"https://gitee.com/zhongyang219/TrafficMonitor/raw/master/version_utf8.info\", version_info, true))     //获取版本信息\n            return false;\n    }\n\n    ParseUpdateInfo(version_info);\n\n    return true;\n}\n\nvoid CUpdateHelper::ParseUpdateInfo(wstring version_info)\n{\n    CSimpleXML version_xml;\n    version_xml.LoadXMLContentDirect(version_info);\n\n    m_version = version_xml.GetNode(L\"version\");\n    wstring str_source_tag = (m_update_source == UpdateSource::GitHubSource ? L\"GitHub\" : L\"Gitee\");\n    wstring str_link_tag, str_link_tag_x64, str_link_tag_arm64ec;\n#ifdef WITHOUT_TEMPERATURE\n    str_link_tag = L\"link_without_temperature\";\n    str_link_tag_x64 = L\"link_without_temperature_x64\";\n    str_link_tag_arm64ec = L\"link_without_temperature_arm64ec\";\n#else\n    str_link_tag = L\"link\";\n    str_link_tag_x64 = L\"link_x64\";\n    str_link_tag_arm64ec = L\"link_arm64ec\";\n#endif\n    m_link64 = version_xml.GetNode(str_link_tag_x64.c_str(), str_source_tag.c_str());\n    m_link = version_xml.GetNode(str_link_tag.c_str(), str_source_tag.c_str());\n    m_link_arm64ec = version_xml.GetNode(str_link_tag_arm64ec.c_str(), str_source_tag.c_str());\n    CString contents_zh_cn = version_xml.GetNode(L\"contents_zh_cn\", L\"update_contents\").c_str();\n    CString contents_en = version_xml.GetNode(L\"contents_en\", L\"update_contents\").c_str();\n    CString contents_zh_tw = version_xml.GetNode(L\"contents_zh_tw\", L\"update_contents\").c_str();\n    contents_zh_cn.Replace(L\"\\\\n\", L\"\\r\\n\");\n    contents_en.Replace(L\"\\\\n\", L\"\\r\\n\");\n    contents_zh_tw.Replace(L\"\\\\n\", L\"\\r\\n\");\n    m_contents_zh_cn = contents_zh_cn;\n    m_contents_en = contents_en;\n    m_contents_zh_tw = contents_zh_tw;\n}\n\nconst std::wstring& CUpdateHelper::GetVersion() const\n{\n    return m_version;\n}\n\nconst std::wstring& CUpdateHelper::GetLink() const\n{\n    return m_link;\n}\n\nconst std::wstring& CUpdateHelper::GetLink64() const\n{\n    return m_link64;\n}\n\nconst std::wstring& CUpdateHelper::GetLinkArm64ec() const\n{\n    return m_link_arm64ec;\n}\n\nconst std::wstring& CUpdateHelper::GetContentsEn() const\n{\n    return m_contents_en;\n}\n\nconst std::wstring& CUpdateHelper::GetContentsZhCn() const\n{\n    return m_contents_zh_cn;\n}\n\nconst std::wstring& CUpdateHelper::GetContentsZhTw() const\n{\n    return m_contents_zh_tw;\n}\n\nbool CUpdateHelper::IsRowData()\n{\n    return m_row_data;\n}\n"
  },
  {
    "path": "TrafficMonitor/UpdateHelper.h",
    "content": "﻿#pragma once\nclass CUpdateHelper\n{\npublic:\n    CUpdateHelper();\n    ~CUpdateHelper();\n\n    enum class UpdateSource\n    {\n        GitHubSource,\n        GiteeSource\n    };\n\n    void SetUpdateSource(UpdateSource update_source);\n\n    bool CheckForUpdate();\n\n    const std::wstring& GetVersion() const;\n    const std::wstring& GetLink() const;\n    const std::wstring& GetLink64() const;\n    const std::wstring& GetLinkArm64ec() const;\n    const std::wstring& GetContentsEn() const;\n    const std::wstring& GetContentsZhCn() const;\n    const std::wstring& GetContentsZhTw() const;\n    bool IsRowData();\n\nprivate:\n    void ParseUpdateInfo(wstring version_info);\n\nprivate:\n    std::wstring m_version;\n    std::wstring m_link;\n    std::wstring m_link64;\n    std::wstring m_link_arm64ec;\n    std::wstring m_contents_en;\n    std::wstring m_contents_zh_cn;\n    std::wstring m_contents_zh_tw;\n    bool m_row_data{ true };\n    UpdateSource m_update_source{ UpdateSource::GitHubSource };\n};\n"
  },
  {
    "path": "TrafficMonitor/WIC.cpp",
    "content": "#include \"stdafx.h\"\n#include \"WIC.h\"\n#include \"TrafficMonitor.h\"\n\nCWICFactory CWICFactory::m_instance;\n\nCWICFactory::CWICFactory()\n{\n#ifndef COMPILE_IN_WIN_XP\n    //ʼm_pWICFactory\n    _hrOleInit = ::OleInitialize(NULL);\n    CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pWICFactory));\n    if (m_pWICFactory == nullptr)\n        CoCreateInstance(CLSID_WICImagingFactory1, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pWICFactory));\n#endif\n}\n\nCWICFactory::~CWICFactory()\n{\n    if (m_pWICFactory)\n    {\n        m_pWICFactory->Release();\n        m_pWICFactory = NULL;\n    }\n\n    if (SUCCEEDED(_hrOleInit))\n    {\n        OleUninitialize();\n    }\n}\n\n\n//////////////////////////////////////////////////////////\n\ntypedef DWORD ARGB;\nstd::map<HICON, HBITMAP> CMenuIcon::m_icon_map;\n\nCMenuIcon::CMenuIcon()\n{\n}\n\nCMenuIcon::~CMenuIcon()\n{\n}\n\nHRESULT CMenuIcon::AddIconToMenuItem(HMENU hmenu, int iMenuItem, BOOL fByPosition, HICON hicon)\n{\n    //Wine²˵ͼ쳣˲Ϊ˵ͼ\n    if (theApp.m_win_version.IsWine())\n        return 0;\n\n#ifndef COMPILE_IN_WIN_XP\n    HBITMAP hbmp{};\n    HRESULT hr = GetBitmapByIcon(hicon, hbmp);\n\n    if (SUCCEEDED(hr))\n    {\n        hr = AddBitmapToMenuItem(hmenu, iMenuItem, fByPosition, hbmp);\n    }\n\n    return hr;\n#else\n    return 0;\n#endif // !COMPILE_IN_WIN_XP\n}\n\nHRESULT CMenuIcon::AddBitmapToMenuItem(HMENU hmenu, int iItem, BOOL fByPosition, HBITMAP hbmp)\n{\n    HRESULT hr = E_FAIL;\n\n    MENUITEMINFO mii = { sizeof(mii) };\n    mii.fMask = MIIM_BITMAP;\n    mii.hbmpItem = hbmp;\n    if (SetMenuItemInfo(hmenu, iItem, fByPosition, &mii))\n    {\n        hr = S_OK;\n    }\n\n    return hr;\n}\n\nvoid CMenuIcon::InitBitmapInfo(BITMAPINFO * pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp)\n{\n    ZeroMemory(pbmi, cbInfo);\n    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n    pbmi->bmiHeader.biPlanes = 1;\n    pbmi->bmiHeader.biCompression = BI_RGB;\n\n    pbmi->bmiHeader.biWidth = cx;\n    pbmi->bmiHeader.biHeight = cy;\n    pbmi->bmiHeader.biBitCount = bpp;\n}\n\nHRESULT CMenuIcon::Create32BitHBITMAP(HDC hdc, const SIZE * psize, void ** ppvBits, HBITMAP * phBmp)\n{\n    *phBmp = NULL;\n\n    BITMAPINFO bmi;\n    InitBitmapInfo(&bmi, sizeof(bmi), psize->cx, psize->cy, 32);\n\n    HDC hdcUsed = hdc ? hdc : GetDC(NULL);\n    if (hdcUsed)\n    {\n        *phBmp = CreateDIBSection(hdcUsed, &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0);\n        if (hdc != hdcUsed)\n        {\n            ReleaseDC(NULL, hdcUsed);\n        }\n    }\n    return (NULL == *phBmp) ? E_OUTOFMEMORY : S_OK;\n}\n\nHRESULT CMenuIcon::GetBitmapByIcon(HICON hicon, HBITMAP& hbmp)\n{\n    auto iter = m_icon_map.find(hicon);\n    if (iter != m_icon_map.end())\n    {\n        hbmp = iter->second;\n        return ERROR_SUCCESS;\n    }\n    else\n    {\n        if (CWICFactory::GetWIC() == nullptr)\n            return 0;\n        hbmp = NULL;\n\n        IWICBitmap* pBitmap;\n        HRESULT hr = CWICFactory::GetWIC()->CreateBitmapFromHICON(hicon, &pBitmap);\n        if (SUCCEEDED(hr))\n        {\n            IWICFormatConverter* pConverter;\n            hr = CWICFactory::GetWIC()->CreateFormatConverter(&pConverter);\n            if (SUCCEEDED(hr))\n            {\n                hr = pConverter->Initialize(pBitmap, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeCustom);\n                if (SUCCEEDED(hr))\n                {\n                    UINT cx, cy;\n                    hr = pConverter->GetSize(&cx, &cy);\n                    if (SUCCEEDED(hr))\n                    {\n                        const SIZE sizIcon = { (int)cx, -(int)cy };\n                        BYTE* pbBuffer;\n                        hr = Create32BitHBITMAP(NULL, &sizIcon, reinterpret_cast<void**>(&pbBuffer), &hbmp);\n                        if (SUCCEEDED(hr))\n                        {\n                            const UINT cbStride = cx * sizeof(ARGB);\n                            const UINT cbBuffer = cy * cbStride;\n                            hr = pConverter->CopyPixels(NULL, cbStride, cbBuffer, pbBuffer);\n                        }\n                    }\n                }\n\n                pConverter->Release();\n            }\n\n            pBitmap->Release();\n        }\n        if (SUCCEEDED(hr))\n        {\n            m_icon_map[hicon] = hbmp;\n        }\n        if (FAILED(hr))\n        {\n            DeleteObject(hbmp);\n            hbmp = NULL;\n        }\n        return hr;\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/WIC.h",
    "content": "//ʹ Windows ӳWICͼ꣨HICONתΪ͸ȵPARGB32λͼӵ˵\n//https://docs.microsoft.com/en-us/previous-versions/bb757020(v=msdn.10)\n\n#pragma once\n#include \"HResultException.h\"\n\nclass CWICFactory\n{\npublic:\n    ~CWICFactory();\n    static IWICImagingFactory* GetWIC() { return m_instance.m_pWICFactory; }\n\nprivate:\n    HRESULT _hrOleInit{};\n    IWICImagingFactory *m_pWICFactory{};\n\n    static CWICFactory m_instance;      //CWICFactoryΨһĶ\n\nprivate:\n    CWICFactory();\n};\n\nclass CMenuIcon\n{\npublic:\n    CMenuIcon();\n    ~CMenuIcon();\n\n    //һ˵ͼ\n    static HRESULT AddIconToMenuItem(HMENU hmenu, int iMenuItem, BOOL fByPosition, HICON hicon);\n\nprivate:\n    static HRESULT AddBitmapToMenuItem(HMENU hmenu, int iItem, BOOL fByPosition, HBITMAP hbmp);\n    static void InitBitmapInfo(__out_bcount(cbInfo) BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp);\n    static HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, __deref_opt_out void **ppvBits, __out HBITMAP* phBmp);\n    static HRESULT GetBitmapByIcon(HICON hicon, HBITMAP& hbmp);\n\n    static std::map<HICON, HBITMAP> m_icon_map;\n};\n\nclass CWICException final : public CHResultException\n{\n    using CHResultException::CHResultException;\n};\n"
  },
  {
    "path": "TrafficMonitor/Win11TaskbarDlg.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"Win11TaskbarDlg.h\"\n#include \"WindowsSettingHelper.h\"\n\nvoid CWin11TaskbarDlg::AdjustTaskbarWndPos(bool force_adjust)\n{\n    ::GetWindowRect(m_hNotify, m_rcNotify);\n    ::GetWindowRect(m_hStart, m_rcStart);\n    m_rcStart.MoveToXY(m_rcStart.left - m_rcTaskbar.left, m_rcStart.top - m_rcTaskbar.top);\n\n    //设置窗口大小\n    m_rect.right = m_rect.left + m_window_width;\n    m_rect.bottom = m_rect.top + m_window_height;\n    if (force_adjust || m_rcNotify.Width() != m_last_notify_width || m_rcStart.left != m_last_start_pos)   //如果最小化窗口的宽度改变了，重新设置任务栏窗口的位置\n    {\n        m_last_notify_width = m_rcNotify.Width();\n        m_last_start_pos = m_rcStart.left;\n        //任务窗口显示在右侧时，或者Windows11下任务栏左对齐时\n        //（Windows11下，如果任务栏设置为左对齐，即使在“任务栏窗口设置”中设置了任务窗口显示在左边，窗口仍然显示在右边）\n        if (!theApp.m_taskbar_data.tbar_wnd_on_left || !CWindowsSettingHelper::IsTaskbarCenterAlign())\n        {\n            ////靠近任务栏图标的情况\n            //if (theApp.m_taskbar_data.tbar_wnd_snap && IsTaskbarCloseToIconEnable(theApp.m_taskbar_data.tbar_wnd_on_left))\n            //{\n            //    m_rect.MoveToX(m_rcMin.right + 2);\n            //}\n            ////靠近通知区的情况\n            //else\n            //{\n            //通知区窗口的水平位置\n            int notify_x_pos = m_rcNotify.left;\n            //没有获取到通知区位置的情况\n            if (notify_x_pos == 0)\n            {\n                //Win11副屏没有通知区窗口，这里使用固定的值（88像素的系统时间区域）\n                if (m_is_secondary_display)\n                    notify_x_pos = m_rcTaskbar.Width() - DPI(88);\n                //如果不是副屏，但是仍然没有获取到通知区域的位置，使用配置文件中taskbar_right_space_win11指定的值\n                else\n                    notify_x_pos = m_rcTaskbar.Width() - DPI(theApp.m_taskbar_data.taskbar_right_space_win11);\n            }\n            //如果显示了小组件，并且任务栏靠左显示，则留出小组件的位置\n            if (theApp.m_taskbar_data.avoid_overlap_with_widgets && CWindowsSettingHelper::IsTaskbarWidgetsBtnShown() && !CWindowsSettingHelper::IsTaskbarCenterAlign())\n                m_rect.MoveToX(notify_x_pos - m_rect.Width() + 2 - DPI(theApp.m_taskbar_data.taskbar_left_space_win11));\n            else\n                m_rect.MoveToX(notify_x_pos - m_rect.Width() + 2);\n            //}\n        }\n        //任务栏窗口显示在左侧时\n        else\n        {\n            //靠近“开始”按钮\n            if (theApp.m_taskbar_data.tbar_wnd_snap)\n            {\n                m_rect.MoveToX(m_rcStart.left - m_rect.Width() - 2);\n            }\n            //靠近最左侧\n            else\n            {\n                if (CWindowsSettingHelper::IsTaskbarWidgetsBtnShown())\n                    m_rect.MoveToX(2 + DPI(theApp.m_taskbar_data.taskbar_left_space_win11));\n                else\n                    m_rect.MoveToX(2);\n            }\n        }\n        //水平偏移\n        m_rect.MoveToX(m_rect.left + DPI(theApp.m_taskbar_data.window_offset_left));\n        ////确保水平方向不超出屏幕边界\n        //if (m_rect.left < 0)\n        //    m_rect.MoveToX(0);\n        //if (m_rcTaskbar.Width() > m_rect.Width() && m_rect.right > m_rcTaskbar.Width())\n        //    m_rect.MoveToX(m_rcTaskbar.Width() - m_rect.Width());\n\n        //设置任务栏窗口的垂直位置\n        //注：这里加上(m_rcTaskbar.Height() - rcStart.Height())用于修正Windows11 build 22621版本后触屏设备任务栏窗口位置不正确的问题。\n        //在这种情况下m_rcTaskbar的高度要大于m_rcBar的高度，正常情况下，它们的高度相同\n        //但是当任务栏上没有任何图标时，m_rcBar的高度会变为0，因此使用rcStart代替\n        m_rect.MoveToY((m_rcStart.Height() - m_rect.Height()) / 2 + (m_rcTaskbar.Height() - m_rcStart.Height()) + DPI(theApp.m_taskbar_data.window_offset_top));\n        ////确保垂直方向不超出屏幕边界\n        //if (m_rect.top < 0)\n        //    m_rect.MoveToY(0);\n        //if (m_rcTaskbar.Height() > m_rect.Height() && m_rect.bottom > m_rcTaskbar.Height())\n        //    m_rect.MoveToY(m_rcTaskbar.Height() - m_rect.Height());\n\n        MoveWindow(m_rect);\n    }\n}\n\nvoid CWin11TaskbarDlg::InitTaskbarWnd()\n{\n    m_hNotify = ::FindWindowEx(m_hTaskbar, 0, L\"TrayNotifyWnd\", NULL);\n    m_hStart = ::FindWindowEx(m_hTaskbar, nullptr, L\"Start\", NULL);\n    ::GetWindowRect(m_hNotify, m_rcNotify);\n}\n\nvoid CWin11TaskbarDlg::ResetTaskbarPos()\n{\n}\n\nHWND CWin11TaskbarDlg::GetParentHwnd()\n{\n    return m_hTaskbar;\n}\n\nvoid CWin11TaskbarDlg::CheckTaskbarOnTopOrBottom()\n{\n    m_taskbar_on_top_or_bottom = true;\n}\n"
  },
  {
    "path": "TrafficMonitor/Win11TaskbarDlg.h",
    "content": "﻿#pragma once\n#include \"TaskBarDlg.h\"\nclass CWin11TaskbarDlg :\n    public CTaskBarDlg\n{\npublic:\n\nprivate:\n    // 通过 CTaskBarDlg 继承\n    void InitTaskbarWnd() override;\n    virtual void AdjustTaskbarWndPos(bool force_adjust) override;\n    void ResetTaskbarPos() override;\n    virtual HWND GetParentHwnd() override;\n\n    HWND m_hNotify;     //任务栏通知区域的句柄\n    HWND m_hStart;      //开始按钮的句柄\n    CRect m_rcNotify;   //任务栏通知区域的矩形区域\n    CRect m_rcStart;     //开始按钮的矩形区域\n    int m_last_notify_width{};\n    int m_last_start_pos{};\n\n    // 通过 CTaskBarDlg 继承\n    void CheckTaskbarOnTopOrBottom() override;\n\n};\n\n"
  },
  {
    "path": "TrafficMonitor/Win11TaskbarSettingDlg.cpp",
    "content": "﻿// Win11TaskbarSettingDlg.cpp: 实现文件\n//\n\n#include \"stdafx.h\"\n#include \"TrafficMonitor.h\"\n#include \"afxdialogex.h\"\n#include \"Win11TaskbarSettingDlg.h\"\n#include \"TaskBarDlg.h\"\n#include \"WindowsSettingHelper.h\"\n\n\n// CWin11TaskbarSettingDlg 对话框\n\nIMPLEMENT_DYNAMIC(CWin11TaskbarSettingDlg, CBaseDialog)\n\nCWin11TaskbarSettingDlg::CWin11TaskbarSettingDlg(TaskBarSettingData& data, CWnd* pParent /*=nullptr*/)\n\t: CBaseDialog(IDD_WIN11_TASKBAR_SETTING_DLG, pParent)\n    , m_data(data)\n{\n\n}\n\nCWin11TaskbarSettingDlg::~CWin11TaskbarSettingDlg()\n{\n}\n\nvoid CWin11TaskbarSettingDlg::DoDataExchange(CDataExchange* pDX)\n{\n    DDX_Control(pDX, IDC_WINDOW_OFFSET_TOP_EDIT, m_window_offset_top_edit);\n    DDX_Control(pDX, IDC_WINDOW_OFFSET_LEFT_EDIT, m_window_offset_left_edit);\n    CBaseDialog::DoDataExchange(pDX);\n    DDX_Control(pDX, IDC_WIDTET_WIDTH_EDIT, m_widgets_width_edit);\n}\n\nCString CWin11TaskbarSettingDlg::GetDialogName() const\n{\n    return _T(\"Win11TaskbarSettingDlg\");\n}\n\nbool CWin11TaskbarSettingDlg::InitializeControls()\n{\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_VERTICAL_OFFSET_STATIC },\n        { CtrlTextInfo::L3, IDC_WINDOW_OFFSET_TOP_EDIT },\n        { CtrlTextInfo::L2, IDC_PIXEL_STATIC },\n        { CtrlTextInfo::L4, IDC_HORIZONTAL_OFFSET_STATIC },\n        { CtrlTextInfo::L3, IDC_WINDOW_OFFSET_LEFT_EDIT },\n        { CtrlTextInfo::L2, IDC_PIXEL_STATIC1 },\n        });\n    RepositionTextBasedControls({\n        { CtrlTextInfo::L4, IDC_WIDGET_WIDTH_STATIC },\n        { CtrlTextInfo::L3, IDC_WIDTET_WIDTH_EDIT },\n        { CtrlTextInfo::L2, IDC_PIXEL_STATIC2 },\n        });\n\n    return true;\n}\n\nvoid CWin11TaskbarSettingDlg::EnableDlgCtrl(UINT id, bool enable)\n{\n    CWnd* pCtrl = GetDlgItem(id);\n    if (pCtrl != nullptr)\n        pCtrl->EnableWindow(enable);\n}\n\n\nBEGIN_MESSAGE_MAP(CWin11TaskbarSettingDlg, CBaseDialog)\n    ON_BN_CLICKED(IDC_RESTORE_DEFAULT_BUTTON, &CWin11TaskbarSettingDlg::OnBnClickedRestoreDefaultButton)\nEND_MESSAGE_MAP()\n\n\n// CWin11TaskbarSettingDlg 消息处理程序\n\n\nBOOL CWin11TaskbarSettingDlg::OnInitDialog()\n{\n    CBaseDialog::OnInitDialog();\n    SetIcon(theApp.GetMenuIcon(IDI_TASKBAR_WINDOW), FALSE);\n\n    EnableDlgCtrl(IDC_TASKBAR_WND_SNAP_CHECK, CTaskBarDlg::IsTaskbarCloseToIconEnable(m_data.tbar_wnd_on_left));\n    CheckDlgButton(IDC_TASKBAR_WND_SNAP_CHECK, m_data.tbar_wnd_snap);\n    m_window_offset_top_edit.SetRange(-20, 20);\n    m_window_offset_top_edit.SetValue(m_data.window_offset_top);\n    m_window_offset_left_edit.SetRange(-800, 800);\n    m_window_offset_left_edit.SetValue(m_data.window_offset_left);\n    CheckDlgButton(IDC_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK, m_data.avoid_overlap_with_widgets);\n    //EnableDlgCtrl(IDC_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK, CWindowsSettingHelper::IsTaskbarWidgetsBtnShown());\n    m_widgets_width_edit.SetRange(0, 300);\n    m_widgets_width_edit.SetValue(m_data.taskbar_left_space_win11);\n    //m_widgets_width_edit.EnableWindow(CWindowsSettingHelper::IsTaskbarWidgetsBtnShown());\n\n    return TRUE;  // return TRUE unless you set the focus to a control\n    // 异常: OCX 属性页应返回 FALSE\n}\n\n\nvoid CWin11TaskbarSettingDlg::OnOK()\n{\n    m_data.tbar_wnd_snap = (IsDlgButtonChecked(IDC_TASKBAR_WND_SNAP_CHECK) != 0);\n\n    m_data.window_offset_top = m_window_offset_top_edit.GetValue();\n    m_data.ValidWindowOffsetTop();\n    m_data.window_offset_left = m_window_offset_left_edit.GetValue();\n    m_data.ValidWindowOffsetLeft();\n\n    m_data.avoid_overlap_with_widgets = (IsDlgButtonChecked(IDC_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK) != 0);\n\n    m_data.taskbar_left_space_win11 = m_widgets_width_edit.GetValue();\n    if (m_data.taskbar_left_space_win11 < 0)\n        m_data.taskbar_left_space_win11 = 0;\n    if (m_data.taskbar_left_space_win11 > 300)\n        m_data.taskbar_left_space_win11 = 300;\n\n    CBaseDialog::OnOK();\n}\n\n\nvoid CWin11TaskbarSettingDlg::OnBnClickedRestoreDefaultButton()\n{\n    m_window_offset_top_edit.SetValue(0);\n    m_window_offset_left_edit.SetValue(0);\n    m_widgets_width_edit.SetValue(160);\n}\n"
  },
  {
    "path": "TrafficMonitor/Win11TaskbarSettingDlg.h",
    "content": "﻿#pragma once\n#include \"afxdialogex.h\"\n#include \"SpinEdit.h\"\n#include \"BaseDialog.h\"\n\n// CWin11TaskbarSettingDlg 对话框\n\nclass CWin11TaskbarSettingDlg : public CBaseDialog\n{\n\tDECLARE_DYNAMIC(CWin11TaskbarSettingDlg)\n\npublic:\n\tCWin11TaskbarSettingDlg(TaskBarSettingData& data, CWnd* pParent = nullptr);   // 标准构造函数\n\tvirtual ~CWin11TaskbarSettingDlg();\n\n// 对话框数据\n#ifdef AFX_DESIGN_TIME\n\tenum { IDD = IDD_WIN11_TASKBAR_SETTING_DLG };\n#endif\n\nprivate:\n    TaskBarSettingData& m_data;\n    CSpinEdit m_window_offset_top_edit;\n    CSpinEdit m_window_offset_left_edit;\n    CSpinEdit m_widgets_width_edit;\n\nprotected:\n    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持\n    virtual CString GetDialogName() const override;\n    virtual bool InitializeControls() override;\n\n    void EnableDlgCtrl(UINT id, bool enable);\n\n\tDECLARE_MESSAGE_MAP()\npublic:\n    virtual BOOL OnInitDialog();\n    virtual void OnOK();\n    afx_msg void OnBnClickedRestoreDefaultButton();\n};\n"
  },
  {
    "path": "TrafficMonitor/WinVersionHelper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"WinVersionHelper.h\"\n#include \"WindowsSettingHelper.h\"\n\n\nCWinVersionHelper::CWinVersionHelper()\n{\n\tDWORD dwMajorVer{}, dwMinorVer{}, dwBuildNumber{};\n\tHMODULE hModNtdll{};\n\tif (hModNtdll = ::LoadLibraryW(L\"ntdll.dll\"))\n\t{\n\t\ttypedef void (WINAPI *pfRTLGETNTVERSIONNUMBERS)(DWORD*, DWORD*, DWORD*);\n\t\tpfRTLGETNTVERSIONNUMBERS pfRtlGetNtVersionNumbers;\n\t\tpfRtlGetNtVersionNumbers = (pfRTLGETNTVERSIONNUMBERS)::GetProcAddress(hModNtdll, \"RtlGetNtVersionNumbers\");\n\t\tif (pfRtlGetNtVersionNumbers)\n\t\t{\n\t\t\tpfRtlGetNtVersionNumbers(&dwMajorVer, &dwMinorVer, &dwBuildNumber);\n\t\t\tdwBuildNumber &= 0x0ffff;\n\t\t}\n\n\t\t//判断是否在Wine环境中\n\t\tFARPROC pProc = GetProcAddress(hModNtdll, \"wine_get_version\");\n\t\tif (pProc != NULL)\n\t\t{\n\t\t\tm_is_wine = true;\n\t\t}\n\n\t\t::FreeLibrary(hModNtdll);\n\t\thModNtdll = NULL;\n\t}\n\tm_major_version = dwMajorVer;\n\tm_minor_version = dwMinorVer;\n\tm_build_number = dwBuildNumber;\n\n    CWindowsSettingHelper::CheckWindows10LightTheme();\n}\n\n\nCWinVersionHelper::~CWinVersionHelper()\n{\n}\n\nbool CWinVersionHelper::IsWindows11OrLater() const\n{\n\tif (m_major_version > 10)\n\t\treturn true;\n\telse if (m_major_version == 10 && m_minor_version > 0)\n\t\treturn true;\n\telse if (m_major_version == 10 && m_minor_version == 0 && m_build_number >= 21996)\n\t\treturn true;\n\telse return false;\n}\n\nbool CWinVersionHelper::IsWindows10FallCreatorOrLater() const\n{\n\tif (m_major_version > 10)\n\t\treturn true;\n\telse if (m_major_version == 10 && m_minor_version > 0)\n\t\treturn true;\n\telse if (m_major_version == 10 && m_minor_version == 0 && m_build_number >= 16299)\n\t\treturn true;\n\telse return false;\n}\n\nbool CWinVersionHelper::IsWindows7() const\n{\n\treturn (m_major_version == 6 && m_minor_version == 1);\n}\n\nbool CWinVersionHelper::IsWindows8Or8point1() const\n{\n\treturn (m_major_version == 6 && m_minor_version > 1);\n}\n\nbool CWinVersionHelper::IsWindows8Point1OrLater() const\n{\n\tif (m_major_version > 6)\n    {\n        return true;\n    }\n    else if (m_major_version == 6 && m_minor_version >= 3)\n    {\n        return true;\n    }\n    return false;\n}\n\nbool CWinVersionHelper::IsWindows8OrLater() const\n{\n    if (m_major_version > 6)\n        return true;\n    else if (m_major_version == 6 && m_minor_version >= 2)\n        return true;\n    else return false;\n}\n\nbool CWinVersionHelper::IsWindows10OrLater() const\n{\n    return m_major_version >= 10;\n}\n\nbool CWinVersionHelper::IsWine() const\n{\n\treturn m_is_wine;\n}\n"
  },
  {
    "path": "TrafficMonitor/WinVersionHelper.h",
    "content": "﻿#pragma once\nclass CWinVersionHelper\n{\npublic:\n\tCWinVersionHelper();\n\t~CWinVersionHelper();\n\n\tbool IsWindows11OrLater() const;\t\t\t//判断当前Windows版本是否为Win11或更新的版本\n\tbool IsWindows10FallCreatorOrLater() const;\t\t//判断当前Windows版本是否为Win10秋季创意者更新或更新的版本\n\tbool IsWindows7() const;\t\t\t\t\t//判断Windows版本是否为Windows7\n\tbool IsWindows8Or8point1() const;\t\t\t//判断Windows版本是否为Windows8或Windows8.1\n    bool IsWindows8Point1OrLater() const;       //判断Windows版本是否大于等于Windows8.1\n    bool IsWindows8OrLater() const;\n    bool IsWindows10OrLater() const;\n\tbool IsWine() const;\t\t\t\t\t\t//判断是否在Wine环境下\n\n\tint GetMajorVersion() const { return m_major_version; }\n\tint GetMinorVersion() const { return m_minor_version; }\n\tint GetBuildNumber() const { return m_build_number; }\nprotected:\n\tint m_major_version{};\n\tint m_minor_version{};\n\tint m_build_number{};\n\tbool m_is_wine{};\n};\n"
  },
  {
    "path": "TrafficMonitor/WindowsSettingHelper.cpp",
    "content": "#include \"stdafx.h\"\n#include \"WindowsSettingHelper.h\"\n#include \"TrafficMonitor.h\"\n\nbool CWindowsSettingHelper::m_light_theme{};\nbool CWindowsSettingHelper::IsWindows10LightTheme()\n{\n    return m_light_theme;\n}\n\nvoid CWindowsSettingHelper::CheckWindows10LightTheme()\n{\n    if (theApp.m_win_version.IsWindows10OrLater())\n    {\n        HKEY hKey;\n        DWORD dwThemeData(0);\n        LONG lRes = RegOpenKeyExW(HKEY_CURRENT_USER, L\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Themes\\\\Personalize\", 0, KEY_READ, &hKey);\n        if (lRes == ERROR_SUCCESS) {\n            GetDWORDRegKeyData(hKey, L\"SystemUsesLightTheme\", dwThemeData);\n            m_light_theme = (dwThemeData != 0);\n        }\n        else\n        {\n            m_light_theme = false;\n        }\n        RegCloseKey(hKey);\n    }\n    else\n    {\n        m_light_theme = false;\n    }\n}\n\nbool CWindowsSettingHelper::IsDotNetFramework4Point5Installed()\n{\n    DWORD netFramewordRelease{};\n    if (!GetDWORDRegKeyData(HKEY_LOCAL_MACHINE, L\"Software\\\\Microsoft\\\\NET Framework Setup\\\\NDP\\\\v4\\\\Full\", L\"Release\", netFramewordRelease))\n        return false;\n    return netFramewordRelease >= 379893;\n}\n\nbool CWindowsSettingHelper::IsTaskbarShowingInAllDisplays()\n{\n    DWORD data{};\n    if (!GetDWORDRegKeyData(HKEY_CURRENT_USER, L\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Advanced\", L\"MMTaskbarEnabled\", data))\n        return true;\n    return data != 0;\n}\n\nbool CWindowsSettingHelper::IsTaskbarWidgetsBtnShown()\n{\n    if (!theApp.m_taskbar_data.is_windows_web_experience_detected)\n        return false;\n    DWORD data{};\n    if (!GetDWORDRegKeyData(HKEY_CURRENT_USER, L\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Advanced\", L\"TaskbarDa\", data))\n        return true;\n    return data != 0;\n}\n\nbool CWindowsSettingHelper::IsTaskbarCenterAlign()\n{\n    DWORD data{};\n    if (!GetDWORDRegKeyData(HKEY_CURRENT_USER, L\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\Advanced\", L\"TaskbarAl\", data))\n        return true;\n    return data != 0;\n}\n\nLONG CWindowsSettingHelper::GetDWORDRegKeyData(HKEY hKey, const wstring& strValueName, DWORD& dwValueData)\n{\n    DWORD dwBufferSize(sizeof(DWORD));\n    DWORD dwResult(0);\n    LONG lError = ::RegQueryValueExW(hKey, strValueName.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&dwResult), &dwBufferSize);\n    if (lError == ERROR_SUCCESS)\n        dwValueData = dwResult;\n    return lError;\n}\n\nbool CWindowsSettingHelper::GetDWORDRegKeyData(HKEY keyParent, const wstring& strKeyName, const wstring& strValueName, DWORD& dwValueData)\n{\n    CRegKey key;\n    if (key.Open(keyParent, strKeyName.c_str(), KEY_READ) != ERROR_SUCCESS)\n        return false;\n    return (key.QueryDWORDValue(strValueName.c_str(), dwValueData) == ERROR_SUCCESS);\n}\n"
  },
  {
    "path": "TrafficMonitor/WindowsSettingHelper.h",
    "content": "#pragma once\nclass CWindowsSettingHelper\n{\npublic:\n    static bool IsWindows10LightTheme();\t\t\t\t//жWindowsǷΪǳɫ\n    static void CheckWindows10LightTheme();\n    static bool IsDotNetFramework4Point5Installed();\t//жǷװ.Net Framework 4.5 (https://docs.microsoft.com/zh-cn/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed)\n    static bool IsTaskbarShowingInAllDisplays();        //Ƿʾʾ\n\n    //Windows11\n    static bool IsTaskbarWidgetsBtnShown();             //ǷʾˡСť\n    static bool IsTaskbarCenterAlign();                  //Ƿ\n\nprivate:\n    static LONG GetDWORDRegKeyData(HKEY hKey, const wstring& strValueName, DWORD& dwValueData);\n    static bool GetDWORDRegKeyData(HKEY keyParent, const wstring& strKeyName, const wstring& strValueName, DWORD& dwValueData);\n\nprivate:\n    static \tbool m_light_theme;\n};\n\n"
  },
  {
    "path": "TrafficMonitor/WindowsWebExperienceDetector.cpp",
    "content": "#include \"stdafx.h\"\n#include \"WindowsWebExperienceDetector.h\"\n#ifndef DISABLE_WINDOWS_WEB_EXPERIENCE_DETECTOR\n#include <winrt/Windows.Foundation.Collections.h>\n#include <winrt/Windows.ApplicationModel.h>\n#include <winrt/Windows.Management.Deployment.h>\n#include <winrt/Windows.Storage.h>\n#pragma comment(lib, \"RuntimeObject.lib\")\n#endif\n#include \"TrafficMonitor.h\"\n\nbool WindowsWebExperienceDetector::IsDetected() noexcept\n{\n#ifndef DISABLE_WINDOWS_WEB_EXPERIENCE_DETECTOR\n    if (theApp.m_win_version.IsWindows11OrLater())\n    {\n        auto manager = winrt::Windows::Management::Deployment::PackageManager{};\n        auto packages = manager.FindPackagesForUser(\n            {},\n            winrt::hstring{ L\"MicrosoftWindows.Client.WebExperience\" },\n            winrt::hstring{\n                L\"CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US\" });\n        auto result = packages.First().HasCurrent();\n        return result;\n    }\n#endif\n    return false;\n}\n"
  },
  {
    "path": "TrafficMonitor/WindowsWebExperienceDetector.h",
    "content": "#pragma once\n\nclass WindowsWebExperienceDetector\n{\npublic:\n    static bool IsDetected() noexcept;\n};\n"
  },
  {
    "path": "TrafficMonitor/WineTaskbarDlg.cpp",
    "content": "#include \"stdafx.h\"\n#include \"WineTaskbarDlg.h\"\n\nvoid CWineTaskbarDlg::InitTaskbarWnd()\n{\n    SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);\n}\n\nvoid CWineTaskbarDlg::AdjustTaskbarWndPos(bool force_adjust)\n{\n    //ƶ½\n    int screen_width = GetSystemMetrics(SM_CXSCREEN);\n    int screen_height = GetSystemMetrics(SM_CYSCREEN);\n    CRect rect{ m_rect };\n    if (theApp.m_taskbar_data.tbar_wnd_on_left)\n        rect.MoveToXY(0, screen_height - m_rect.Height());\n    else\n        rect.MoveToXY(screen_width - m_rect.Width(), screen_height - m_rect.Height());\n    this->MoveWindow(rect);\n}\n\nvoid CWineTaskbarDlg::ResetTaskbarPos()\n{\n}\n\nvoid CWineTaskbarDlg::CheckTaskbarOnTopOrBottom()\n{\n    m_taskbar_on_top_or_bottom = true;\n}\n\nHWND CWineTaskbarDlg::GetParentHwnd()\n{\n    return GetDesktopWindow()->GetSafeHwnd();\n}\n"
  },
  {
    "path": "TrafficMonitor/WineTaskbarDlg.h",
    "content": "#pragma once\n#include \"TaskBarDlg.h\"\nclass CWineTaskbarDlg :\n    public CTaskBarDlg\n{\nprivate:\n    // ͨ CTaskBarDlg ̳\n    void InitTaskbarWnd() override;\n    void AdjustTaskbarWndPos(bool force_adjust) override;\n    void ResetTaskbarPos() override;\n    void CheckTaskbarOnTopOrBottom() override;\n    HWND GetParentHwnd() override;\n};\n\n"
  },
  {
    "path": "TrafficMonitor/auto_start_helper.cpp",
    "content": "﻿#include \"stdafx.h\"\n#include \"auto_start_helper.h\"\n\n#include <Lmcons.h>\n\n#include <comdef.h>\n#include <taskschd.h>\n#include \"SimpleXML.h\"\n# pragma comment(lib, \"taskschd.lib\")\n\n// Helper macros from wix.\n// TODO: use \"s\" and \"...\" parameters to report errors from these functions.\n#define ExitOnFailure(x, s, ...) \\\n    if (FAILED(x))               \\\n    {                            \\\n        goto LExit;              \\\n    }\n#define ExitWithLastError(x, s, ...)       \\\n    {                                      \\\n        DWORD Dutil_er = ::GetLastError(); \\\n        x = HRESULT_FROM_WIN32(Dutil_er);  \\\n        if (!FAILED(x))                    \\\n        {                                  \\\n            x = E_FAIL;                    \\\n        }                                  \\\n        goto LExit;                        \\\n    }\n#define ExitFunction() \\\n    {                  \\\n        goto LExit;    \\\n    }\n\nconst DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\\' + User Name + '\\0'\nconst DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\\0'\n\nbool create_auto_start_task_for_this_user(bool runElevated)\n{\n    HRESULT hr = S_OK;\n\n    WCHAR username_domain[USERNAME_DOMAIN_LEN];\n    WCHAR username[USERNAME_LEN];\n\n    std::wstring wstrTaskName;\n\n    ITaskService* pService = NULL;\n    ITaskFolder* pTaskFolder = NULL;\n    ITaskDefinition* pTask = NULL;\n    IRegistrationInfo* pRegInfo = NULL;\n    ITaskSettings* pSettings = NULL;\n    ITriggerCollection* pTriggerCollection = NULL;\n    IRegisteredTask* pRegisteredTask = NULL;\n\n    // ------------------------------------------------------\n    // Get the Domain/Username for the trigger.\n    if (!GetEnvironmentVariable(L\"USERNAME\", username, USERNAME_LEN))\n    {\n        ExitWithLastError(hr, \"Getting username failed: %x\", hr);\n    }\n    if (!GetEnvironmentVariable(L\"USERDOMAIN\", username_domain, USERNAME_DOMAIN_LEN))\n    {\n        ExitWithLastError(hr, \"Getting the user's domain failed: %x\", hr);\n    }\n    wcscat_s(username_domain, L\"\\\\\");\n    wcscat_s(username_domain, username);\n\n    // Task Name.\n    wstrTaskName = L\"Autorun for \";\n    wstrTaskName += username;\n\n    // Get the executable path passed to the custom action.\n    WCHAR wszExecutablePath[MAX_PATH];\n    GetModuleFileName(NULL, wszExecutablePath, MAX_PATH);\n\n    // ------------------------------------------------------\n    // Create an instance of the Task Service.\n    hr = CoCreateInstance(CLSID_TaskScheduler,\n                          NULL,\n                          CLSCTX_INPROC_SERVER,\n                          IID_ITaskService,\n                          (void**)&pService);\n    ExitOnFailure(hr, \"Failed to create an instance of ITaskService: %x\", hr);\n\n    // Connect to the task service.\n    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());\n    ExitOnFailure(hr, \"ITaskService::Connect failed: %x\", hr);\n\n    // ------------------------------------------------------\n    // Get the TrafficMonitor task folder. Creates it if it doesn't exist.\n    hr = pService->GetFolder(_bstr_t(L\"\\\\TrafficMonitor\"), &pTaskFolder);\n    if (FAILED(hr))\n    {\n        // Folder doesn't exist. Get the Root folder and create the TrafficMonitor subfolder.\n        ITaskFolder* pRootFolder = NULL;\n        hr = pService->GetFolder(_bstr_t(L\"\\\\\"), &pRootFolder);\n        ExitOnFailure(hr, \"Cannot get Root Folder pointer: %x\", hr);\n        hr = pRootFolder->CreateFolder(_bstr_t(L\"\\\\TrafficMonitor\"), _variant_t(L\"\"), &pTaskFolder);\n        if (FAILED(hr))\n        {\n            pRootFolder->Release();\n            ExitOnFailure(hr, \"Cannot create TrafficMonitor task folder: %x\", hr);\n        }\n    }\n\n    // If the task exists, just enable it.\n    {\n        IRegisteredTask* pExistingRegisteredTask = NULL;\n        hr = pTaskFolder->GetTask(_bstr_t(wstrTaskName.c_str()), &pExistingRegisteredTask);\n        if (SUCCEEDED(hr))\n        {\n            // Task exists, try enabling it.\n            hr = pExistingRegisteredTask->put_Enabled(VARIANT_TRUE);\n            pExistingRegisteredTask->Release();\n            if (SUCCEEDED(hr))\n            {\n                // Function enable. Sounds like a success.\n                ExitFunction();\n            }\n        }\n    }\n\n    // Create the task builder object to create the task.\n    hr = pService->NewTask(0, &pTask);\n    ExitOnFailure(hr, \"Failed to create a task definition: %x\", hr);\n\n    // ------------------------------------------------------\n    // Get the registration info for setting the identification.\n    hr = pTask->get_RegistrationInfo(&pRegInfo);\n    ExitOnFailure(hr, \"Cannot get identification pointer: %x\", hr);\n    hr = pRegInfo->put_Author(_bstr_t(username_domain));\n    ExitOnFailure(hr, \"Cannot put identification info: %x\", hr);\n\n    // ------------------------------------------------------\n    // Create the settings for the task\n    hr = pTask->get_Settings(&pSettings);\n    ExitOnFailure(hr, \"Cannot get settings pointer: %x\", hr);\n\n    hr = pSettings->put_StartWhenAvailable(VARIANT_FALSE);\n    ExitOnFailure(hr, \"Cannot put_StartWhenAvailable setting info: %x\", hr);\n    hr = pSettings->put_StopIfGoingOnBatteries(VARIANT_FALSE);\n    ExitOnFailure(hr, \"Cannot put_StopIfGoingOnBatteries setting info: %x\", hr);\n    hr = pSettings->put_ExecutionTimeLimit(_bstr_t(L\"PT0S\")); //Unlimited\n    ExitOnFailure(hr, \"Cannot put_ExecutionTimeLimit setting info: %x\", hr);\n    hr = pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);\n    ExitOnFailure(hr, \"Cannot put_DisallowStartIfOnBatteries setting info: %x\", hr);\n\n    // ------------------------------------------------------\n    // Get the trigger collection to insert the logon trigger.\n    hr = pTask->get_Triggers(&pTriggerCollection);\n    ExitOnFailure(hr, \"Cannot get trigger collection: %x\", hr);\n\n    // Add the logon trigger to the task.\n    {\n        ITrigger* pTrigger = NULL;\n        ILogonTrigger* pLogonTrigger = NULL;\n        hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);\n        ExitOnFailure(hr, \"Cannot create the trigger: %x\", hr);\n\n        hr = pTrigger->QueryInterface(\n            IID_ILogonTrigger, (void**)&pLogonTrigger);\n        pTrigger->Release();\n        ExitOnFailure(hr, \"QueryInterface call failed for ILogonTrigger: %x\", hr);\n\n        hr = pLogonTrigger->put_Id(_bstr_t(L\"Trigger1\"));\n\n        // Timing issues may make explorer not be started when the task runs.\n        // Add a little delay to mitigate this.\n        hr = pLogonTrigger->put_Delay(_bstr_t(L\"PT03S\"));\n\n        // Define the user. The task will execute when the user logs on.\n        // The specified user must be a user on this computer.\n        hr = pLogonTrigger->put_UserId(_bstr_t(username_domain));\n        pLogonTrigger->Release();\n        ExitOnFailure(hr, \"Cannot add user ID to logon trigger: %x\", hr);\n    }\n\n    // ------------------------------------------------------\n    // Add an Action to the task. This task will execute the path passed to this custom action.\n    {\n        IActionCollection* pActionCollection = NULL;\n        IAction* pAction = NULL;\n        IExecAction* pExecAction = NULL;\n\n        // Get the task action collection pointer.\n        hr = pTask->get_Actions(&pActionCollection);\n        ExitOnFailure(hr, \"Cannot get Action collection pointer: %x\", hr);\n\n        // Create the action, specifying that it is an executable action.\n        hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);\n        pActionCollection->Release();\n        ExitOnFailure(hr, \"Cannot create the action: %x\", hr);\n\n        // QI for the executable task pointer.\n        hr = pAction->QueryInterface(\n            IID_IExecAction, (void**)&pExecAction);\n        pAction->Release();\n        ExitOnFailure(hr, \"QueryInterface call failed for IExecAction: %x\", hr);\n\n        // Set the path of the executable to TrafficMonitor (passed as CustomActionData).\n        hr = pExecAction->put_Path(_bstr_t(wszExecutablePath));\n        pExecAction->Release();\n        ExitOnFailure(hr, \"Cannot set path of executable: %x\", hr);\n    }\n\n    // ------------------------------------------------------\n    // Create the principal for the task\n    {\n        IPrincipal* pPrincipal = NULL;\n        hr = pTask->get_Principal(&pPrincipal);\n        ExitOnFailure(hr, \"Cannot get principal pointer: %x\", hr);\n\n        // Set up principal information:\n        hr = pPrincipal->put_Id(_bstr_t(L\"Principal1\"));\n\n        hr = pPrincipal->put_UserId(_bstr_t(username_domain));\n\n        hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);\n\n        if (runElevated)\n        {\n            hr = pPrincipal->put_RunLevel(_TASK_RUNLEVEL::TASK_RUNLEVEL_HIGHEST);\n        }\n        else\n        {\n            hr = pPrincipal->put_RunLevel(_TASK_RUNLEVEL::TASK_RUNLEVEL_LUA);\n        }\n        pPrincipal->Release();\n        ExitOnFailure(hr, \"Cannot put principal run level: %x\", hr);\n    }\n    // ------------------------------------------------------\n    //  Save the task in the TrafficMonitor folder.\n    {\n        _variant_t SDDL_FULL_ACCESS_FOR_EVERYONE = L\"D:(A;;FA;;;WD)\";\n        hr = pTaskFolder->RegisterTaskDefinition(\n            _bstr_t(wstrTaskName.c_str()),\n            pTask,\n            TASK_CREATE_OR_UPDATE,\n            _variant_t(username_domain),\n            _variant_t(),\n            TASK_LOGON_INTERACTIVE_TOKEN,\n            SDDL_FULL_ACCESS_FOR_EVERYONE,\n            &pRegisteredTask);\n        ExitOnFailure(hr, \"Error saving the Task : %x\", hr);\n    }\n\nLExit:\n    if (pService)\n        pService->Release();\n    if (pTaskFolder)\n        pTaskFolder->Release();\n    if (pTask)\n        pTask->Release();\n    if (pRegInfo)\n        pRegInfo->Release();\n    if (pSettings)\n        pSettings->Release();\n    if (pTriggerCollection)\n        pTriggerCollection->Release();\n    if (pRegisteredTask)\n        pRegisteredTask->Release();\n\n    return (SUCCEEDED(hr));\n}\n\nbool delete_auto_start_task_for_this_user()\n{\n    HRESULT hr = S_OK;\n\n    WCHAR username[USERNAME_LEN];\n    std::wstring wstrTaskName;\n\n    ITaskService* pService = NULL;\n    ITaskFolder* pTaskFolder = NULL;\n\n    // ------------------------------------------------------\n    // Get the Username for the task.\n    if (!GetEnvironmentVariable(L\"USERNAME\", username, USERNAME_LEN))\n    {\n        ExitWithLastError(hr, \"Getting username failed: %x\", hr);\n    }\n\n    // Task Name.\n    wstrTaskName = L\"Autorun for \";\n    wstrTaskName += username;\n\n    // ------------------------------------------------------\n    // Create an instance of the Task Service.\n    hr = CoCreateInstance(CLSID_TaskScheduler,\n                          NULL,\n                          CLSCTX_INPROC_SERVER,\n                          IID_ITaskService,\n                          (void**)&pService);\n    ExitOnFailure(hr, \"Failed to create an instance of ITaskService: %x\", hr);\n\n    // Connect to the task service.\n    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());\n    ExitOnFailure(hr, \"ITaskService::Connect failed: %x\", hr);\n\n    // ------------------------------------------------------\n    // Get the TrafficMonitor task folder.\n    hr = pService->GetFolder(_bstr_t(L\"\\\\TrafficMonitor\"), &pTaskFolder);\n    if (FAILED(hr))\n    {\n        // Folder doesn't exist. No need to disable a non-existing task.\n        hr = S_OK;\n        ExitFunction();\n    }\n\n    // ------------------------------------------------------\n    // If the task exists, disable.\n    {\n        IRegisteredTask* pExistingRegisteredTask = NULL;\n        hr = pTaskFolder->GetTask(_bstr_t(wstrTaskName.c_str()), &pExistingRegisteredTask);\n        if (SUCCEEDED(hr))\n        {\n            // Task exists, try disabling it.\n            hr = pTaskFolder->DeleteTask(_bstr_t(wstrTaskName.c_str()), 0);\n        }\n    }\n\nLExit:\n    if (pService)\n        pService->Release();\n    if (pTaskFolder)\n        pTaskFolder->Release();\n\n    return (SUCCEEDED(hr));\n}\n\nbool is_auto_start_task_active_for_this_user(std::wstring* path)\n{\n    HRESULT hr = S_OK;\n\n    WCHAR username[USERNAME_LEN];\n    std::wstring wstrTaskName;\n\n    ITaskService* pService = NULL;\n    ITaskFolder* pTaskFolder = NULL;\n\n    bool command_path_match{};\n\n    // ------------------------------------------------------\n    // Get the Username for the task.\n    if (!GetEnvironmentVariable(L\"USERNAME\", username, USERNAME_LEN))\n    {\n        ExitWithLastError(hr, \"Getting username failed: %x\", hr);\n    }\n\n    // Task Name.\n    wstrTaskName = L\"Autorun for \";\n    wstrTaskName += username;\n\n    // ------------------------------------------------------\n    // Create an instance of the Task Service.\n    hr = CoCreateInstance(CLSID_TaskScheduler,\n                          NULL,\n                          CLSCTX_INPROC_SERVER,\n                          IID_ITaskService,\n                          (void**)&pService);\n    ExitOnFailure(hr, \"Failed to create an instance of ITaskService: %x\", hr);\n\n    // Connect to the task service.\n    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());\n    ExitOnFailure(hr, \"ITaskService::Connect failed: %x\", hr);\n\n    // ------------------------------------------------------\n    // Get the TrafficMonitor task folder.\n    hr = pService->GetFolder(_bstr_t(L\"\\\\TrafficMonitor\"), &pTaskFolder);\n    ExitOnFailure(hr, \"ITaskFolder doesn't exist: %x\", hr);\n\n    // ------------------------------------------------------\n    // If the task exists, disable.\n    {\n        IRegisteredTask* pExistingRegisteredTask = NULL;\n        hr = pTaskFolder->GetTask(_bstr_t(wstrTaskName.c_str()), &pExistingRegisteredTask);\n        if (SUCCEEDED(hr))\n        {\n            // Task exists, get its value.\n            VARIANT_BOOL is_enabled;\n            hr = pExistingRegisteredTask->get_Enabled(&is_enabled);\n            //判断已存在的任务计划命令的exe文件路径是否为当前exe的路径\n            BSTR xml_buff{};\n            pExistingRegisteredTask->get_Xml(&xml_buff);\n            CSimpleXML xml;\n            xml.LoadXMLContentDirect(xml_buff);\n            std::wstring command_path = xml.GetNode(L\"Command\", L\"Exec\");\n            if (path != nullptr)\n                *path = command_path;\n            WCHAR wszExecutablePath[MAX_PATH];\n            GetModuleFileName(NULL, wszExecutablePath, MAX_PATH);\n            command_path_match = (command_path == wszExecutablePath);\n\n            pExistingRegisteredTask->Release();\n            if (SUCCEEDED(hr))\n            {\n                // Got the value. Return it.\n                hr = (is_enabled == VARIANT_TRUE) ? S_OK : E_FAIL; // Fake success or fail to return the value.\n                ExitFunction();\n            }\n        }\n    }\n\nLExit:\n    if (pService)\n        pService->Release();\n    if (pTaskFolder)\n        pTaskFolder->Release();\n    //delete[] buff;\n\n    return (SUCCEEDED(hr) && command_path_match);\n}\n"
  },
  {
    "path": "TrafficMonitor/auto_start_helper.h",
    "content": "#pragma once\n\nbool is_auto_start_task_active_for_this_user(std::wstring* path);\nbool create_auto_start_task_for_this_user(bool runElevated);\nbool delete_auto_start_task_for_this_user();\n"
  },
  {
    "path": "TrafficMonitor/crashtool.cpp",
    "content": "﻿#include \"StdAfx.h\"\n#include \"crashtool.h\"\n\n#include <strsafe.h>\n#include <DbgHelp.h>\n#include <tchar.h>\n#include \"MessageDlg.h\"\n#include \"Common.h\"\n#include \"TrafficMonitor.h\"\n#include <sstream>\n\n#pragma comment(lib, \"Dbghelp.lib\")\n\nclass CCrashReport\n{\npublic:\n    CCrashReport()\n    {\n        GetAppPath();\n    }\n    ~CCrashReport() {}\npublic:\n    // 生成MiniDump文件\n    void CreateMiniDump(EXCEPTION_POINTERS* pEP)\n    {\n        SYSTEMTIME stLocalTime;\n        ::GetLocalTime(&stLocalTime);\n        TCHAR szDumpFile[MAX_PATH] = {0};\n        ::StringCchPrintf(szDumpFile, _countof(szDumpFile), TEXT(\"%s%04d%02d%02d%02d%02d%02d_%s.dmp\"), m_szDumpFilePath,\n                          stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, m_szModuleFileName);\n\n        HANDLE hDumpFile;\n        hDumpFile = ::CreateFile(szDumpFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);\n        if (INVALID_HANDLE_VALUE == hDumpFile)\n        {\n            return;\n        }\n\n\t\tm_dumpFile = szDumpFile;\n\n        MINIDUMP_EXCEPTION_INFORMATION ExpParam;\n        ExpParam.ThreadId = ::GetCurrentThreadId();\n        ExpParam.ExceptionPointers = pEP;\n        ExpParam.ClientPointers = TRUE;\n\n        // 生成minidump文件\n        BOOL bResult = ::MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &ExpParam, NULL, NULL);\n        ::CloseHandle(hDumpFile);\n    }\n\n    //根据地址获取模块路径\n    std::wstring GetModulePath(DWORD64 address)\n    {\n        // 获取模块信息\n        HMODULE hModule = NULL;\n        if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)address, &hModule)) \n        {\n            TCHAR moduleName[MAX_PATH];\n            if (GetModuleFileName(hModule, moduleName, MAX_PATH))\n            {\n                return moduleName;\n            }\n        }\n        return L\"Unknown Module\";\n    }\n\n    //获取崩溃堆栈信息\n    std::wstring GetStackTrace(EXCEPTION_POINTERS* pExceptionInfo)\n    {\n        std::wstringstream stream;\n\n        // 初始化符号处理\n        if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))\n        {\n            stream << L\"Failed to initialize symbol handler.\\r\\n\";\n            return stream.str();\n        }\n\n        // RAII 确保 SymCleanup 被调用\n        struct SymCleanupHelper {\n            ~SymCleanupHelper() { SymCleanup(GetCurrentProcess()); }\n        } cleanupHelper;\n\n        STACKFRAME64 stackFrame = {};\n        CONTEXT context = *pExceptionInfo->ContextRecord;\n\n        // 初始化堆栈帧\n#if defined _M_IX86\n        DWORD machineType = IMAGE_FILE_MACHINE_I386;\n        stackFrame.AddrPC.Offset = context.Eip;    // x86 使用 EIP\n        stackFrame.AddrFrame.Offset = context.Ebp; // x86 使用 EBP\n        stackFrame.AddrStack.Offset = context.Esp; // x86 使用 ESP\n//#elif defined _M_ARM64EC\n//        DWORD machineType = IMAGE_FILE_MACHINE_ARM64;\n//        stackFrame.AddrPC.Offset = context.Pc;     // ARM64 使用 PC\n//        stackFrame.AddrFrame.Offset = context.Fp;  // ARM64 使用 FP\n//        stackFrame.AddrStack.Offset = context.Sp;  // ARM64 使用 SP\n#else\n        DWORD machineType = IMAGE_FILE_MACHINE_AMD64;\n        stackFrame.AddrPC.Offset = context.Rip;    // x64 使用 RIP\n        stackFrame.AddrFrame.Offset = context.Rbp; // x64 使用 RBP\n        stackFrame.AddrStack.Offset = context.Rsp; // x64 使用 RSP\n#endif\n        stackFrame.AddrPC.Mode = AddrModeFlat;\n        stackFrame.AddrFrame.Mode = AddrModeFlat;\n        stackFrame.AddrStack.Mode = AddrModeFlat;\n\n        // 遍历堆栈帧\n        while (StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {\n            if (stackFrame.AddrPC.Offset == 0) break;\n\n            // 获取符号信息\n            BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];\n            PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;\n            pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);\n            pSymbol->MaxNameLen = MAX_SYM_NAME;\n\n            stream << L\"--------------------------------------\\r\\n\";\n\n            DWORD64 displacement = 0;\n            if (SymFromAddr(GetCurrentProcess(), stackFrame.AddrPC.Offset, &displacement, pSymbol)) {\n                stream << L\"Function: \" << CCommon::AsciiToUnicode(pSymbol->Name) << L\" (Displacement: \" << displacement << L\")\\r\\n\";\n            }\n            else {\n                stream << L\"Unknown Function at address: \" << (void*)stackFrame.AddrPC.Offset << L\"\\r\\n\";\n            }\n\n            std::wstring modulePath = GetModulePath(stackFrame.AddrPC.Offset);\n            if (!modulePath.empty())\n                stream << L\"Module Path: \" << modulePath << L\"\\r\\n\";\n\n            // 获取源代码行信息\n            IMAGEHLP_LINE64 line = {};\n            line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);\n            DWORD lineDisplacement = 0;\n            if (SymGetLineFromAddr64(GetCurrentProcess(), stackFrame.AddrPC.Offset, &lineDisplacement, &line)) {\n                stream << L\"File: \" << CCommon::AsciiToUnicode(line.FileName) << L\" (Line: \" << line.LineNumber << L\")\\r\\n\";\n            }\n        }\n        return stream.str();\n    }\n\n\tvoid ShowCrashInfo(EXCEPTION_POINTERS* pEP)\n\t{\n\t\tCString info = CCommon::LoadTextFormat(IDS_CRASH_INFO, { m_dumpFile });\n\t\tinfo += _T(\"\\r\\n\");\n        //在崩溃信息中调用堆栈\n        std::wstring stack_trace = GetStackTrace(pEP);\n        if (!stack_trace.empty())\n        {\n            info += _T(\"Stack trace:\\r\\n\");\n            info += stack_trace.c_str();\n            info += _T(\"\\r\\n\");\n        }\n\t\tinfo += theApp.GetSystemInfoString();\n        //写入日志\n        CString crash_log = info;\n        crash_log.Replace(_T(\"\\r\\n\"), _T(\"\\n\"));\n        crash_log.Replace(_T(\"\\n\\n\"), _T(\"\\n\"));\n        CCommon::WriteLog(crash_log.GetString(), theApp.m_log_path.c_str());\n        //显示崩溃对话框\n        CMessageDlg dlg;\n        dlg.SetWindowTitle(APP_NAME);\n        dlg.SetInfoText(CCommon::LoadText(IDS_ERROR_MESSAGE));\n        dlg.SetMessageText(info);\n        dlg.SetStandarnMessageIcon(CMessageDlg::SI_ERROR);\n        dlg.DoModal();\n\t}\n\nprivate:\n    void GetAppPath()\n    {\n        ZeroMemory(m_szModuleFileName, MAX_PATH);\n        ::GetModuleFileName(NULL, m_szDumpFilePath, _countof(m_szDumpFilePath));\n        for (int nIndex = (int)_tcslen(m_szDumpFilePath); nIndex >= 0; --nIndex)\n        {\n            if (m_szDumpFilePath[nIndex] == TEXT('\\\\'))\n            {\n                ::memmove(m_szModuleFileName, m_szDumpFilePath + nIndex + 1, (int)_tcslen(m_szDumpFilePath));\n                m_szDumpFilePath[nIndex + 1] = 0;\n                break;\n            }\n        }\n        ZeroMemory(m_szDumpFilePath, MAX_PATH);\n        if (!::GetTempPath(MAX_PATH, m_szDumpFilePath))\n        {\n            m_szDumpFilePath[0] = _T('C');\n            m_szDumpFilePath[1] = _T(':');\n            m_szDumpFilePath[2] = _T('\\\\');\n            m_szDumpFilePath[3] = _T('\\0');\n        }\n    }\nprivate:\n    wchar_t m_szDumpFilePath[MAX_PATH];\n    wchar_t m_szModuleFileName[MAX_PATH];\n\n\tCString m_dumpFile;\n};\n\nnamespace CRASHREPORT\n{\n    static LONG WINAPI __UnhandledExceptionFilter(PEXCEPTION_POINTERS pEP)\n    {\n        ::SetErrorMode(0); //使用默认的\n        CCrashReport cr;\n        cr.CreateMiniDump(pEP);\n\t\tcr.ShowCrashInfo(pEP);\n        return EXCEPTION_CONTINUE_SEARCH;\n    }\n\n    void StartCrashReport()\n    {\n        ::SetUnhandledExceptionFilter(__UnhandledExceptionFilter);\n    }\n}\n"
  },
  {
    "path": "TrafficMonitor/crashtool.h",
    "content": "#pragma once\n\nnamespace CRASHREPORT\n{\n    /**@brief\n        dmupģʽ\n        󣬵ʱһdumpļļC:\\Users\\<û>\\AppData\\Local\\TempĿ¼\n        ļʽʱ_.exe.dmp\n        \n        20150116174802_CrashShare.exe.dmp\n    */\n    void StartCrashReport();\n}"
  },
  {
    "path": "TrafficMonitor/language/English.ini",
    "content": "﻿[general]\nBCP_47 = \"en-US\"\nDISPLAY_NAME = \"English\"\nTRANSLATOR = \"\"\nTRANSLATOR_URL = \"\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"Check for update failed, please check your network connection!\"\nIDS_CHECK_UPDATE_ERROR = \"Check for update failed and get the wrong information from the remote update file, please contact the author!\"\nIDS_UPDATE_AVLIABLE = \"New version V%s detected, do you want to go to update?\"\nIDS_UPDATE_AVLIABLE2 = \"New version V%s detected, update content: \\r\\n%s\\r\\ndo you want to go to update?\"\nIDS_ALREADY_UPDATED = \"Already updated to the latest version.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"Cannot achieve auto run when Windows start, cannot find the corresponding key in the registry.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"Registry key write failed, may not have permission to access the key!\"\nIDS_AUTORUN_DELETE_FAILED = \"Registry key delete failed, may not have permission to access the key!\"\nIDS_AN_INSTANCE_RUNNING= \"There is already an instance running.\"\nIDS_TRAFFIC_USED_TODAY = \"Traffic used today\"\nIDS_MEMORY_USAGE = \"Memory usage\"\nIDS_CPU_USAGE = \"CPU usage\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Send an e-mail to the author.\"\nIDS_GOTO_GITHUB = \"Go to the page on GitHub for this project.\"\nIDS_DONATE_ATHOUR = \"Donate the author\"\nIDS_UPLOAD = \"Upload\"\nIDS_DOWNLOAD = \"Download\"\nIDS_MEMORY = \"Memory\"\nIDS_UPLOAD_DISP = \"UP\"\nIDS_DOWNLOAD_DISP = \"DN\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"Warning: Unable to save settings, unable to write data to file= \"\"<%file_path%>\"\"! Running this program as an administrator may solve this problem.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"The size of the buffer used to store connection information is not enough, the connection has been reinitialized. (<%cnt%> times has been reinitialized)\"\nIDS_CONNECTION_NUM_CHANGED = \"The connection number change has been detected. The connection has been retrieved. Previous connections: <%before%>, now connections: <%after%>. (<%cnt%> times has been reinitialized)\"\nIDS_CONNECTION_NOT_MATCH = \"An exception may have occurred, the currently selected connection is inconsistent with the expected connection. The connection has been retrieved. (<%cnt%> times has been reinitialized)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"The window is not successfully embedded in the taskbar, it may be blocked by security software or the start menu is not closed, please try restarting explorer. TrafficMonitor will keep trying but stop reminding, error code:\"\nIDS_MEMORY_UDAGE_EXCEED= \"Memory usage has been reached\"\nIDS_NOTIFY = \"Notify\"\nIDS_TODAY_TRAFFIC_EXCEED = \"Traffic used today has been reached\"\nIDS_DATE = \"Date\"\nIDS_TRAFFIC_USED = \"Total traffic\"\nIDS_FIGURE = \"Figure\"\nIDS_DEFAULT_ICON = \"Default Icon\"\nIDS_ICON = \"Icon\"\nIDS_INTERFACE_NAME = \"Interface name\"\nIDS_INTERFACE_DESCRIPTION= \"Interface description\"\nIDS_CONNECTION_TYPE = \"Connection type\"\nIDS_IF_TYPE_OTHER = \"Other type of network\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"Ethernet network\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Token ring network\"\nIDS_IF_TYPE_FDDI = \"Fiber Distributed Data Interface (FDDI) network\"\nIDS_IF_TYPE_PPP = \"PPP network\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"Software loopback network\"\nIDS_IF_TYPE_ATM = \"ATM network\"\nIDS_IF_TYPE_IEEE80211 = \"IEEE 802.11 wireless network\"\nIDS_IF_TYPE_TUNNEL = \"Tunnel type encapsulation network\"\nIDS_IF_TYPE_IEEE1394 = \"IEEE 1394 (Firewire) high performance serial bus network\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"Mobile broadband interface for WiMax devices\"\nIDS_IF_TYPE_WWANPP = \"Mobile broadband interface for GSM-based devices\"\nIDS_IF_TYPE_WWANPP2 = \"Mobile broadband interface for CDMA-based devices\"\nIDS_UNKNOW_CONNECTION = \"Unknow network\"\nIDS_SPEED = \"Speed\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"Adapter physical address\"\nIDS_IP_ADDRESS = \"IP address\"\nIDS_SUBNET_MASK = \"Subnet mask\"\nIDS_DEFAULT_GATEWAY = \"Default gateway\"\nIDS_OPERATIONAL_STATUS = \"Connection status\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"LAN adapter has been disabled\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"WAN adapter that is not connected\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"network cable disconnected or no carrier\"\nIDS_IF_OPER_STATUS_CONNECTING = \"WAN adapter that is in the process of connecting\"\nIDS_IF_OPER_STATUS_CONNECTED = \"WAN adapter that is connected to a remote peer\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"LAN adapters is connected\"\nIDS_UNKNOW_STATUS = \"Unknow status\"\nIDS_BYTES_RECEIVED = \"Bytes received\"\nIDS_BYTES_SENT = \"Bytes sent\"\nIDS_BYTES_RECEIVED_SINCE_START= \"Bytes received since the program start\"\nIDS_BYTES_SENT_SINCE_START= \"Bytes sent since the program start\"\nIDS_PROGRAM_ELAPSED_TIME= \"Program elapsed time\"\nIDS_HOUR_MINUTE_SECOND = \"%d hours, %d minutes, %d seconds\"\nIDS_INTERNET_IP_ADDRESS= \"Internet IP address\"\nIDS_GET_FAILED = \"Get failed\"\nIDS_ITEM = \"Item\"\nIDS_VALUE = \"Value\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"Copy to clipboard failed!\"\nIDS_SKIN_AUTHOUR = \"Skin author:\"\nIDS_SPEED_SHORT_MODE_TIP = \"When checked, the network speed display will be reduced for 1 decimal place, and the unit does not show= \"\"B\"\".\"\nIDS_AUTO = \"Auto\"\nIDS_FIXED_AS = \"Fixed as\"\nIDS_OPEN_CONNECTION_DETIAL= \"Open connection details\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"Open historical traffic statistics\"\nIDS_SHOW_HIDE_MORE_INFO= \"Show/hide more info\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"Show/hide CPU and memory usage\"\nIDS_OPEN_OPTION_SETTINGS= \"Open option settings\"\nIDS_OPEN_TASK_MANAGER = \"Open task manager\"\nIDS_CHANGE_SKIN = \"Change skin\"\nIDS_NONE = \"None\"\nIDS_FONT_SIZE_WARNING = \"The font size must be between %d and %d!\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"Warning: The text color is the same as the background color!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"Warning: The background color is the same as the text color!\"\nIDS_FOLLOWING_SYSTEM = \"Following system\"\nIDS_LANGUAGE_CHANGE_INFO = \"Please restart the application to apply the language setting.\"\nIDS_MAIN_WINDOW_SETTINGS= \"Main Window Settings\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"Taskbar Window Settings\"\nIDS_GENERAL_SETTINGS = \"General Settings\"\nIDS_ACQUIRING = \"Acquiring\"\nIDS_LIST_VIEW = \"List View\"\nIDS_CALENDAR_VIEW = \"Calendar View\"\nIDS_MONDAY = \"Mon\"\nIDS_TUESDAY = \"Tue\"\nIDS_WEDNESDAY = \"Wed\"\nIDS_THURSDAY = \"Thu\"\nIDS_FRIDAY = \"Fri\"\nIDS_SATURDAY = \"Sat\"\nIDS_SUNDAY = \"Sun\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"Current month total traffic:\"\nIDS_TRAFFIC_USED1 = \"Traffic used:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Failed to insert to the taskbar, retry <%cnt%> times. GetLastError(): <%error_code%>.\"\nIDS_NO_CONNECTION = \"No Connection\"\nIDS_CONTACT_TRANSLATOR = \"Contact this translator.\"\nIDS_THANKS_DONORS = \"Thanks to the following donors:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"An error occurred when requesting= \"\"<%1%>\"\", error code: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"When this item is checked, all network interfaces will be displayed in the= \"\"Select Network Connections\"\" list in the right-click menu. It is recommended that you check this item only when needed.\"\nIDS_CFG_DIR_CHANGED_INFO = \"You have changed the location where the configuration and data files saved. It will take effect after restarted. You may need to transfer the configuration and data files to the new location manually.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<Double-click here to acquire.>\"\nIDS_ERROR1 = \"Error\"\nIDS_ERROR_MESSAGE = \"Error Message:\"\nIDS_CRASH_INFO = \"Sorry, the program has crashed. Please restart the program. \\r\\nIf you encounter this problem many times, please try to disable the hardware monitoring function in= \"\"Options\"\" >= \"\"General Settings\"\", and disable all plugins in the= \"\"Plugin Manager\"\" dialog box. \\r\\nIf the problem still exists, please email this file= \"\"<%1%>\"\" to bugreport-zhongyang219@outlook.com to help the author locate the problem. And add the following to the body of the message:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"Acknowledgement\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Are you sure you want to save the current taskbar color setting to= \"\"Preset <%1%>\"\"?\"\nIDS_SPECIFIC_APP = \"Open specified application\"\nIDS_EXE_FILTER = \"Applications|*.exe|Batch files|*.bat||\"\nIDS_PRESET = \"Preset\"\nIDS_LIGHT_MODE = \"Light mode\"\nIDS_AUTO_ADAPT_TIP_INFO= \"This function will automatically switch the color presets when Windows 10 dark/light themes changed. Click the= \"\"Auto Adapt settings\"\" button to configure the preset scheme for automatic switching.\"\nIDS_WITHOUT_TEMPERATURE= \"Lite\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"Mouse penetrate is turned on. If you need to turn off mouse penetrate, locate trafficMonitor icon in the system notification area, click right mouse button, and turn off mouse penetrate in the menu. Click Cancel no longer prompt.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"Historical traffic data loss was detected. The current number of records: <%1%>, <%2%> records were recovered from the backup file.\"\nIDS_LEGEND = \"Legend\"\nIDS_LICENSE_EXPLAIN = \"Please follow the following open source protocol when using the source code of this software.\"\nIDS_LICENSE = \"License\"\nIDS_DAY_VIEW = \"Day view\"\nIDS_MONTH_VIEW = \"Month view\"\nIDS_QUARTER_VIEW = \"Quarter view\"\nIDS_YEAR_VIEW = \"Year view\"\nIDS_LINEAR_SCALE = \"Linear scale\"\nIDS_LOG_SCALE = \"Logarithmic scale\"\nIDS_CPU_TEMPERATURE = \"CPU Temperature\"\nIDS_GPU_TEMPERATURE = \"GPU Temperature\"\nIDS_CPU_FREQ = \"CPU Freq\"\nIDS_HDD_TEMPERATURE = \"Hard Disk Temperature\"\nIDS_MAINBOARD_TEMPERATURE= \"Main Board Temperature\"\nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"HDD\"\nIDS_MAINBOARD_DISP = \"MBD\"\nIDS_CPU_TEMPERATURE_EXCEED= \"CPU temperature has been reached\"\nIDS_GPU_TEMPERATURE_EXCEED= \"GPU temperature has been reached\"\nIDS_HDD_TEMPERATURE_EXCEED= \"Hard disk temperature has been reached\"\nIDS_MBD_TEMPERATURE_EXCEED= \"Main board temperature has been reached\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: A beautiful and easy-to-use local music player for Windows\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: A simple text editor for Windows\"\nIDS_COLOR = \"Color\"\nIDS_COLOR_LABEL = \"Label color\"\nIDS_COLOR_VALUE = \"Value color\"\nIDS_GPU_USAGE = \"GPU usage\"\nIDS_IF_OPER_STATUS_UP = \"Adapter is connected\"\nIDS_IF_OPER_STATUS_DOWN= \"Adapter is not connected\"\nIDS_IF_OPER_STATUS_DORMANT= \"Adapter is connecting\"\nIDS_GOTO_GITEE = \"Go to the page on Gitee for this project.\"\nIDS_USAGE_PERCENTAGE = \"Used Percentage\"\nIDS_MEMORY_USED = \"Memory used\"\nIDS_MEMORY_AVAILABLE = \"Memory available\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \".Net Framework v4.5.2 or higher is not installed in the system. The temperature monitoring function will not be available. Click Cancel to no longer prompt.\"\nIDS_VERSION_UPDATE = \"New version update\"\nIDS_AVREAGE_TEMPERATURE= \"Average Temperature\"\nIDS_HARDWARE_MONITOR_WARNING = \"Warning: You are turning on the hardware monitoring function. Hardware monitoring function can be used to display temperature and GPU usage information. Please read the following carefully before turning on the hardware monitoring function:\\r\\nTrafficMonitor is not a professional hardware monitoring software. It cannot guarantee that hardware information can be obtained on any computer, nor can it guarantee the accuracy of the obtained hardware information.\\r\\nThe hardware monitoring function is implemented by the third library LibreHardwareMonitor. After the hardware monitoring is turned on, some problems may occur in some computers, including but not limited to :\\r\\n* Abnormal CPU and memory usage\\r\\n* Program crash\\r\\n* Computer crush\\r\\nPlease decide to turn on the hardware monitoring function after you are aware of the above risks. \\r\\nDo you really want to turn on the hardware monitoring function?\"\nIDS_HDD_USAGE = \"Hard Disk usage\"\nIDS_FILE_NAME = \"File name\"\nIDS_STATUS = \"Status\"\nIDS_PLUGIN_LOAD_SUCCEED= \"Load succeed\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"Plug-in module load failed, error code: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"Function acquisition failed, error code: <%1%>\"\nIDS_PLUGIN_INFO = \"Plugin details\"\nIDS_NAME = \"Name\"\nIDS_DESCRIPTION = \"Description\"\nIDS_FILE_PATH = \"File path\"\nIDS_ITEM_NUM = \"Displayed items number\"\nIDS_ITEM_NAMES = \"Displayed items names\"\nIDS_AUTHOR = \"Author\"\nIDS_COPYRIGHT = \"Copyright\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"The plug-in does not provide option settings.\"\nIDS_PLUGIN_NAME = \"Plug-in name\"\nIDS_DISABLED = \"Disabled\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Please restart the program to apply this change.\"\nIDS_VERSION = \"Version\"\nIDS_DISP_ITEM_ID = \"Displayed item ID\"\nIDS_PLUGIN_API_VERSION = \"API version\"\nIDS_WEEK_VIEW = \"Weekly view\"\nIDS_WEEK_NUM = \"Week <%1%>\"\nIDS_URL = \"Url\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"The plug-in version is too low.\"\nIDS_MODIFY_PRESET = \"Modify Preset\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"Please select at least one!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"When the= \"\"Automatically adapt to Windows 10 dark/light theme\"\" function is enabled, if this option is checked, when the taskbar window color, background color settings are changed, according to the current Windows dark/light theme, automatically save to the corresponding preset.\"\nIDS_TOTAL_NET_SPEED = \"Total speed\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"Display resource usage graphs on CPU/memory hard disk utilization, temperature information, and plugin items.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"Display net speed indicator on upload, download and total net speed.\"\nIDS_REFRESH_CONNECTION_LIST= \"Refresh connection list\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"Hardware monitoring function failed to initialize, hardware monitoring will not be available!\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Error getting hardware monitoring data!\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"Auto-run mode : Registry\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"Auto-run mode: Task schedule\"\nIDS_PATH = \"Path\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"Set auto-run at start up failed!\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Failed to update the contents of the taskbar window, direct2d rendering has been disabled. Note: the settings window may not update this setting adjustment immediately.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"An error occurred during direct2d rendering and direct2d rendering has been disabled. Note: the settings window may not update this adjustment immediately.\"\nIDS_PLUGIN_OPTIONS = \"Plugin Options\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"Get CPU usage by performance counter failed, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"Primary display\"\nIDS_SECONDARY_DISPLAY = \"Secondary display <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"The system has been restored from hibernation, the connection has been reinitialized. (<%1%> times has been reinitialized.)\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"Update available, latest version: <%1%>\"\nIDS_TRAFFICMONITOR_PLUGIN_NITIFICATION = \"TrafficMonitor Plugin Notification\"\nIDS_SKIN_FILE_ERROR_INFO = \"Skin file parse failed!\"\n\nTXT_OK = \"OK\"\nTXT_CANCEL = \"Cancel\"\nTXT_CLOSE = \"Close\"\nTXT_APPLY = \"Apply\"\n\n; Text used for dialog. (Must be started with \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"About TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>, V<%2%>\"\nTXT_ABOUT_COPYRIGHT = \"Copyright (C) 2017-2025 By ZhongYang\\nLast compiled date: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%> Translator: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"The third-party libraries used in this project:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"The author's other software:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"Contact author\"\nTXT_ABOUT_LICENSE = \"License\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"Acknowledgement\"\nTXT_ABOUT_DONATE = \"Donate\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor is already running.\"\nTXT_EXIT_THE_PROGRAM = \"E&xit the program\"\nTXT_OPEN_OPTION_SETTINGS = \"Open &option settings\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"Show/hide &main window\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"Show/hide &taskbar window\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Auto adapt settings\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Color preset used in dark Windows mode:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Color preset used in light Windows mode:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"Auto-save taskbar window color settings to preset\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Display Text Settings\"\nTXT_RESTORE_DEFAULT = \"Restore &Default for All\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Application Settings\"\nTXT_CHECK_UPDATE = \"Check for update at startup\"\nTXT_CHECK_NOW = \"&Check now\"\nTXT_UPDATE_SOURCE = \"Update source:\"\nTXT_AUTO_RUN_CHECK = \"Auto run when Windows starts\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Reset autorun\"\nTXT_LANGUAGE = \"Language:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"Configuration and data files\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Save to Appdata directory\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Save to the program directory\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Open configuration file &directory\"\nTXT_NOTIFICATION_MESSAGE = \"Notification Message\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"Notify when today traffic has been reached\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"Notify when memory usage has been reached\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"Notify when CPU temperature has been reached\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"Notify when GPU temperature has been reached\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"Notify when Hard disk temperature has been reached\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"Notify when Main board temperature has been reached\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Hardware Monitoring\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"GPU\"\nTXT_HARD_DISK = \"Hard disk\"\nTXT_MAIN_BOARD = \"Main board\"\nTXT_SELECT_HDD_STATIC = \"Select the hard disk to be monitored:\"\nTXT_SELECT_CPU_STATIC = \"Select the CPU temperature to be monitored:\"\nTXT_ADVANCED = \"Advanced\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Show all network connections\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"&Select the connection to monitor...\"\nTXT_CPU_ACQUISITION_METHOD = \"CPU usage acquisition method:\"\nTXT_USE_CPU_TIME_RADIO = \"Based on CPU time\"\nTXT_USE_PDH_RADIO = \"Use the performance counter\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"Use the hardware monitor\"\nTXT_MONITORING_INTERVALS = \"Monitoring intervals:\"\nTXT_MILLISECONDS = \"milliseconds\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"&Restore default\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Plug-in manage...\"\nTXT_DISPLAY = \"Display\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"Show &Notify Icon\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Year:\"\nTXT_MONTH = \"Month:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Historical Traffic Statistics\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"View type:\"\nTXT_FIGURE_VIEW_SCALE = \"Figure view scale:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Change Notify Icon\"\nTXT_SELECT_A_ICON = \"Select an icon:\"\nTXT_PREVIEW = \"Preview\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Auto adapt by Windows 10 dark/light mode\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Main Window Color Settings\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Hide main window when program is running full screen\"\nTXT_COLOR_AND_FONT = \"Color and Font\"\nTXT_FONT = \"Font:\"\nTXT_FONT_SIZE = \"Font size:\"\nTXT_SET_FONT_BUTTON = \"Choose &Font...\"\nTXT_TEXT_COLOR = \"Text color:\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"&Restore skin default\"\nTXT_DISPLAY_TEXT = \"Display Text\"\nTXT_SWITCH_UP_DOWN_CHECK = \"Swap the position of upload and download\"\nTXT_UNIT_SETTINGS = \"Unit Settings\"\nTXT_UNIT_SELECTION = \"Unit selection:\"\nTXT_HIDE_UNIT_CHECK = \"Don't show speed unit\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Short mode for netspeed display\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Don't show percent\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Specify colors for each item\"\nTXT_DOUBLE_CLICK_ACTION = \"Double click action:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Separate value and unit with space\"\nTXT_NETSPEED_UNIT = \"Netspeed unit:\"\nTXT_UNIT_BYTE_RADIO = \"B (Byte)\"\nTXT_UNIT_BIT_RADIO = \"b (bit)\"\nTXT_SHOW_TOOL_TIP_CHK = \"Show mouse tooltip\"\nTXT_EXE_PATH_STATIC = \"Specified application:\"\nTXT_BROWSE_BUTTON = \"&Browse...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Display &Text settings...\"\nTXT_MEMORY_DISPLAY_MODE = \"Memory display mode:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Always on top\"\nTXT_MOUSE_PENETRATE_CHECK = \"Mouse penetrate\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Lock window position\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Allow out of screen boundaries\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Message\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Connection Details\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Option Settings\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Plug-in Manage\"\nTXT_OPTINS_BUTTON = \"&Options...\"\nTXT_PLUGIN_INFO_BUTTON = \"&Details...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Plug-in development guide\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"Download more plug-ins\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Open plugin directory\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Select the connection to monitor\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Display settings\"\nTXT_MOVE_UP_BUTTON = \"Move Up\"\nTXT_MOVE_DOWN_BUTTON = \"Move Down\"\nTXT_RESTORE_DEFAULT_BUTTON = \"Restore &Default\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Skin auto switching settings\"\nTXT_SKIN_IN_DARK_MODE = \"Skin used in dark Windows mode:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Skin used in light Windows mode:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Change Skin\"\nTXT_PREVIEW_GROUP_STATIC = \"Preview\"\nTXT_SELECT_A_SKIN = \"Select a skin\"\nTXT_SKIN_AUTHOR = \"Skin author:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Skin making-up tutorial\"\nTXT_DOWNLOAD_MORE_SKIN = \"Download more skins\"\nTXT_OPEN_SKIN_DIR = \"Open skin directory\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Automatically switch skins according to Windows dark / light color modes.\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Auto switching settings...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"Taskbar window color settings\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Preset\"\nTXT_BACKGROUND_COLOR = \"Background color:\"\nTXT_BACKGROUND_TRANSPARENT = \"Background transparent\"\nTXT_AUTO_SET_BACK_COLOR = \"Automatically set the background color according to the taskbar color\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Auto adapt to Windows 10 dark/light themes\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"Auto Adapt &settings...\"\nTXT_DISPLAY_SETTINGS = \"Display Settings\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"&Display settings...\"\nTXT_SPEED_SHORT_MODE = \"Short mode for netspeed display\"\nTXT_VALUE_RIGHT_ALIGN = \"Align values to the right\"\nTXT_NET_SPEED_DATA_WIDTH = \"Net speed data width:\"\nTXT_CHARACTORS = \"characters\"\nTXT_HORIZONTAL_ARRANGE = \"Horizontal arrange\"\nTXT_ITEM_SPACING = \"Item spacing:\"\nTXT_VERTICAL_MARGIN = \"Vertical Margin:\"\nTXT_PIXELS = \"pixels\"\nTXT_TASKBAR_WINDOW = \"Taskbar window\"\nTXT_TASKBAR_WND_ON_LEFT = \"Taskbar window appears to the left of the taskbar\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"The display to show taskbar window:\"\nTXT_WIN11_SETTINGS_BUTTON = \"Settings related to Windows11\"\nTXT_RESOURCE_USAGE_GRAPH = \"Resource usage graph\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Show resource usage graph\"\nTXT_SHOW_DASHED_BOX = \"Show dashed box\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Show net speed graph\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"The max value of the net speed graph:\"\nTXT_USAGE_GRAPH_COLOR = \"Usage graph color:\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"Following Windows theme color\"\nTXT_GRAPH_DISPLAY_MODE = \"Graph display mode:\"\nTXT_BAR_MODE = \"Bar mode\"\nTXT_PLOT_MODE = \"Plot mode\"\nTXT_RENDERING_SETTINGS = \"Rendering settings\"\nTXT_RENDERING_SETTINGS_NOTE = \"Note: Direct2D rendering is only used when \"\"Background transparent\"\" is checked but \"\"Automatically set the background color according to the taskbar color\"\" is not checked.\"\nTXT_ENABLE_COLOR_EMOJI = \"Enable colorful emoji\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Settings related to Windows11\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"Taskbar window closed to the icon instead of the sides of the taskbar\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Window vertical offset:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Window horizontal offset:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Avoid overlapping with right Widgets (Check this option if the Widgets appears on the right side of the taskbar)\"\nTXT_WIDGETS_WIDTH = \"Widgets width:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Show Scale\"\nTXT_USE_LINEAR_SCALE = \"Use Linear Scale\"\nTXT_USE_LOG_SCALE = \"Use Logarithmic Scale\"\nTXT_FIRST_DAT_OF_WEEEK = \"The first day of the week\"\nTXT_SUNDAY = \"Sunday\"\nTXT_MONDAY = \"Monday\"\nTXT_GO_TO_TODAY = \"Go to today\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"&Copy Text\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"&Select Network Connections\"\nTXT_AUTO_SELECT = \"&Auto Select\"\nTXT_SELECT_ALL = \"&Select All\"\nTXT_CONNECTION_DETAILS = \"Connection &Details\"\nTXT_ALWAYS_ON_TOP = \"Always on &Top\"\nTXT_MOUSE_PENETRATE = \"Mo&use Penetrate\"\nTXT_LOCK_WINDOW_POS = \"&Lock Window Position\"\nTXT_SHOW_MORE_INFO = \"Show More &Info\"\nTXT_SHOW_TASKBAR_WINDOW = \"Show Taskbar &Window\"\nTXT_SHOW_MAIN_WINDOW = \"Show &Main Window\"\nTXT_WINDOW_OPACITY = \"Window O&pacity\"\nTXT_OTHER_FUNCTIONS = \"Other &Functions\"\nTXT_CHANGE_SKIN = \"Change &Skin...\"\nTXT_CHANGE_NOTIFY_ICON = \"Change &Notify Icon...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Allow Out of Screen &Boundaries\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"&Historical Traffic Statistics\"\nTXT_PLUGIN_MANAGE = \"Plugin-in Manage...\"\nTXT_OPTIONS = \"&Options...\"\nTXT_HELP_MENU = \"&Help\"\nTXT_HELP = \"&Help\"\nTXT_FAQ = \"&Frequently Asked Questions\"\nTXT_UPDATE_LOG = \"Update &Log\"\nTXT_ABOUT = \"&About...\"\nTXT_CHECK_UPDATE = \"&Check for Update...\"\nTXT_EXIT = \"E&xit\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"Dis&play Settings...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"&Close Taskbar Window\"\nTXT_TASK_MANAGER = \"&Task Manager\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Details...\"\nTXT_PLUGIN_OPTIONS = \"&Options...\"\nTXT_PLUGIN_DISABLE = \"D&isabled\"\n\n;IDR_DISPLAY_ITEM_CONTEXT_MENU\nTXT_RESTORE_DEFAULT = \"&Restore Default\"\n"
  },
  {
    "path": "TrafficMonitor/language/German.ini",
    "content": "﻿[general]\nBCP_47 = \"de-DE\"\nDISPLAY_NAME = \"Deutsch\"\nTRANSLATOR = \"bege10\"\nTRANSLATOR_URL = \"\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"Update-Check fehlgeschlagen, bitte die Internetverbindung prüfen!\"\nIDS_CHECK_UPDATE_ERROR = \"Update-Check fehlgeschlagen und falsche Information von der serverseitigen Update-Datei erhalten, bitte kontaktiere den Entwickler!\"\nIDS_UPDATE_AVLIABLE = \"Neue Version V%s erkannt, willst du updaten?\"\nIDS_UPDATE_AVLIABLE2 = \"Neue Version V%s erkannt, Update-Inhalt: \\r\\n%s\\r\\nwillst du updaten?\"\nIDS_ALREADY_UPDATED = \"Dies ist schon die neueste Version.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"Kann automatischen Start beim Start von Windows nicht erlangen, kann den entsprechenden Schlüssel in der Registry nicht finden.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"Schreiben des Registryschlüssels fehlgeschlagen, könnte keine Berechtigung haben auf den Schlüssel zuzugreifen!\"\nIDS_AUTORUN_DELETE_FAILED = \"Löschen des Registryschlüssels fehlgeschlagen, könnte keine Berechtigung haben auf den Schlüssel zuzugreifen!\"\nIDS_AN_INSTANCE_RUNNING= \"Es läuft bereits eine Instanz.\"\nIDS_TRAFFIC_USED_TODAY = \"Heute genutzter Verkehr\"\nIDS_MEMORY_USAGE = \"Speicherauslastung\"\nIDS_CPU_USAGE = \"CPU-Auslastung\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Schicke eine E-Mail an den Entwickler.\"\nIDS_GOTO_GITHUB = \"Gehe zur GitHub-Seite dieses Projekts.\"\nIDS_DONATE_ATHOUR = \"Spende an den Entwickler\"\nIDS_UPLOAD = \"Upload\"\nIDS_DOWNLOAD = \"Download\"\nIDS_MEMORY = \"Speicher\"\nIDS_UPLOAD_DISP = \"UP\"\nIDS_DOWNLOAD_DISP = \"DN\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"Warnung: kann die Einstellungen nicht speichern, kann Daten nicht in Datei= \"\"<%file_path%>\"\" schreiben! Dieses Programm als Administrator auszuführen könnte das Problem lösen.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"Die Puffergröße für die Speicherung der Verbindungsinformation reicht nicht aus, die Verbindung wurde neu initialisiert. (<%cnt%> mal neu initialisiert)\"\nIDS_CONNECTION_NUM_CHANGED = \"Eine Änderung der Verbindungsnummer wurde erkannt. Die Verbindung wurde wiederhergestellt. Vorherige Verbindungen: <%before%>, Jetzige Verbindungen: <%after%>. (<%cnt%> mal neu initialisiert)\"\nIDS_CONNECTION_NOT_MATCH = \"Ein Ausnahmefall ist eingetreten, die kürzlich ausgewählte Verbindung ist inkonsistent der erwarteten Verbindung. Die Verbindung wurde wiederhergestellt. (<%cnt%> mal neu initialisiert)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"Das Fenster ist nicht erfolgreich in die Taskbar eingebettet, es könnte durch Sicherheitssoftware blockiert sein, oder das Startmenü ist nicht geschlossen. Bitte versuche den Explorer neu zu starten. TrafficMonitor wird es weiter versuchen, aber nicht weiter erinnern. Fehlercode:\"\nIDS_MEMORY_UDAGE_EXCEED= \"Die Speicherauslastung wurde erreicht\"\nIDS_NOTIFY = \"Benachrichtigen\"\nIDS_TODAY_TRAFFIC_EXCEED = \"Die heutige Nutzung wurde erreicht\"\nIDS_DATE = \"Datum\"\nIDS_TRAFFIC_USED = \"Verkehr gesamt\"\nIDS_FIGURE = \"Diagramm\"\nIDS_DEFAULT_ICON = \"Standardsymbol\"\nIDS_ICON = \"Symbol\"\nIDS_INTERFACE_NAME = \"Schnittstellenname\"\nIDS_INTERFACE_DESCRIPTION= \"Schnittstellenbeschreibung\"\nIDS_CONNECTION_TYPE = \"Verbindungstyp\"\nIDS_IF_TYPE_OTHER = \"Anderer Netzwerktyp\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"Ethernet-Netzwerk\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Token-Ring-Netzwerk\"\nIDS_IF_TYPE_FDDI = \"Fiber Distributed Data Interface (FDDI) Netzwerk\"\nIDS_IF_TYPE_PPP = \"PPP-Netzwerk\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"Software-Loopback-Netzwerk\"\nIDS_IF_TYPE_ATM = \"ATM Netzwerk\"\nIDS_IF_TYPE_IEEE80211 = \"IEEE 802.11 Drahtlos-Netzwerk\"\nIDS_IF_TYPE_TUNNEL = \"Tunnel type encapsulation Netzwerk\"\nIDS_IF_TYPE_IEEE1394 = \"IEEE 1394 (Firewire) Hochleistungs-Serial-Bus-Netzwerk\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"Mobile Breitbandschnittstelle für WiMax-Geräte\"\nIDS_IF_TYPE_WWANPP = \"Mobile Breitbandschnittstelle für GSM-basierte Geräte\"\nIDS_IF_TYPE_WWANPP2 = \"Mobile Breitbandschnittstelle für CDMA-basierte Geräte\"\nIDS_UNKNOW_CONNECTION = \"Unbekanntes Netzwerk\"\nIDS_SPEED = \"Geschwindigkeit\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"Physische Adresse des Adapters\"\nIDS_IP_ADDRESS = \"IP-Adresse\"\nIDS_SUBNET_MASK = \"Subnetzmaske\"\nIDS_DEFAULT_GATEWAY = \"Standardgateway\"\nIDS_OPERATIONAL_STATUS = \"Verbindungsstatus\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"LAN-Adapter wurde deaktiviert\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"WAN-Adapter ist nicht verbunden\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"Netzwerkkabel nicht verbunden oder kein Anbieter\"\nIDS_IF_OPER_STATUS_CONNECTING = \"WAN-Adapter stellt Verbindung her\"\nIDS_IF_OPER_STATUS_CONNECTED = \"WAN-Adapter mit Remote-Peer verbunden\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"LAN-Adapters ist verbunden\"\nIDS_UNKNOW_STATUS = \"Unbekannter Status\"\nIDS_BYTES_RECEIVED = \"Bytes empfangen\"\nIDS_BYTES_SENT = \"Bytes gesendet\"\nIDS_BYTES_RECEIVED_SINCE_START= \"Bytes empfangen seit Programmstart\"\nIDS_BYTES_SENT_SINCE_START= \"Bytes gesendet seit Programmstart\"\nIDS_PROGRAM_ELAPSED_TIME= \"Vergangene Programmzeit\"\nIDS_HOUR_MINUTE_SECOND = \"%d Stunden, %d Minuten, %d Sekunden\"\nIDS_INTERNET_IP_ADDRESS= \"Internet IP-Adresse\"\nIDS_GET_FAILED = \"Ermittlung fehlgeschlagen\"\nIDS_ITEM = \"Element\"\nIDS_VALUE = \"Wert\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"Kopieren in die Zwischenablage fehlgeschlagen!\"\nIDS_SKIN_AUTHOUR = \"Skin-Autor/in:\"\nIDS_OVERWRITE_FONT_TEXT_WARNING = \"Hinweis: Dieses Skin überschreibt die Schrift- und Anzeigetext-Einstellungen.\"\nIDS_OVERWRITE_FONT_WARNING= \"Hinweis: Dieses Skin überschreibt die Schrifteinstellungen.\"\nIDS_OVERWRITE_TEXT_WARNING = \"Hinweis: Dieses Skin überschreibt die Anzeigetext-Einstellungen.\"\nIDS_SPEED_SHORT_MODE_TIP = \"Wenn ausgewählt, wird die Anzeige der Netzgeschwindigkeit auf 1 Dezimalstelle reduziert und die Einheit zeigt nicht= \"\"B\"\".\"\nIDS_AUTO = \"Auto\"\nIDS_FIXED_AS = \"Als\"\nIDS_OPEN_CONNECTION_DETIAL= \"Verbindungsdetails öffnen\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"Datenverbrauchsstatistik öffnen\"\nIDS_SHOW_HIDE_MORE_INFO= \"Mehr Infos anzeigen/verstecken\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"CPU- und Speicherauslastung anzeigen/verstecken\"\nIDS_OPEN_OPTION_SETTINGS= \"Einstellungen öffnen\"\nIDS_OPEN_TASK_MANAGER = \"Taskmanager öffnen\"\nIDS_CHANGE_SKIN = \"Skin wechseln\"\nIDS_NONE = \"None\"\nIDS_FONT_SIZE_WARNING = \"Die Schriftgröße muss zwischen %d und %d sein!\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"Warnung: Die Textfarbe ist identisch mit der Hintergrundfarbe!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"Warnung: Die Hintergrundfarbe ist identisch mit der Textfarbe!\"\nIDS_FOLLOWING_SYSTEM = \"Dem System folgen\"\nIDS_LANGUAGE_CHANGE_INFO = \"Bitte das Programm neu starten, um die Spracheinstellung zu übernehmen.\"\nIDS_MAIN_WINDOW_SETTINGS= \"Hauptfenstereinstellungen\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"Taskbarfenster-Einstellungen\"\nIDS_GENERAL_SETTINGS = \"Allgemeine Einstellungen\"\nIDS_ACQUIRING = \"Erfassung\"\nIDS_LIST_VIEW = \"Listenanzeige\"\nIDS_CALENDAR_VIEW = \"Kalenderanzeige\"\nIDS_MONDAY = \"Mo\"\nIDS_TUESDAY = \"Di\"\nIDS_WEDNESDAY = \"Mi\"\nIDS_THURSDAY = \"Do\"\nIDS_FRIDAY = \"Fr\"\nIDS_SATURDAY = \"Sa\"\nIDS_SUNDAY = \"So\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"Gesamtverkehr aktueller Monat:\"\nIDS_TRAFFIC_USED1 = \"Verbrauch:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Einfügen in die Taskbar fehlgeschlagen, <%cnt%> wiederholte Versuche. GetLastError(): <%error_code%>.\"\nIDS_NO_CONNECTION = \"Keine Verbindung\"\nIDS_CONTACT_TRANSLATOR = \"Kontaktiere diese/n Übersetzer/in.\"\nIDS_THANKS_DONORS = \"Danke an die folgenden Spender/innen:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"Ein Fehler trat auf bei der Anforderung= \"\"<%1%>\"\", Fehlercode: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"Wenn diese Option aktiviert ist, werden alle Netzwerkschnittstellen in der= \"\"Wähle Netzwerkverbindungen\"\"-Liste im Rechtsklickmenü angezeigt. Es wird empfohlen dies nur bei Bedarf zu aktivieren.\"\nIDS_CFG_DIR_CHANGED_INFO = \"Du hast den Speicherort der Konfigurations- und Datendateien geändert. Diese wird nach einem Neustart übernommen. Eventuell musst du die Konfigurations- und Datendateien manuell an den neuen Ort verschieben.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<Hier doppelklicken zur Ermittlung.>\"\nIDS_ERROR1 = \"Fehler\"\nIDS_ERROR_MESSAGE = \"Fehlermeldung:\"\nIDS_CRASH_INFO = \"Entschuldigung, das Programm ist abgestürzt. Bitte starte das Programm neu. \\r\\nWenn das Problem öfter auftritt, deaktiviere bitte die Hardwareüberwachungsfunktion in= \"\"Optionen\"\" >= \"\"Allgemeine Einstellungen\"\", und deaktiviere alle Plugins im= \"\"Plugin-Manager\"\" Dialogfenster. \\r\\nWenn das Problem weiter existiert, schicke diese Datei= \"\"<%1%>\"\" an bugreport-zhongyang219@outlook.com um dem Entwickler zu helfen das Problem zu lokalisieren. Und füge Folgendes dem Nachrichtentext hinzu:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"Anerkennung\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Bist du sicher, dass du die aktuelle Taskbarfarbeinstellung in= \"\"Voreinstellung <%1%>\"\" speichern willst?\"\nIDS_SPECIFIC_APP = \"Spezifizierte Anwendung öffnen\"\nIDS_EXE_FILTER = \"Programme|*.exe|Batch-Dateien|*.bat||\"\nIDS_PRESET = \"Voreinstellung\"\nIDS_LIGHT_MODE = \"Heller Modus\"\nIDS_AUTO_ADAPT_TIP_INFO= \"Diese Funktion wird automatisch die Farbvoreinstellungen umschalten, wenn sich die Windows 10 Hell/Dunkel-Themes ändern. Klicke den= \"\"Auto-Anpassen-Einstellungen\"\" Button um das Voreinstellungsschema für automatisches Umschalten zu konfigurieren.\"\nIDS_WITHOUT_TEMPERATURE= \"Lite\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"Durchklicken mit der Maus ist aktiviert. Um diese Funktion auszuschalten, klicke mit der rechten Maustaste auf das TrafficMonitor-Symbol im Systembenachrichtigungsbereich und deaktiviere die Funktion im Menü. Klicke auf Abbrechen um nicht mehr benachrichtigt zu werden.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"Die Daten der Nutzungsstatistik sind verloren gegangen. Aktuelle Anzahl an Datensätzen: <%1%>, <%2%> wurden aus der Sicherungsdatei wiederhergestellt.\"\nIDS_LEGEND = \"Legende\"\nIDS_LICENSE_EXPLAIN = \"Please follow the following open source protocol when using \\r\\nthe source code of this software.\"\nIDS_LICENSE = \"Lizenz\"\nIDS_DAY_VIEW = \"Tag\"\nIDS_MONTH_VIEW = \"Monat\"\nIDS_QUARTER_VIEW = \"Vierteljahr\"\nIDS_YEAR_VIEW = \"Jahr\"\nIDS_LINEAR_SCALE = \"Linearer Maßstab\"\nIDS_LOG_SCALE = \"Logarithmischer Maßstab\"\nIDS_CPU_TEMPERATURE = \"CPU-Temperatur\"\nIDS_GPU_TEMPERATURE = \"GPU-Temperatur\"\nIDS_CPU_FREQ = \"CPU_Freq\"\nIDS_HDD_TEMPERATURE = \"Festplattentemperatur\"\nIDS_MAINBOARD_TEMPERATURE= \"Mainboard-Temperatur\"\nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"HDD\"\nIDS_MAINBOARD_DISP = \"MBD\"\nIDS_CPU_TEMPERATURE_EXCEED= \"Die CPU-Temperatur wurde erreicht\"\nIDS_GPU_TEMPERATURE_EXCEED= \"Die GPU-Temperatur wurde erreicht\"\nIDS_HDD_TEMPERATURE_EXCEED= \"Die Festplattentemperatur wurde erreicht\"\nIDS_MBD_TEMPERATURE_EXCEED= \"Die Mainboard-Temperatur wurde erreicht\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: Ein schöner und einfach zu bedienender lokaler Musik-Player für Windows\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: Ein einfacher Texteditor für Windows\"\nIDS_COLOR = \"Farbe\"\nIDS_COLOR_LABEL = \"Beschriftungsfarbe\"\nIDS_COLOR_VALUE = \"Wertfarbe\"\nIDS_GPU_USAGE = \"GPU-Auslastung\"\nIDS_IF_OPER_STATUS_UP = \"Der Adapter ist verbunden\"\nIDS_IF_OPER_STATUS_DOWN= \"Der Adapter ist nicht verbunden\"\nIDS_IF_OPER_STATUS_DORMANT= \"Der Adapter verbindet sich\"\nIDS_GOTO_GITEE = \"Gehe auf die Gitee-Seite dieses Projekts.\"\nIDS_USAGE_PERCENTAGE = \"Genutzter Prozentsatz\"\nIDS_MEMORY_USED = \"Genutzter Speicher\"\nIDS_MEMORY_AVAILABLE = \"Verfügbarer Speicher\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \".Net Framework v4.5.2 oder höher ist auf dem System nicht installiert. Die Temperaturüberwachung ist nicht verfügbar. Klicke auf Abbrechen, um nicht mehr gefragt zu werden.\"\nIDS_VERSION_UPDATE = \"Update auf neue Version\"\nIDS_AVREAGE_TEMPERATURE= \"Durchschnittstemperatur\"\nIDS_HARDWARE_MONITOR_WARNING = \"Warnung: Du schaltest die Hardwareüberwachung ein. Die Hardwareüberwachung kann genutzt werden für die Anzeige der Temperatur und der GPU-Nutzung. Bitte lies das folgende sorgfältig durch, bevor du die Hardwareüberwachung anschaltest:\\r\\nTrafficMonitor ist keine professionelle Hardwareüberwachungssoftware. Sie kann nicht weder garantieren, dass auf jedem Computer Hardwareinformationen erhalten werden können, noch die Genauigkeit der erhaltenen Hardwareinformationen.\\r\\nDie Hardwareüberwachung ist implementiert mit der Third-Party-Bibliothek LibreHardwareMonitor. Nachdem die Hardwareüberwachung eingeschaltet ist, können auf manchen Computern Probleme entstehen, einschließlich aber nicht beschränkt auf:\\r\\n* Abnormale CPU- und Speichernutzung\\r\\n* Programmabsturz\\r\\n* Computerabsturz\\r\\nBitte entscheide dich die Hardwareüberwachung einzuschalten, nachdem du dir der obigen Risiken bewusst bist. \\r\\nWillst du die Hardwareüberwachung wirklich einschalten?\"\nIDS_HDD_USAGE = \"Festplattennutzung\"\nIDS_FILE_NAME = \"Dateiname\"\nIDS_STATUS = \"Status\"\nIDS_PLUGIN_LOAD_SUCCEED= \"Erfolgreich geladen\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"Laden des Plugin-Moduls fehlgeschlagen, Fehlercode: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"Funktionserfassung fehlgeschlagen, Fehlercode: <%1%>\"\nIDS_PLUGIN_INFO = \"Plugin-Details\"\nIDS_NAME = \"Name\"\nIDS_DESCRIPTION = \"Beschreibung\"\nIDS_FILE_PATH = \"Dateipfad\"\nIDS_ITEM_NUM = \"Anzahl angezeigter Elemente\"\nIDS_ITEM_NAMES = \"Namen angezeigter Elemente\"\nIDS_AUTHOR = \"Entwickler\"\nIDS_COPYRIGHT = \"Copyright\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"Das Plugin hat keine Optionseinstellungen.\"\nIDS_PLUGIN_NAME = \"Plugin-Name\"\nIDS_DISABLED = \"Deaktiviert\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Bitte starte das Programm neu um die Änderungen anzuwenden.\"\nIDS_VERSION = \"Version\"\nIDS_DISP_ITEM_ID = \"Angezeigte Element-ID\"\nIDS_PLUGIN_API_VERSION = \"API-Version\"\nIDS_WEEK_VIEW = \"Wochenansicht\"\nIDS_WEEK_NUM = \"Woche <%1%>\"\nIDS_URL = \"Url\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"Die Plugin-Version ist zu niedrig.\"\nIDS_MODIFY_PRESET = \"Voreinstellung ändern\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"Bitte mindestens eins auswählen!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"Wenn die Funktion= \"\"Automatisch an Windows 10 Hell/Dunkel-Theme anpassen\"\" und diese Option aktiviert sind, werden die Farben des Taskbarfensters, wenn sie geändert werden, automatisch in die jeweilige Voreinstellung entsprechend dem aktuellen Windows-Hell-/Dunkel-Modus gespeichert.\"\nIDS_TOTAL_NET_SPEED = \"Gesamtgeschwindigkeit\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"Ressourcennutzungsdiagramm anzeigen für CPU-/Speicher-/Festplattennutzung, Temperatur und Plugin-Elemente.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"Netzgeschwindigkeitsdiagramm für Upload, Download und Gesamtgeschwindigkeit anzeigen.\"\nIDS_REFRESH_CONNECTION_LIST= \"Verbindungsliste aktualisieren\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"Die Initialisierung der Hardwareüberwachung ist fehlgeschlagen und deshalb nicht verfügbar!\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Fehler beim Erfassen der Hardwareüberwachungsdaten!\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"Autostart-Modus : Registry\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"Autostart-Modus: Aufgabenplanung\"\nIDS_PATH = \"Pfad\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"Aktivieren des Autostarts beim Gerätestart fehlgeschlagen!\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Aktualisierung des Taskbarfensterinhalts fehlgeschlagen, Direct2Dd-Rendering wurde deaktiviert. Hinweis: Das Einstellungsfenster könnte die Einstellungsanpassung nicht sofort aktualisieren.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Ein Fehler ist während des Direct2Dd-Rendering aufgetreten und es wurde deaktiviert. Hinweis: Das Einstellungsfenster könnte die Einstellungsanpassung nicht sofort aktualisieren.\"\nIDS_PLUGIN_OPTIONS = \"Plugin-Optionen\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"Das Erfassen der CPU-Nutzung durch den Performance Counter ist fehlgeschlagen, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"Primäres Display\"\nIDS_SECONDARY_DISPLAY = \"Sekundäres Display <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"Das System wurde aus dem Ruhezustand geweckt, die Verbindung wurde reinitialisiert. (<%1%> mal reinitialisiert.)\"\n\nTXT_OK = \"OK\"\nTXT_CANCEL = \"Abbrechen\"\nTXT_CLOSE = \"Schließen\"\nTXT_APPLY = \"Anwenden\"\n\n; Text used for dialog. (Must be started with \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"Über TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>, V<%2%>\"\nTXT_ABOUT_COPYRIGHT = \"Copyright (C) 2017-2025 By ZhongYang\\nLast compiled date: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%> Übersetzer: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"In diesen Projekt verwendete Third-Party-Bibliotheken:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"Andere Software des Entwicklers:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"Entwickler kontaktieren\"\nTXT_ABOUT_LICENSE = \"Lizenz\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"Anerkennung\"\nTXT_ABOUT_DONATE = \"Spenden\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor läuft bereits.\"\nTXT_EXIT_THE_PROGRAM = \"Das &Programm verlassen\"\nTXT_OPEN_OPTION_SETTINGS = \"&Einstellungen öffnen\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"&Hauptfenster anzeigen/verstecken\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"&Taskbarfenster anzeigen/verstecken\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Einstellungen für Auto-Anpassung\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Farbvoreinstellung für den dunklen Windows-Modus:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Farbvoreinstellung für den hellen Windows-Modus:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"Farbeinstellungen des Taskbarfenster automatisch in die Voreinstellungen sichern\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Anzeigetext-Einstellungen\"\nTXT_RESTORE_DEFAULT = \"&Standard wiederherstellen\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Programmeinstellungen\"\nTXT_CHECK_UPDATE = \"Beim Start auf Updates prüfen\"\nTXT_CHECK_NOW = \"&Jetzt prüfen\"\nTXT_UPDATE_SOURCE = \"Updatequelle:\"\nTXT_AUTO_RUN_CHECK = \"Automatisch starten, wenn Windows startet\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Autorun zurücksetzen\"\nTXT_LANGUAGE = \"Sprache:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"Konfigurations- und Datendateien\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Ins Appdata-Verzeichnis sichern\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Ins Programmverzeichnis sichern\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Konfigurationsdatei und -&Verzeichnis öffnen\"\nTXT_NOTIFICATION_MESSAGE = \"Benachrichtigungstext\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"Benachrichtigen, wenn der heutige Verkehr erreicht wurde\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"Benachrichtigen, wenn die Speichernutzung erreicht wurde\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"Benachrichtigen, wenn die CPU-Temperatur erreicht wurde\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"Benachrichtigen, wenn die GPU-Temperatur erreicht wurde\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"Benachrichtigen, wenn die Festplattentemperatur erreicht wurde\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"Benachrichtigen, wenn die Mainboardtemperatur erreicht wurde\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Hardwareüberwachung\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"GPU\"\nTXT_HARD_DISK = \"Festplatte\"\nTXT_MAIN_BOARD = \"Mainboard\"\nTXT_SELECT_HDD_STATIC = \"Zu überwachende Festplatte auswählen:\"\nTXT_SELECT_CPU_STATIC = \"Zu überwachende CPU-Temperatur auswählen:\"\nTXT_ADVANCED = \"Erweitert\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Alle Netzwerkverbindungen anzeigen\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"Zu überwachende &Verbindungen auswählen...\"\nTXT_CPU_ACQUISITION_METHOD = \"Erfassungsmethode für die CPU-Nutzung:\"\nTXT_USE_CPU_TIME_RADIO = \"Auf Basis der CPU-Zeit\"\nTXT_USE_PDH_RADIO = \"Den Performance Counter nutzen\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"Den Hardwaremonitor nutzen\"\nTXT_MONITORING_INTERVALS = \"Überwachungsintervalle:\"\nTXT_MILLISECONDS = \"Millisekunden\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"&Standard wiederherstellen\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Plugin-Manager...\"\nTXT_DISPLAY = \"Display\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"&Benachrichtigungssymbol anzeigen\"\nTXT_SKINS = \"Skins\"\nTXT_ALLOW_SKIN_FONT_CHECK = \"Skins erlauben die Schrifteinstellungen zu überschreiben\"\nTXT_ALLOW_SKIN_DISP_STR_CHECK = \"Skins erlauben die Anzeigetexteinstellungen zu überschreiben\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Jahr:\"\nTXT_MONTH = \"Monat:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Netzverkehrsstatistik\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"Zeitraum:\"\nTXT_FIGURE_VIEW_SCALE = \"Anzeigemaßstab:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Benachrichtigungssymbol ändern\"\nTXT_SELECT_A_ICON = \"Symbol wählen:\"\nTXT_PREVIEW = \"Vorschau\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Automatisch an Windows 10 Hell/Dunkel-Theme anpassen\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Hauptfenster Farbeinstellungen\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Hauptfenster verstecken, wenn das Programm im Vollbildmodus läuft\"\nTXT_COLOR_AND_FONT = \"Farbe und Schrift\"\nTXT_FONT = \"Schriftart:\"\nTXT_FONT_SIZE = \"Schriftgröße:\"\nTXT_SET_FONT_BUTTON = \"&Schriftart wählen...\"\nTXT_TEXT_COLOR = \"Textfarbe:\"\nTXT_DISPLAY_TEXT = \"Anzeigetext\"\nTXT_SWITCH_UP_DOWN_CHECK = \"Upload- und Download-Position tauschen\"\nTXT_UNIT_SETTINGS = \"Einstellungen Einheit\"\nTXT_UNIT_SELECTION = \"Auswahl Einheit:\"\nTXT_HIDE_UNIT_CHECK = \"Netzgeschwindigkeitseinheit nicht anzeigen\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Gekürzte Netzgeschwindigkeitsanzeige\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Prozentzeichen nicht anzeigen\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Farben für jedes Element einstellen\"\nTXT_DOUBLE_CLICK_ACTION = \"Doppelklick-Aktion:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Wert und Einheit durch Leerzeichen trennen\"\nTXT_NETSPEED_UNIT = \"Netzgeschwindigkeitseinheit:\"\nTXT_UNIT_BYTE_RADIO = \"B (Byte)\"\nTXT_UNIT_BIT_RADIO = \"b (bit)\"\nTXT_SHOW_TOOL_TIP_CHK = \"Maus-Tooltip anzeigen\"\nTXT_EXE_PATH_STATIC = \"Spezifizierte Anwendung:\"\nTXT_BROWSE_BUTTON = \"&Browsen...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Anzeige&text-Einstellungen...\"\nTXT_MEMORY_DISPLAY_MODE = \"Speicheranzeigemodus:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Immer im Vordergrund\"\nTXT_MOUSE_PENETRATE_CHECK = \"Durchklickbar\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Fensterposition sperren\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Erlaube über Bildschirmrand hinaus\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Nachricht\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Verbindungsdetails\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Einstellungen\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Plugin-Manager\"\nTXT_OPTINS_BUTTON = \"&Optionen...\"\nTXT_PLUGIN_INFO_BUTTON = \"&Details...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Plugin-Entwicklungsleitfaden\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"Mehr Plugins herunterladen\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Plugin-Verzeichnis öffnen\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Zu überwachende Verbindung auswählen\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Anzeigeeinstellungen\"\nTXT_MOVE_UP_BUTTON = \"Hoch\"\nTXT_MOVE_DOWN_BUTTON = \"Runter\"\nTXT_RESTORE_DEFAULT_BUTTON = \"&Standard wiederherstellen\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Einstellungen für automatische Skin-Umschaltung\"\nTXT_SKIN_IN_DARK_MODE = \"Skin im dunklen Modus von Windows:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Skin im hellen Modus von Windows:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Skin wechseln\"\nTXT_PREVIEW_GROUP_STATIC = \"Vorschau\"\nTXT_SELECT_A_SKIN = \"Skin wählen\"\nTXT_SKIN_AUTHOR = \"Skin-Autor:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Anleitung für Skin-Erstellung\"\nTXT_DOWNLOAD_MORE_SKIN = \"Weitere Skins herunterladen\"\nTXT_OPEN_SKIN_DIR = \"Skin-Verzeichnis öffnen\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Skins automatisch entsprechend Windows-Dunkel-/Hell-Modus umschalten.\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Einstellungen für Auto-Umschaltung...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"Taskbarfenster-Farbeinstellungen\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Voreinstellung\"\nTXT_BACKGROUND_COLOR = \"Hintergrundfarbe:\"\nTXT_BACKGROUND_TRANSPARENT = \"Hintergrund transparent\"\nTXT_AUTO_SET_BACK_COLOR = \"Hintergrund entsprechend der Taskbarfarbe automatisch einstellen\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Automatisch an Windows 10 Hell/Dunkel-Theme anpassen\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"&Einstellungen für Auto-Anpassung...\"\nTXT_DISPLAY_SETTINGS = \"Anzeigeeinstellungen\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"&Anzeigeeinstellungen...\"\nTXT_SPEED_SHORT_MODE = \"Gekürzte Netzgeschwindigkeitsanzeige\"\nTXT_VALUE_RIGHT_ALIGN = \"Werte rechts ausrichten\"\nTXT_NET_SPEED_DATA_WIDTH = \"Breite der Netzgeschwindigkeitsanzeige:\"\nTXT_CHARACTORS = \"Zeichen\"\nTXT_HORIZONTAL_ARRANGE = \"Horizontal anzeigen\"\nTXT_ITEM_SPACING = \"Abstand zwischen Elementen:\"\nTXT_VERTICAL_MARGIN = \"Vertikaler Rand:\"\nTXT_PIXELS = \"Pixel\"\nTXT_TASKBAR_WINDOW = \"Taskbarfenster\"\nTXT_TASKBAR_WND_ON_LEFT = \"Taskbarfenster erscheint auf der Taskbar links\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"Display, auf dem das Taskbarfenster angezeigt wird:\"\nTXT_WIN11_SETTINGS_BUTTON = \"Einstellungen entsprechend Windows 11\"\nTXT_RESOURCE_USAGE_GRAPH = \"Ressourcennutzungsdiagramm\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Ressourcennutzungsdiagramm anzeigen\"\nTXT_SHOW_DASHED_BOX = \"Gestrichelte Umrandung anzeigen\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Netzgeschwindigkeitsdiagramm anzeigen\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"Maximalwert der Netzgeschwindigkeitsdiagramm:\"\nTXT_USAGE_GRAPH_COLOR = \"Nutzungsdiagrammfarbe:\"\nTXT_GRAPH_DISPLAY_MODE = \"Diagrammanzeige:\"\nTXT_BAR_MODE = \"Balken-Modus\"\nTXT_PLOT_MODE = \"Plot-Modus\"\nTXT_RENDERING_SETTINGS = \"Rendering-Einstellungen\"\nTXT_RENDERING_SETTINGS_NOTE = \"Hinweis:Direct2D-Rendering wird nur genutzt, wenn \"\"Background transparent\"\" aktiviert und \"\"Hintergrund entsprechend der Taskbarfarbe automatisch einstellen\"\" nicht aktiviert ist.\"\nTXT_ENABLE_COLOR_EMOJI = \"Farbige Emoji aktivieren\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Einstellungen entsprechend Windows 11\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"Taskbarfenster beim Symbol statt an den Seiten der Taskbar\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Vertikaler Versatz des Fensters:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Horizontaler Versatz des Fensters:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Überlagerung mit den rechten Widgets vermeiden (Auswählen, wenn die Widgets auf der rechten Seite der Taskbar erscheinen)\"\nTXT_WIDGETS_WIDTH = \"Widgetbreite:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Maßstab anzeigen\"\nTXT_USE_LINEAR_SCALE = \"Linearen Maßstab nutzen\"\nTXT_USE_LOG_SCALE = \"Logarithmischen Maßstab nutzen\"\nTXT_FIRST_DAT_OF_WEEEK = \"Erster Tag der Woche\"\nTXT_SUNDAY = \"Sonntag\"\nTXT_MONDAY = \"Montag\"\nTXT_GO_TO_TODAY = \"Gehe zu heute\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"&Text kopieren\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"&Netzwerkverbindungen wählen\"\nTXT_AUTO_SELECT = \"Aut&omatisch auswählen\"\nTXT_SELECT_ALL = \"Alle aus&wählen\"\nTXT_CONNECTION_DETAILS = \"Verbindungs&details\"\nTXT_ALWAYS_ON_TOP = \"Immer im &Vordergrund\"\nTXT_MOUSE_PENETRATE = \"Durch&klickbar\"\nTXT_LOCK_WINDOW_POS = \"&Fensterposition sperren\"\nTXT_SHOW_MORE_INFO = \"Mehr &Infos anzeigen\"\nTXT_SHOW_TASKBAR_WINDOW = \"&Taskbarfenster anzeigen\"\nTXT_SHOW_MAIN_WINDOW = \"&Hauptfenster anzeigen\"\nTXT_WINDOW_OPACITY = \"F&ensterundurchsichtigkeit \"\nTXT_OTHER_FUNCTIONS = \"Andere F&unktionen\"\nTXT_CHANGE_SKIN = \"&Skin wechseln...\"\nTXT_CHANGE_NOTIFY_ICON = \"Benach&richtigungssymbol wechseln...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Erlaube über &Bildschirmrand hinaus\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"&Netzverkehrsstatistik\"\nTXT_PLUGIN_MANAGE = \"&Plugin-Manager...\"\nTXT_OPTIONS = \"&Optionen...\"\nTXT_HELP_MENU = \"H&ilfe...\"\nTXT_HELP = \"&Hilfe\"\nTXT_FAQ = \"Häufige Fragen (FA&Q)\"\nTXT_UPDATE_LOG = \"Update-&Log\"\nTXT_ABOUT = \"Übe&r...\"\nTXT_CHECK_UPDATE = \"&Auf Updates prüfen...\"\nTXT_EXIT = \"E&xit\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"&Anzeigeeinstellungen...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"Taskbarfenster &schließen\"\nTXT_TASK_MANAGER = \"&Taskmanager\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Details...\"\nTXT_PLUGIN_OPTIONS = \"&Optionen...\"\nTXT_PLUGIN_DISABLE = \"De&aktiviert\"\n"
  },
  {
    "path": "TrafficMonitor/language/Hebrew.ini",
    "content": "﻿[general]\nBCP_47 = \"he-IL\"\nDISPLAY_NAME = \"עברית\"\nTRANSLATOR = \"Y-PLONI\"\nTRANSLATOR_URL = \"7353755@gmail.com\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"בדיקת עדכונים נכשלה, אנא בדוק את חיבור הרשת שלך!\"\nIDS_CHECK_UPDATE_ERROR = \"בדיקת עדכונים נכשלה וקיבלה מידע שגוי מקובץ העדכון המרוחק, אנא פנה למחבר!\"\nIDS_UPDATE_AVLIABLE = \"זוהתה גרסה חדשה V%s, האם ברצונך לעדכן?\"\nIDS_UPDATE_AVLIABLE2 = \"גרסה חדשה V%s זמינה! תיאור השינויים: \\r\\n%s\\r\\nהאם ברצונך לעדכן?\"\nIDS_ALREADY_UPDATED = \"הגרסה האחרונה כבר מותקנת.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"לא ניתן להפעיל את התוכנה עם עליית Windows, המפתח המתאים אינו נמצא ברישום.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"כתיבת מפתח הרישום נכשלה, ייתכן שאין הרשאה לגשת למפתח!\"\nIDS_AUTORUN_DELETE_FAILED = \"מחיקת מפתח הרישום נכשלה, ייתכן שאין הרשאה לגשת למפתח!\"\nIDS_AN_INSTANCE_RUNNING= \"כבר קיימת מופע פועל.\"\nIDS_TRAFFIC_USED_TODAY = \"תעבורה שהשתמשו בה היום\"\nIDS_MEMORY_USAGE = \"ניצול זיכרון\"\nIDS_CPU_USAGE = \"ניצול מעבד\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"שלח מייל למחבר.\"\nIDS_GOTO_GITHUB = \"עבור לעמוד הפרויקט ב-GitHub.\"\nIDS_DONATE_ATHOUR = \"תרום למחבר\"\nIDS_UPLOAD = \"העלה\"\nIDS_DOWNLOAD = \"הורד\"\nIDS_MEMORY = \"זיכרון\"\nIDS_UPLOAD_DISP = \"UP\"\nIDS_DOWNLOAD_DISP = \"DN\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"אזהרה: לא ניתן לשמור את ההגדרות. לא ניתן לכתוב לקובץ <%file_path%>! הפעלת התוכנה כמנהל מערכת עשויה לפתור את הבעיה.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"גודל המאגר לאחסון פרטי החיבור אינו מספיק. החיבור אופס. (אופס <%cnt%> פעמים)\"\nIDS_CONNECTION_NUM_CHANGED = \"זוהתה שינוי במספר החיבורים. החיבור התקבל מחדש. חיבורים קודמים: <%before%>, כעת חיבורים: <%after%>. (<%cnt%> פעמים אופס מחדש)\"\nIDS_CONNECTION_NOT_MATCH = \"ייתכן שהתרחשה חריגה, החיבור שנבחר כעת אינו תואם לחיבור הצפוי. החיבור התקבל מחדש. (<%cnt%> פעמים אופס מחדש)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"החלון לא הצליח להשתלב בשורת המשימות. ייתכן שהוא נחסם על ידי תוכנת אבטחה או שתפריט 'התחל' פתוח. נסה להפעיל מחדש את Explorer. TrafficMonitor ימשיך לנסות, אך לא יציג עוד הודעות שגיאה. קוד שגיאה:\"\nIDS_MEMORY_UDAGE_EXCEED= \"ניצול הזיכרון הגיע למקסימום\"\nIDS_NOTIFY = \"התרעה\"\nIDS_TODAY_TRAFFIC_EXCEED = \"הניצול בעבורה היום הגיע למקסימום\"\nIDS_DATE = \"תאריך\"\nIDS_TRAFFIC_USED = \"כלל התעבורה\"\nIDS_FIGURE = \"תרשים\"\nIDS_DEFAULT_ICON = \"סמל ברירת מחדל\"\nIDS_ICON = \"סמל\"\nIDS_INTERFACE_NAME = \"שם ממשק\"\nIDS_INTERFACE_DESCRIPTION= \"תיאור ממשק\"\nIDS_CONNECTION_TYPE = \"סוג חיבור\"\nIDS_IF_TYPE_OTHER = \"סוג רשת אחר\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"רשת Ethernet\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"רשת Token Ring\"\nIDS_IF_TYPE_FDDI = \"רשת Fiber Distributed Data Interface (FDDI)\"\nIDS_IF_TYPE_PPP = \"רשת PPP\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"רשת לולאה פנימית (Loopback)\"\nIDS_IF_TYPE_ATM = \"רשת ATM\"\nIDS_IF_TYPE_IEEE80211 = \"רשת אלחוטית IEEE 802.11\"\nIDS_IF_TYPE_TUNNEL = \"רשת מסוג encapsulation Tunnel\"\nIDS_IF_TYPE_IEEE1394 = \"רשת IEEE 1394 (FireWire) עם ערוץ טורי מהיר\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"ממשק פס רחב נייד עבור מכשירי WiMax\"\nIDS_IF_TYPE_WWANPP = \"ממשק פס רחב נייד עבור מכשירים מבוססי GSM\"\nIDS_IF_TYPE_WWANPP2 = \"ממשק פס רחב נייד עבור מכשירים מבוססי CDMA\"\nIDS_UNKNOW_CONNECTION = \"רשת לא מוכרת\"\nIDS_SPEED = \"מהירות\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"כתובת פיזית של המתאם\"\nIDS_IP_ADDRESS = \"כתובת IP\"\nIDS_SUBNET_MASK = \"מסכת רשת משנה\"\nIDS_DEFAULT_GATEWAY = \"שער ברירת מחדל\"\nIDS_OPERATIONAL_STATUS = \"מצב חיבור\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"מתאם ה-LAN הושבת\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"מתאם ה-WAN אינו מחובר\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"כבל הרשת מנותק או שאין אות\"\nIDS_IF_OPER_STATUS_CONNECTING = \"מתאם ה-WAN בתהליך התחברות\"\nIDS_IF_OPER_STATUS_CONNECTED = \"מתאם ה-WAN מחובר לעמית מרוחק\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"מתאם ה-LAN מחובר\"\nIDS_UNKNOW_STATUS = \"מצב לא מוכר\"\nIDS_BYTES_RECEIVED = \"בתים שהתקבלו\"\nIDS_BYTES_SENT = \"בתים שנשלחו\"\nIDS_BYTES_RECEIVED_SINCE_START= \"בתים שהתקבלו מאז הפעלת התוכנה\"\nIDS_BYTES_SENT_SINCE_START= \"בתים שנשלחו מאז הפעלת התוכנה\"\nIDS_PROGRAM_ELAPSED_TIME= \"משך זמן הפעלת התוכנה\"\nIDS_HOUR_MINUTE_SECOND = \"%d שעות, %d דקות, %d שניות\"\nIDS_INTERNET_IP_ADDRESS= \"כתובת IP ציבורית\"\nIDS_GET_FAILED = \"קבלת נתונים נכשלה\"\nIDS_ITEM = \"פריט\"\nIDS_VALUE = \"ערך\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"העתקה ללוח נכשלה!\"\nIDS_SKIN_AUTHOUR = \"מחבר העיצוב:\"\nIDS_SPEED_SHORT_MODE_TIP = \"כאשר האפשרות מסומנת, תצוגת מהירות הרשת תופחת בעשרונית אחת, והיחידה לא תציג= \"\"B\"\".\"\nIDS_AUTO = \"אוטומטי\"\nIDS_FIXED_AS = \"נקבע כ\"\nIDS_OPEN_CONNECTION_DETIAL= \"פתח פרטי חיבור\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"פתח נתוני תעבורה היסטוריים\"\nIDS_SHOW_HIDE_MORE_INFO= \"הצג/הסתר מידע נוסף\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"הצג/הסתר ניצול מעבד וזיכרון\"\nIDS_OPEN_OPTION_SETTINGS= \"פתח הגדרות אפשרויות\"\nIDS_OPEN_TASK_MANAGER = \"פתח את מנהל המשימות\"\nIDS_CHANGE_SKIN = \"שנה עיצוב\"\nIDS_NONE = \"ללא\"\nIDS_FONT_SIZE_WARNING = \"גודל הגופן חייב להיות בין %d ל-%d!\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"אזהרה: צבע הטקסט זהה לצבע הרקע!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"אזהרה: צבע הרקע זהה לצבע הטקסט!\"\nIDS_FOLLOWING_SYSTEM = \"בהתאם למערכת\"\nIDS_LANGUAGE_CHANGE_INFO = \"אנא הפעל מחדש את היישום כדי להחיל את הגדרת השפה.\"\nIDS_MAIN_WINDOW_SETTINGS= \"הגדרות חלון ראשי\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"הגדרות חלון שורת המשימות\"\nIDS_GENERAL_SETTINGS = \"הגדרות כלליות\"\nIDS_ACQUIRING = \"מקבל נתונים\"\nIDS_LIST_VIEW = \"תצוגת רשימה\"\nIDS_CALENDAR_VIEW = \"תצוגת לוח שנה\"\nIDS_MONDAY = \"יום שני\"\nIDS_TUESDAY = \"יום שלישי\"\nIDS_WEDNESDAY = \"יום רביעי\"\nIDS_THURSDAY = \"יום חמישי\"\nIDS_FRIDAY = \"יום שישי\"\nIDS_SATURDAY = \"שבת קודש\"\nIDS_SUNDAY = \"יום ראשון\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"כלל התעבורה לחודש הנוכחי:\"\nIDS_TRAFFIC_USED1 = \"תעבורה שנוצלה:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"ההוספה לשורת המשימות נכשלה. מנסה שוב (ניסיון <%cnt%>). קוד שגיאה: <%error_code%>.\"\nIDS_NO_CONNECTION = \"אין חיבור\"\nIDS_CONTACT_TRANSLATOR = \"צור קשר עם המתרגם.\"\nIDS_THANKS_DONORS = \"תודה לתורמים הבאים:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"אירעה שגיאה בעת בקשה= \"\"<%1%>\"\", קוד שגיאה: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"כאשר פריט זה מסומן, יוצגו כל ממשקי הרשת ברשימה= \"\"בחר חיבורי רשת\"\" בתפריט לחיצה ימנית. מומלץ לסמן אפשרות זו רק בעת הצורך.\"\nIDS_CFG_DIR_CHANGED_INFO = \"שינית את מיקום קבצי ההגדרות והנתונים. השינוי ייכנס לתוקף לאחר הפעלה מחדש. ייתכן שתצטרך להעביר את קבצי ההגדרות והנתונים למיקום החדש באופן ידני.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<לחץ לחיצה כפולה לקבלת הנתונים.>\"\nIDS_ERROR1 = \"שגיאה\"\nIDS_ERROR_MESSAGE = \"הודעת שגיאה:\"\nIDS_CRASH_INFO = \"מצטערים, התוכנה קרסה. אנא הפעל מחדש את התוכנה. \\r\\nאם אתה נתקל בבעיה זו פעמים רבות, נסה להשבית את פונקציית ניטור החומרה ב= \"\"אפשרויות\"\" >= \"\"הגדרות כלליות\"\", ולהשבית את כל התוספים בחלונית= \"\"מנהל התוספים\"\". \\r\\nאם הבעיה נמשכת, שלח דוא\\\"ל עם קובץ זה= \"\"<%1%>\"\" אל bugreport-zhongyang219@outlook.com כדי לעזור למחבר לאתר את הבעיה. הוסף את הפרטים הבאים בגוף ההודעה:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"הוקרה\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"האם אתה בטוח שברצונך לשמור את הגדרת צבע שורת המשימות הנוכחית ל= \"\"ערכת <%1%>\"\"?\"\nIDS_SPECIFIC_APP = \"פתח יישום מסוים\"\nIDS_EXE_FILTER = \"יישומים|*.exe|קובצי אצווה|*.bat||\"\nIDS_PRESET = \"ערכת הגדרות\"\nIDS_LIGHT_MODE = \"מצב בהיר\"\nIDS_AUTO_ADAPT_TIP_INFO= \"פונקציה זו תחליף אוטומטית את ערכת הצבעים כאשר נושא כהה/בהיר של Windows 10 משתנה. לחץ על כפתור= \"\"הגדרות התאמה אוטומטית\"\" כדי להגדיר את ערכת ההחלפה האוטומטית.\"\nIDS_WITHOUT_TEMPERATURE= \"קל\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"חדירת עכבר מופעלת. אם ברצונך לכבות את חדירת העכבר, מצא את הסמל של TrafficMonitor באזור ההתראות של המערכת, לחץ לחיצה ימנית ובטל את חדירת העכבר בתפריט. לחץ על ביטול כדי לא להציג שוב.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"זוהה אובדן נתוני תעבורה היסטוריים. מספר הרשומות הנוכחי: <%1%>, <%2%> רשומות שוחזרו מקובץ הגיבוי.\"\nIDS_LEGEND = \"מקרא\"\nIDS_LICENSE_EXPLAIN = \"בעת שימוש בקוד המקור של תוכנה זו, יש לפעול בהתאם לרישיון הקוד הפתוח הבא.\"\nIDS_LICENSE = \"רישיון\"\nIDS_DAY_VIEW = \"תצוגת יום\"\nIDS_MONTH_VIEW = \"תצוגת חודש\"\nIDS_QUARTER_VIEW = \"תצוגת רבעון\"\nIDS_YEAR_VIEW = \"תצוגת שנה\"\nIDS_LINEAR_SCALE = \"קנה מידה ליניארי\"\nIDS_LOG_SCALE = \"קנה מידה לוגריתמי\"\nIDS_CPU_TEMPERATURE = \"טמפרטורת המעבד\"\nIDS_GPU_TEMPERATURE = \"טמפרטורת הכרטיס הגרפי\"\nIDS_CPU_FREQ = \"תדר המעבד\"\nIDS_HDD_TEMPERATURE = \"טמפרטורת הדיסק הקשיח\"\nIDS_MAINBOARD_TEMPERATURE= \"טמפרטורת לוח האם\"\nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"HDD\"\nIDS_MAINBOARD_DISP = \"MBD\"\nIDS_CPU_TEMPERATURE_EXCEED= \"טמפרטורת המעבד הגיעה למקסימום\"\nIDS_GPU_TEMPERATURE_EXCEED= \"טמפרטורת הכרטיס הגרפי הגיעה למקסימום\"\nIDS_HDD_TEMPERATURE_EXCEED= \"טמפרטורת הדיסק הקשיח הגיעה למקסימום\"\nIDS_MBD_TEMPERATURE_EXCEED= \"טמפרטורת לוח האם הגיעה למקסימום\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: נגן מוזיקה מקומי יפהפה וקל לשימוש עבור Windows\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: עורך טקסט פשוט עבור Windows\"\nIDS_COLOR = \"צבע\"\nIDS_COLOR_LABEL = \"צבע תווית\"\nIDS_COLOR_VALUE = \"צבע ערך\"\nIDS_GPU_USAGE = \"ניצול GPU\"\nIDS_IF_OPER_STATUS_UP = \"המתאם מחובר\"\nIDS_IF_OPER_STATUS_DOWN= \"המתאם אינו מחובר\"\nIDS_IF_OPER_STATUS_DORMANT= \"המתאם בתהליך התחברות\"\nIDS_GOTO_GITEE = \"עבור לעמוד הפרויקט ב-Gitee.\"\nIDS_USAGE_PERCENTAGE = \"אחוז ניצול\"\nIDS_MEMORY_USED = \"זיכרון בשימוש\"\nIDS_MEMORY_AVAILABLE = \"זיכרון זמין\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \".Net Framework v4.5.2 או גרסה חדשה יותר לא מותקן במערכת. פונקציית ניטור הטמפרטורה לא תהיה זמינה. לחץ על ביטול כדי לא להציג שוב.\"\nIDS_VERSION_UPDATE = \"עדכון לגרסה חדשה\"\nIDS_AVREAGE_TEMPERATURE= \"טמפרטורה ממוצעת\"\nIDS_HARDWARE_MONITOR_WARNING = \"אזהרה: אתה עומד להפעיל את פונקציית ניטור החומרה. פונקציה זו מאפשרת להציג מידע על טמפרטורה וניצול-GPU. אנא קרא את ההנחיות הבאות לפני הפעלת ניטור החומרה:\\r\\nTrafficMonitor אינה תוכנה מקצועית לניטור חומרה. אין התחייבות שניתן יהיה לקבל מידע חומרתי בכל מחשב, או שהמידע שיתקבל יהיה מדויק.\\r\\nפונקציית ניטור החומרה מבוססת על הספרייה החיצונית LibreHardwareMonitor. לאחר הפעלת הניטור, ייתכנו בעיות מסוימות בחלק מהמחשבים, כולל אך לא מוגבל ל:\\r\\n* שימוש חריג במעבד ובזיכרון\\r\\n* קריסת התוכנה\\r\\n* קריסת המחשב\\r\\nיש להפעיל את פונקציית ניטור החומרה רק לאחר הבנת הסיכונים הללו. \\r\\nהאם אתה בטוח שברצונך להפעיל את פונקציית ניטור החומרה?\"\nIDS_HDD_USAGE = \"ניצול הדיסק הקשיח\"\nIDS_FILE_NAME = \"שם הקובץ\"\nIDS_STATUS = \"מצב\"\nIDS_PLUGIN_LOAD_SUCCEED= \"הטעינה הצליחה\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"טעינת מודול התוסף נכשלה, קוד שגיאה: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"קבלת הפונקציה נכשלה, קוד שגיאה: <%1%>\"\nIDS_PLUGIN_INFO = \"פרטי תוסף\"\nIDS_NAME = \"שם\"\nIDS_DESCRIPTION = \"תיאור\"\nIDS_FILE_PATH = \"נתיב קובץ\"\nIDS_ITEM_NUM = \"מספר הפריטים המוצגים\"\nIDS_ITEM_NAMES = \"שמות הפריטים המוצגים\"\nIDS_AUTHOR = \"מחבר\"\nIDS_COPYRIGHT = \"זכויות יוצרים\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"התוסף אינו מספק הגדרות אפשרויות.\"\nIDS_PLUGIN_NAME = \"שם התוסף\"\nIDS_DISABLED = \"מושבת\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"אנא הפעל מחדש את התוכנה כדי להחיל שינוי זה.\"\nIDS_VERSION = \"גרסה\"\nIDS_DISP_ITEM_ID = \"מזהה הפריט המוצג\"\nIDS_PLUGIN_API_VERSION = \"גרסת API\"\nIDS_WEEK_VIEW = \"תצוגת שבוע\"\nIDS_WEEK_NUM = \"שבוע <%1%>\"\nIDS_URL = \"כתובת URL\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"גרסת התוסף ישנה מדי.\"\nIDS_MODIFY_PRESET = \"שנה ערכת הגדרות\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"אנא בחר לפחות אחד!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"כאשר פונקציית= \"\"התאמה אוטומטית לנושא כהה/בהיר של Windows 10\"\" מופעלת, אם אפשרות זו מסומנת, כאשר צבע חלון שורת המשימות או הגדרות צבע הרקע משתנים, לפי הנושא הכהה/בהיר הנוכחי של Windows, השינויים יישמרו אוטומטית לערכת ההגדרות המתאימה.\"\nIDS_TOTAL_NET_SPEED = \"מהירות כוללת\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"הצג גרפים של ניצול משאבים עבור מעבד/זיכרון, ניצול דיסק קשיח, מידע טמפרטורה ופריטי תוספים.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"הצג מחוון מהירות רשת עבור העלאה, הורדה ומהירות רשת כוללת.\"\nIDS_REFRESH_CONNECTION_LIST= \"רענן רשימת חיבורים\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"הפעלת ניטור החומרה נכשלה, ניטור החומרה לא יהיה זמין!\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"שגיאה בקבלת נתוני ניטור החומרה!\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"מצב הפעלה אוטומטית: רישום מערכת\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"מצב הפעלה אוטומטית: מתזמן משימות\"\nIDS_PATH = \"נתיב\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"הגדרת הפעלה אוטומטית עם עליית המערכת נכשלה!\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"עדכון תוכן חלון שורת המשימות נכשל, עיבוד Direct2D הושבת. הערה: חלון ההגדרות עשוי שלא לעדכן שינוי זה באופן מיידי.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"אירעה שגיאה במהלך עיבוד Direct2D ועיבוד Direct2D הושבת. הערה: חלון ההגדרות עשוי שלא לעדכן שינוי זה באופן מיידי.\"\nIDS_PLUGIN_OPTIONS = \"אפשרויות תוסף\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"קבלת ניצול המעבד על ידי מונה הביצועים נכשלה, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"מסך ראשי\"\nIDS_SECONDARY_DISPLAY = \"מסך משני <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"המערכת חזרה ממצב שינה, החיבור אופס מחדש. (<%1%> פעמים אופס מחדש.)\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"זמין עדכון, גרסה אחרונה: <%1%>\"\n\nTXT_OK = \"אישור\"\nTXT_CANCEL = \"ביטול\"\nTXT_CLOSE = \"סגור\"\nTXT_APPLY = \"החל\"\n\n; טקסט המשמש לדיאלוגים. (חייב להתחיל ב-\"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"אודות TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>, V<%2%>\"\nTXT_ABOUT_COPYRIGHT = \"זכויות יוצרים (C) 2017-2025 מאת ZhongYang\\nתאריך הקומפילציה האחרון: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%> מתרגם: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"הספריות של צד שלישי המשמשות בפרויקט זה:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"תוכנות נוספות של המחבר:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"צור קשר עם המחבר\"\nTXT_ABOUT_LICENSE = \"רישיון\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"הוקרה\"\nTXT_ABOUT_DONATE = \"תרומה\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor כבר פועל.\"\nTXT_EXIT_THE_PROGRAM = \"צא מהתוכנה\"\nTXT_OPEN_OPTION_SETTINGS = \"פתח הגדרות אפשרויות\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"הצג/הסתר חלון ראשי\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"הצג/הסתר חלון שורת המשימות\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"הגדרות התאמה אוטומטית\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"ערכת צבעים המשמשת במצב כהה של Windows:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"ערכת צבעים המשמשת במצב בהיר של Windows:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"שמור אוטומטית את הגדרות צבע חלון שורת המשימות לערכה\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"הגדרות תצוגת טקסט\"\nTXT_RESTORE_DEFAULT = \"שחזר ברירת מחדל\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"הגדרות יישום\"\nTXT_CHECK_UPDATE = \"בדוק עדכונים בעת הפעלה\"\nTXT_CHECK_NOW = \"בדוק כעת\"\nTXT_UPDATE_SOURCE = \"מקור העדכון:\"\nTXT_AUTO_RUN_CHECK = \"הפעל אוטומטית עם הפעלת Windows\"\nTXT_RESET_AUTO_RUN_BUTTON = \"אפס הפעלה אוטומטית\"\nTXT_LANGUAGE = \"שפה:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"הגדרות וקובצי נתונים\"\nTXT_SAVE_TO_APPDATA_RADIO = \"שמור בתיקיית AppData\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"שמור בתיקיית התוכנה\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"פתח תיקיית הגדרות\"\nTXT_NOTIFICATION_MESSAGE = \"הודעות מערכת\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"התרע כאשר כמות התעבורה היומית הושגה\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"התרע כאשר ניצול הזיכרון הגיע למקסימום\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"התרע כאשר טמפרטורת המעבד הגיעה למקסימום\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"התרע כאשר טמפרטורת הכרטיס הגרפי הגיעה למקסימום\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"התרע כאשר טמפרטורת הדיסק הקשיח הגיעה למקסימום\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"התרע כאשר טמפרטורת לוח האם הגיעה למקסימום\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"ניטור חומרה\"\nTXT_CPU = \"מעבד\"\nTXT_GPU = \"כרטיס גרפי\"\nTXT_HARD_DISK = \"דיסק קשיח\"\nTXT_MAIN_BOARD = \"לוח אם\"\nTXT_SELECT_HDD_STATIC = \"בחר דיסק קשיח לניטור:\"\nTXT_SELECT_CPU_STATIC = \"בחר טמפרטורת מעבד לניטור:\"\nTXT_ADVANCED = \"מתקדם\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"הצג את כל חיבורי הרשת\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"בחר חיבור לניטור...\"\nTXT_CPU_ACQUISITION_METHOD = \"שיטת קבלת נתוני המעבד:\"\nTXT_USE_CPU_TIME_RADIO = \"מבוסס על זמן מעבד\"\nTXT_USE_PDH_RADIO = \"שימוש במונה ביצועים\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"שימוש בניטור חומרה\"\nTXT_MONITORING_INTERVALS = \"מרווחי ניטור:\"\nTXT_MILLISECONDS = \"מילישניות\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"שחזר ברירת מחדל\"\nTXT_PLUGIN_MANAGE_BUTTON = \"נהל תוספים...\"\nTXT_DISPLAY = \"תצוגה\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"הצג סמל התראה\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"שנה:\"\nTXT_MONTH = \"חודש:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"סטטיסטיקות תעבורה היסטוריות\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"סוג תצוגה:\"\nTXT_FIGURE_VIEW_SCALE = \"קנה מידה של תרשים:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"שנה סמל התראה\"\nTXT_SELECT_A_ICON = \"בחר סמל:\"\nTXT_PREVIEW = \"תצוגה מקדימה\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"התאם אוטומטית לפי מצב כהה/בהיר של Windows 10\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"הגדרות צבע חלון ראשי\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"הסתר חלון ראשי כאשר התוכנה פועלת במסך מלא\"\nTXT_COLOR_AND_FONT = \"צבע וגופן\"\nTXT_FONT = \"גופן:\"\nTXT_FONT_SIZE = \"גודל גופן:\"\nTXT_SET_FONT_BUTTON = \"בחר גופן...\"\nTXT_TEXT_COLOR = \"צבע טקסט:\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"שחזר ברירת מחדל של העיצוב\"\nTXT_DISPLAY_TEXT = \"תצוגת טקסט\"\nTXT_SWITCH_UP_DOWN_CHECK = \"החלף מיקום העלאה והורדה\"\nTXT_UNIT_SETTINGS = \"הגדרות יחידות\"\nTXT_UNIT_SELECTION = \"בחירת יחידות:\"\nTXT_HIDE_UNIT_CHECK = \"אל תציג יחידת מהירות\"\nTXT_SPEED_SHORT_MODE_CHECK = \"מצב תצוגת מהירות קצר\"\nTXT_HIDE_PERCENTAGE_CHECK = \"אל תציג אחוזים\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"הגדר צבעים לכל פריט בנפרד\"\nTXT_DOUBLE_CLICK_ACTION = \"פעולה בלחיצה כפולה:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"הפרד ערך ויחידה עם רווח\"\nTXT_NETSPEED_UNIT = \"יחידת מהירות רשת:\"\nTXT_UNIT_BYTE_RADIO = \"B (בית)\"\nTXT_UNIT_BIT_RADIO = \"b (ביט)\"\nTXT_SHOW_TOOL_TIP_CHK = \"הצג הסבר צף עם העכבר\"\nTXT_EXE_PATH_STATIC = \"יישום שנבחר:\"\nTXT_BROWSE_BUTTON = \"עיון...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"הגדרות תצוגת טקסט...\"\nTXT_MEMORY_DISPLAY_MODE = \"מצב תצוגת זיכרון:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"תמיד עליון\"\nTXT_MOUSE_PENETRATE_CHECK = \"אפשר חדירת עכבר\"\nTXT_LOCK_WINDOW_POS_CHECK = \"נעל מיקום חלון\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"אפשר חריגה מגבולות המסך\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"הודעה\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"פרטי חיבור\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"הגדרות אפשרויות\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"ניהול תוספים\"\nTXT_OPTINS_BUTTON = \"אפשרויות...\"\nTXT_PLUGIN_INFO_BUTTON = \"פרטים...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"מדריך פיתוח תוספים\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"הורד תוספים נוספים\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"פתח תיקיית תוספים\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"בחר את החיבור לניטור\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"הגדרות תצוגה\"\nTXT_MOVE_UP_BUTTON = \"הזז למעלה\"\nTXT_MOVE_DOWN_BUTTON = \"הזז למטה\"\nTXT_RESTORE_DEFAULT_BUTTON = \"שחזר ברירת מחדל\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"הגדרות מעבר אוטומטי של עיצוב\"\nTXT_SKIN_IN_DARK_MODE = \"עיצוב המשמש במצב כהה של Windows:\"\nTXT_SKIN_IN_LIGHT_MODE = \"עיצוב המשמש במצב בהיר של Windows:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"שנה עיצוב\"\nTXT_PREVIEW_GROUP_STATIC = \"תצוגה מקדימה\"\nTXT_SELECT_A_SKIN = \"בחר עיצוב\"\nTXT_SKIN_AUTHOR = \"יוצר העיצוב:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"מדריך ליצירת עיצוב\"\nTXT_DOWNLOAD_MORE_SKIN = \"הורד עיצובים נוספים\"\nTXT_OPEN_SKIN_DIR = \"פתח תיקיית עיצובים\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"החלף עיצובים אוטומטית לפי מצב כהה/בהיר של Windows\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"הגדרות מעבר אוטומטי...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"הגדרות צבע חלון שורת המשימות\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"ערכת הגדרות\"\nTXT_BACKGROUND_COLOR = \"צבע רקע:\"\nTXT_BACKGROUND_TRANSPARENT = \"רקע שקוף\"\nTXT_AUTO_SET_BACK_COLOR = \"קבע את צבע הרקע באופן אוטומטי בהתאם לצבע שורת המשימות\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"הסתגל אוטומטית לנושאים כהים/בהירים של Windows 10\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"הגדרות התאמה אוטומטית...\"\nTXT_DISPLAY_SETTINGS = \"הגדרות תצוגה\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"הגדרות תצוגה...\"\nTXT_SPEED_SHORT_MODE = \"מצב תצוגת מהירות רשת קצר\"\nTXT_VALUE_RIGHT_ALIGN = \"ישר ערכים לימין\"\nTXT_NET_SPEED_DATA_WIDTH = \"רוחב נתוני מהירות הרשת:\"\nTXT_CHARACTORS = \"תווים\"\nTXT_HORIZONTAL_ARRANGE = \"סידור אופקי\"\nTXT_ITEM_SPACING = \"ריווח פריטים:\"\nTXT_VERTICAL_MARGIN = \"שוליים אנכיים:\"\nTXT_PIXELS = \"פיקסלים\"\nTXT_TASKBAR_WINDOW = \"חלון שורת המשימות\"\nTXT_TASKBAR_WND_ON_LEFT = \"הצג חלון שורת המשימות משמאל לשורת המשימות\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"המסך להצגת חלון שורת המשימות:\"\nTXT_WIN11_SETTINGS_BUTTON = \"הגדרות הקשורות ל-Windows 11\"\nTXT_RESOURCE_USAGE_GRAPH = \"גרף ניצול משאבים\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"הצג גרף ניצול משאבים\"\nTXT_SHOW_DASHED_BOX = \"הצג מסגרת מקווקוות\"\nTXT_SHOW_NET_SPEED_GRAPH = \"הצג גרף מהירות רשת\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"ערך מקסימלי של גרף מהירות הרשת:\"\nTXT_USAGE_GRAPH_COLOR = \"צבע גרף הניצול:\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"התאם לצבע ערכת הנושא של Windows\"\nTXT_GRAPH_DISPLAY_MODE = \"מצב תצוגת גרף:\"\nTXT_BAR_MODE = \"מצב עמודות\"\nTXT_PLOT_MODE = \"מצב תרשים קווי\"\nTXT_RENDERING_SETTINGS = \"הגדרות עיבוד גרפי\"\nTXT_RENDERING_SETTINGS_NOTE = \"הערה: עיבוד Direct2D משמש רק כאשר האפשרות \"\"רקע שקוף\"\" מסומנת, אך האפשרות \"\"קבע את צבע הרקע באופן אוטומטי בהתאם לצבע שורת המשימות\"\" אינה מסומנת.\"\nTXT_ENABLE_COLOR_EMOJI = \"אפשר אימוג'י צבעוני\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"הגדרות הקשורות ל-Windows 11\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"חלון שורת המשימות מוצמד לאייקון במקום לצדדים של שורת המשימות\"\nTXT_WINDOW_VERTICAL_OFFSET = \"היסט אנכי של החלון:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"היסט אופקי של החלון:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"מנע חפיפה עם ווידג'טים בצד ימין (סמן אפשרות זו אם הווידג'טים מופיעים בצד ימין של שורת המשימות)\"\nTXT_WIDGETS_WIDTH = \"רוחב הווידג'טים:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"הצג קנה מידה\"\nTXT_USE_LINEAR_SCALE = \"השתמש בקנה מידה ליניארי\"\nTXT_USE_LOG_SCALE = \"השתמש בקנה מידה לוגריתמי\"\nTXT_FIRST_DAT_OF_WEEEK = \"היום הראשון בשבוע\"\nTXT_SUNDAY = \"ראשון\"\nTXT_MONDAY = \"שני\"\nTXT_GO_TO_TODAY = \"עבור להיום\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"העתק טקסט\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"בחר חיבורי רשת\"\nTXT_AUTO_SELECT = \"בחר אוטומטית\"\nTXT_SELECT_ALL = \"בחר הכל\"\nTXT_CONNECTION_DETAILS = \"פרטי חיבור\"\nTXT_ALWAYS_ON_TOP = \"תמיד עליון\"\nTXT_MOUSE_PENETRATE = \"הפעל חדירת עכבר\"\nTXT_LOCK_WINDOW_POS = \"נעל מיקום חלון\"\nTXT_SHOW_MORE_INFO = \"הצג מידע נוסף\"\nTXT_SHOW_TASKBAR_WINDOW = \"הצג חלון שורת המשימות\"\nTXT_SHOW_MAIN_WINDOW = \"הצג חלון ראשי\"\nTXT_WINDOW_OPACITY = \"שקיפות חלון\"\nTXT_OTHER_FUNCTIONS = \"פונקציות נוספות\"\nTXT_CHANGE_SKIN = \"שנה עיצוב...\"\nTXT_CHANGE_NOTIFY_ICON = \"שנה סמל התרעה...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"אפשר יציאה מחוץ לגבולות המסך\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"סטטיסטיקת תעבורה היסטורית\"\nTXT_PLUGIN_MANAGE = \"ניהול תוספים...\"\nTXT_OPTIONS = \"אפשרויות...\"\nTXT_HELP_MENU = \"עזרה\"\nTXT_HELP = \"עזרה\"\nTXT_FAQ = \"שאלות נפוצות\"\nTXT_UPDATE_LOG = \"יומן עדכונים\"\nTXT_ABOUT = \"אודות...\"\nTXT_CHECK_UPDATE = \"בדוק עדכון...\"\nTXT_EXIT = \"יציאה\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"הגדרות תצוגה...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"סגור חלון שורת המשימות\"\nTXT_TASK_MANAGER = \"מנהל המשימות\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"פרטים...\"\nTXT_PLUGIN_OPTIONS = \"אפשרויות...\"\nTXT_PLUGIN_DISABLE = \"השבת\"\n"
  },
  {
    "path": "TrafficMonitor/language/Hungarian.ini",
    "content": "﻿[general]\nBCP_47 = \"hu-HU\"\nDISPLAY_NAME = \"Magyar\"\nTRANSLATOR = \"John Fowler\"\nTRANSLATOR_URL = \"\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"A frissítés ellenőrzése sikertelen, kérjük, ellenőrizze a hálózati kapcsolatot!\"\nIDS_CHECK_UPDATE_ERROR = \"A frissítés ellenőrzése sikertelen volt, és hibás információkat kapott a távoli frissítési fájlból. Kérjük, vegye fel a kapcsolatot a szerzővel!\"\nIDS_UPDATE_AVLIABLE = \"Új verziót v%s észleltem, akarja frissíteni?\"\nIDS_UPDATE_AVLIABLE2 = \"Új verzió V%s észlelve, tartalom frissítése: \\r\\n%s\\r\\nFrissíteni szeretné?\"\nIDS_ALREADY_UPDATED = \"Már frissítve a legújabb verzióra.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"A Windows indításakor nem lehet automatikusan futtatni a programo, a rendszerleíró adatbázisban nem található meg a megfelelő kulcs.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"A rendszerleíró kulcs írása sikertelen, lehet, hogy nincs engedélye a kulcs eléréséhez!\"\nIDS_AUTORUN_DELETE_FAILED = \"A rendszerleíró kulcs törlése sikertelen, lehet, hogy nincs engedélye a kulcs eléréséhez!\"\nIDS_AN_INSTANCE_RUNNING= \"Már fut egy példány.\"\nIDS_TRAFFIC_USED_TODAY = \"Ma használt forgalom\"\nIDS_MEMORY_USAGE = \"Memóriahasználat\"\nIDS_CPU_USAGE = \"CPU használat\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Küldjön e-mailt a szerzőnek.\"\nIDS_GOTO_GITHUB = \"Nyissa meg a GitHub oldalát ehhez a projekthez.\"\nIDS_DONATE_ATHOUR = \"Támogassa a szerzőt\"\nIDS_UPLOAD = \"Feltöltés\"\nIDS_DOWNLOAD = \"Letöltés\"\nIDS_MEMORY = \"Memória\"\nIDS_UPLOAD_DISP = \"FEL\"\nIDS_DOWNLOAD_DISP = \"LE\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"Figyelmeztetés: Nem lehet menteni a beállításokat, nem lehet adatokat írni a fájlba= \"\"<%file_path%>\"\"! A program rendszergazdaként való futtatása megoldhatja ezt a problémát.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"A kapcsolati információk tárolására használt puffer mérete nem elegendő, a kapcsolat újrainicializálása megtörtént. (<%cnt%> az időzítés újraindítva)\"\nIDS_CONNECTION_NUM_CHANGED = \"A rendszer észlelte a kapcsolatszám változását. A kapcsolat lekérésre került. Korábbi kapcsolatok: <%before%>, jelenlegi kapcsolatok: <%after%>. (<%cnt%> az időzítés újraindítva)\"\nIDS_CONNECTION_NOT_MATCH = \"Kivétel történt, az aktuálisan kiválasztott kapcsolat nem konzisztens a várt kapcsolattal. A kapcsolat lekérése megtörtént. (<%cnt%> az időzítés újraindítva)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"Az ablak nem sikerült beágyazódni a tálcába, lehet, hogy biztonsági szoftver blokkolja, vagy a Start menü nincs bezárva. Kérjük, próbálja meg újraindítani az Explorer programot. A TrafficMonitor továbbra is próbálkozni fog, de nem fog többé figyelmeztetni, hibakód:\"\nIDS_MEMORY_UDAGE_EXCEED= \"A memóriahasználat elérte a maximumot.\"\nIDS_NOTIFY = \"Értesítés\"\nIDS_TODAY_TRAFFIC_EXCEED = \"A ma használt forgalom elérte a maximumot\"\nIDS_DATE = \"Dátum\"\nIDS_TRAFFIC_USED = \"Teljes forgalom\"\nIDS_FIGURE = \"Alakzat\"\nIDS_DEFAULT_ICON = \"Alapértelmezett ikon\"\nIDS_ICON = \"Ikon\"\nIDS_INTERFACE_NAME = \"Interfész neve\"\nIDS_INTERFACE_DESCRIPTION= \"Interfész leírása\"\nIDS_CONNECTION_TYPE = \"Kapcsolat típusa\"\nIDS_IF_TYPE_OTHER = \"Egyéb típusú hálózat\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"Ethernet hálózat\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Token gyűrű hálózat\"\nIDS_IF_TYPE_FDDI = \"Fiber Distributed Data Interface (FDDI) hálózat\"\nIDS_IF_TYPE_PPP = \"PPP hálózat\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"Szoftveres visszacsatolási hálózat\"\nIDS_IF_TYPE_ATM = \"ATM hálózat\"\nIDS_IF_TYPE_IEEE80211 = \"IEEE 802.11 Vezeték nélküli hálózat\"\nIDS_IF_TYPE_TUNNEL = \"Alagút típusú kapszulázó hálózat\"\nIDS_IF_TYPE_IEEE1394 = \"IEEE 1394 (Firewire) nagy teljesítményű soros buszhálózat\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"Mobil szélessávú interfész WiMax eszközökhöz\"\nIDS_IF_TYPE_WWANPP = \"Mobil szélessávú interfész GSM alapú eszközökhöz\"\nIDS_IF_TYPE_WWANPP2 = \"Mobil szélessávú interfész CDMA-alapú eszközökhöz\"\nIDS_UNKNOW_CONNECTION = \"Ismeretlen hálózat\"\nIDS_SPEED = \"Sebesség\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"Adapter fizikai címe\"\nIDS_IP_ADDRESS = \"IP cím\"\nIDS_SUBNET_MASK = \"Alhálózati maszk\"\nIDS_DEFAULT_GATEWAY = \"Alapértelmezett átjáró\"\nIDS_OPERATIONAL_STATUS = \"Kapcsolat állapota\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"A LAN-adapter le van tiltva\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"Nincs csatlakoztatva a WAN adapter\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"hálózati kábel nincs csatlakoztatva vagy nincs hordozó\"\nIDS_IF_OPER_STATUS_CONNECTING = \"WAN adapter, amely csatlakozás alatt áll\"\nIDS_IF_OPER_STATUS_CONNECTED = \"Távoli társhoz csatlakoztatott WAN-adapter\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"LAN-adapterek csatlakoztatva vannak\"\nIDS_UNKNOW_STATUS = \"Ismeretlen állapot\"\nIDS_BYTES_RECEIVED = \"Fogadott bájtok\"\nIDS_BYTES_SENT = \"Küldött bájtok\"\nIDS_BYTES_RECEIVED_SINCE_START= \"A program kezdete óta kapott bájtok\"\nIDS_BYTES_SENT_SINCE_START= \"A program kezdete óta küldött bájtok\"\nIDS_PROGRAM_ELAPSED_TIME= \"Program indításától eltelt idő\"\nIDS_HOUR_MINUTE_SECOND = \"%d óra, %d perc, %d másodperc\"\nIDS_INTERNET_IP_ADDRESS= \"Internet IP cím\"\nIDS_GET_FAILED = \"Sikertelen\"\nIDS_ITEM = \"Elem\"\nIDS_VALUE = \"Érték\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"A vágólapra másolás sikertelen!\"\nIDS_SKIN_AUTHOUR = \"Skin szerzője:\"\nIDS_SPEED_SHORT_MODE_TIP = \"Ha be van jelölve, a hálózati sebesség kijelzése 1 tizedesjegyre csökken, és az egység nem jelenik meg= \"\"B\"\".\"\nIDS_AUTO = \"Automatikus\"\nIDS_FIXED_AS = \"Rögzítve\"\nIDS_OPEN_CONNECTION_DETIAL= \"Nyissa meg a kapcsolat részleteit\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"Korábbi forgalmi statisztikák megnyitása\"\nIDS_SHOW_HIDE_MORE_INFO= \"További információk megjelenítése/elrejtése\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"CPU- és memóriahasználat megjelenítése/elrejtése\"\nIDS_OPEN_OPTION_SETTINGS= \"Beállítások megnyitása\"\nIDS_OPEN_TASK_MANAGER = \"Nyissa meg a feladatkezelőt\"\nIDS_CHANGE_SKIN = \"Skin megváltoztatása\"\nIDS_NONE = \"Nincs\"\nIDS_FONT_SIZE_WARNING = \"A betűméretnek %d és %d között kell lennie.!\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"Figyelmeztetés: A szöveg színe megegyezik a háttér színével.!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"Figyelmeztetés: A háttérszín megegyezik a szöveg színével.!\"\nIDS_FOLLOWING_SYSTEM = \"Következő rendszer\"\nIDS_LANGUAGE_CHANGE_INFO = \"Kérjük, indítsa újra az alkalmazást a nyelvi beállítás alkalmazásához.\"\nIDS_MAIN_WINDOW_SETTINGS= \"Főablak beállításai\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"A tálca ablakának beállításai\"\nIDS_GENERAL_SETTINGS = \"Általános beállítások\"\nIDS_ACQUIRING = \"Beszerzés\"\nIDS_LIST_VIEW = \"Listanézet\"\nIDS_CALENDAR_VIEW = \"Naptári nézet\"\nIDS_MONDAY = \"Hét\"\nIDS_TUESDAY = \"Ked\"\nIDS_WEDNESDAY = \"Sze\"\nIDS_THURSDAY = \"Csü\"\nIDS_FRIDAY = \"Pén\"\nIDS_SATURDAY = \"Szo\"\nIDS_SUNDAY = \"Vas\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"Az aktuális havi teljes forgalom:\"\nIDS_TRAFFIC_USED1 = \"Használt forgalom:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Nem sikerült beszúrni a tálcára, próbálkozzon újra <%cnt%> alkalommal. GetLastError(): <%error_code%>.\"\nIDS_NO_CONNECTION = \"Nincs kapcsolat\"\nIDS_CONTACT_TRANSLATOR = \"Vegye fel a kapcsolatot ezzel a fordítóval.\"\nIDS_THANKS_DONORS = \"Köszönet a következő adományozóknak:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"Hiba történt a kérés során= \"\"<%1%>\"\", hibakód: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"WHa ez az elem be van jelölve, az összes hálózati interfész megjelenik a= \"\"Válassza a Hálózati kapcsolatok lehetőséget\"\"lista a jobb egérgomb menüjében. Javasoljuk, hogy ezt az elemet csak szükség esetén ellenőrizze.\"\nIDS_CFG_DIR_CHANGED_INFO = \"Megváltoztatta a konfigurációs és adatfájlok mentési helyét. Az újraindítás után lép életbe. Előfordulhat, hogy manuálisan kell átvinnie a konfigurációt és az adatfájlokat az új helyre.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<Kattintson duplán ide a beszerzéshez.>\"\nIDS_ERROR1 = \"Hiba\"\nIDS_ERROR_MESSAGE = \"Hibaüzenet:\"\nIDS_CRASH_INFO = \"Sajnáljuk, a program összeomlott. Kérjük, indítsa újra a programot. \\r\\nHa ez a probléma többször is előfordul, próbálja meg letiltani a hardverfigyelő funkciót az = \"\"Opciók\"\" >= \"\"Általános beállítások\"\" menüpontban, és tiltsa le az összes bővítményt a = \"\"Bővítménykezelő\"\" párbeszédpanelen. \\r\\nHa a probléma továbbra is fennáll, kérjük, küldje el ezt a fájlt= \"\"<%1%>\"\" e-mailben a bugreport-zhongyang219@outlook.com címre, hogy a szerző meg tudja találni a probléma forrását. Az üzenet szövegébe írja be a következőket:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"Elismerés\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Biztosan el akarja menteni a tálca aktuális színbeállítását= \"\"Előbeállítás <%1%>\"\"?\"\nIDS_SPECIFIC_APP = \"Nyissa meg a megadott alkalmazást\"\nIDS_EXE_FILTER = \"Alkalmazások|*.exe|Kötegelt fájlok|*.bat||\"\nIDS_PRESET = \"Előbeállítás\"\nIDS_LIGHT_MODE = \"Világos mód\"\nIDS_AUTO_ADAPT_TIP_INFO= \"Ez a funkció automatikusan váltja a színbeállításokat, amikor a Windows 10 sötét/világos témája megváltozik. Kattintson az \"\"Automatikus Adapter beállítások\"\" gombra az automatikus váltáshoz szükséges beállítások konfigurálásához.\"\nIDS_WITHOUT_TEMPERATURE= \"Kicsi\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"Az egér áthatolása be van kapcsolva. Ha ki szeretné kapcsolni az egér áthatolását, keresse meg a trafficMonitor ikont a rendszer értesítési területén, kattintson a jobb egérgombbal, és kapcsolja ki az egér áthatolását a menüben. Kattintson a Mégse gombra.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"Történelmi forgalmi adatvesztés észlelve. A jelenlegi rekordok száma: <%1%>, <%2%> rekordot sikerült helyreállítani a biztonsági másolatból.\"\nIDS_LEGEND = \"Jelmagyarázat \"\nIDS_LICENSE_EXPLAIN = \"Kérjük, kövesse az alábbi nyílt forráskódú protokollt ennek a szoftvernek a forráskódjának használata során..\"\nIDS_LICENSE = \"Licensz\"\nIDS_DAY_VIEW = \"Napi nézet\"\nIDS_MONTH_VIEW = \"Havi nézet\"\nIDS_QUARTER_VIEW = \"Negyedéves nézet\"\nIDS_YEAR_VIEW = \"Éves nézet\"\nIDS_LINEAR_SCALE = \"Lineáris skála\"\nIDS_LOG_SCALE = \"Logaritmikus skála\"\nIDS_CPU_TEMPERATURE = \"CPU Hőmérséklet\"\nIDS_GPU_TEMPERATURE = \"GPU Hőmérséklet\"\nIDS_CPU_FREQ = \"CPU Frekvencia\"\nIDS_HDD_TEMPERATURE = \"Merevlemez hőmérséklet\"\nIDS_MAINBOARD_TEMPERATURE= \"Alaplap hőmérséklet\"\nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"HDD\"\nIDS_MAINBOARD_DISP = \"MBD\"\nIDS_CPU_TEMPERATURE_EXCEED= \"A CPU hőmérséklete elérte\"\nIDS_GPU_TEMPERATURE_EXCEED= \"A GPU hőmérséklete elérte\"\nIDS_HDD_TEMPERATURE_EXCEED= \"A merevlemez hőmérséklete elérte\"\nIDS_MBD_TEMPERATURE_EXCEED= \"Az alaplap hőmérséklete elérte\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: Gyönyörű és könnyen használható helyi zenelejátszó Windowshoz\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: Egy egyszerű szövegszerkesztő Windowshoz\"\nIDS_COLOR = \"Szín\"\nIDS_COLOR_LABEL = \"Címke színe\"\nIDS_COLOR_VALUE = \"Érték színe\"\nIDS_GPU_USAGE = \"GPU használat\"\nIDS_IF_OPER_STATUS_UP = \"Az adapter csatlakoztatva van\"\nIDS_IF_OPER_STATUS_DOWN= \"Az adapter nincs csatlakoztatva\"\nIDS_IF_OPER_STATUS_DORMANT= \"Az adapter csatlakozik\"\nIDS_GOTO_GITEE = \"Ugrás a Gitee oldalára ehhez a projekthez.\"\nIDS_USAGE_PERCENTAGE = \"Felhasznált százalék\"\nIDS_MEMORY_USED = \"Használt memória\"\nIDS_MEMORY_AVAILABLE = \"Elérhető memória\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \"A .Net Framework 4.5.2-es vagy újabb verziója nincs telepítve a rendszerben. A hőmérséklet-figyelő funkció nem lesz elérhető. Kattintson a Mégse gombra, ha a továbbiakban nem kéri.\"\nIDS_VERSION_UPDATE = \"Új verzió frissítés\"\nIDS_AVREAGE_TEMPERATURE= \"Átlaghőmérséklet\"\nIDS_HARDWARE_MONITOR_WARNING = \"Figyelem: A hardverfigyelő funkciót kapcsolja be. A hardverfigyelő funkcióval megjelenítheti a hőmérsékletet és a GPU használatát. A hardverfigyelő funkció bekapcsolása előtt kérjük, figyelmesen olvassa el az alábbiakat:\\r\\nA TrafficMonitor nem professzionális hardverfigyelő szoftver. Nem garantálja, hogy minden számítógépen megszerezhetőek a hardveradatok, és nem garantálja a megszerezhető hardveradatok pontosságát sem.\\r\\nA hardverfigyelő funkciót a LibreHardwareMonitor nevű harmadik féltől származó könyvtár valósítja meg. A hardverfigyelő funkció bekapcsolása után egyes számítógépeken problémák léphetnek fel, többek között:\\r\\n* Rendellenes CPU- és memóriahasználat\\r\\n* Programleállás\\r\\n* Számítógép leállás\\r\\nKérjük, csak akkor kapcsolja be a hardverfigyelő funkciót, ha tisztában van a fenti kockázatokkal. \\r\\nTényleg be akarja kapcsolni a hardverfigyelő funkciót?\"\nIDS_HDD_USAGE = \"Merevlemez-használat\"\nIDS_FILE_NAME = \"Fájlnév\"\nIDS_STATUS = \"Állapot\"\nIDS_PLUGIN_LOAD_SUCCEED= \"A betöltés sikeres\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"A beépülő modul betöltése sikertelen, hibakód: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"A funkció megszerzése sikertelen, hibakód: <%1%>\"\nIDS_PLUGIN_INFO = \"Beépülő modul részletek\"\nIDS_NAME = \"Név\"\nIDS_DESCRIPTION = \"Leírás\"\nIDS_FILE_PATH = \"Fájl elérési útja\"\nIDS_ITEM_NUM = \"Megjelenített elemek száma\"\nIDS_ITEM_NAMES = \"Megjelenített elemek nevei\"\nIDS_AUTHOR = \"Szerző\"\nIDS_COPYRIGHT = \"Szerzői jog\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"A beépülő modul nem biztosít opcióbeállításokat.\"\nIDS_PLUGIN_NAME = \"Beépülő modul neve\"\nIDS_DISABLED = \"Letiltva\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Kérjük, indítsa újra a programot a módosítás alkalmazásához.\"\nIDS_VERSION = \"Verzió\"\nIDS_DISP_ITEM_ID = \"Megjelenített elem ID\"\nIDS_PLUGIN_API_VERSION = \"API verzió\"\nIDS_WEEK_VIEW = \"Heti nézet\"\nIDS_WEEK_NUM = \"Hét <%1%>\"\nIDS_URL = \"Url\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"A plug-in verzió túl alacsony.\"\nIDS_MODIFY_PRESET = \"Előbeállítás módosítása\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"Kérjük, válasszon ki legalább egyet!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"Ha az \"\"Automatikus alkalmazkodás a Windows 10 sötét/világos témájához\"\" funkció engedélyezve van, és ez az opció be van jelölve, akkor a tálca ablak színének és háttérszínének beállításainak megváltoztatásakor a rendszer automatikusan elmenti a megfelelő előre beállított értékeket a Windows aktuális sötét/világos témájának megfelelően.\"\nIDS_TOTAL_NET_SPEED = \"Teljes sebesség\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"Erőforrás-használati grafikonok megjelenítése a CPU/memória merevlemez-kihasználtságáról, a hőmérsékleti információkról és a bővítmény elemeiről.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"Megjeleníti a nettó sebesség jelzőjét feltöltéskor, letöltéskor és teljes nettó sebességnél.\"\nIDS_REFRESH_CONNECTION_LIST= \"Kapcsolatlista frissítése\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"A hardverfigyelő funkció inicializálása nem sikerült, a hardverfigyelés nem lesz elérhető!\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Hiba a hardveres monitorozási adatok lekérése során!\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"Automatikus futtatási mód : Rendszerleíró adatbázis\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"Automatikus futtatási mód: Feladatütemezés\"\nIDS_PATH = \"Elérési útvonal\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"Az automatikus futtatás beállítása indításkor sikertelen!\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Nem sikerült frissíteni a tálcaablak tartalmát, a direct2d renderelés le van tiltva. Megjegyzés: előfordulhat, hogy a beállítások ablak nem frissíti azonnal ezt a beállítást.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Hiba történt a direct2d renderelés során, és a direct2d renderelés le van tiltva. Megjegyzés: előfordulhat, hogy a beállítások ablak nem frissíti azonnal ezt a beállítást.\"\nIDS_PLUGIN_OPTIONS = \"Bővítmény opciók\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"CPU-használat lekérése teljesítményszámláló szerint sikertelen, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"Elsődleges kijelző\"\nIDS_SECONDARY_DISPLAY = \"Másodlagos kijelző <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"A rendszer helyreállt a hibernált állapotból, a kapcsolat újrainicializálódott. (<%1%> az időzítés újraindítva.)\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"Update available, latest version: <%1%>\"\nIDS_TRAFFICMONITOR_PLUGIN_NITIFICATION = \"TrafficMonitor beépülő modul értesítése\"\n\nTXT_OK = \"OK\"\nTXT_CANCEL = \"Mégse\"\nTXT_CLOSE = \"Bezárás\"\nTXT_APPLY = \"Alkalmaz\"\n\n; Text used for dialog. (Must be started with \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"TrafficMonitor névjegye\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>, V<%2%>\"\nTXT_ABOUT_COPYRIGHT = \"Szerzői jog (C) 2017-2025 Írta: ZhongYang\\nUtolsó összeállítás dátuma: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%> Fordító: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"A projektben használt harmadik féltől származó könyvtárak:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"A szerző egyéb szoftvere:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"Kapcsolat szerzővel\"\nTXT_ABOUT_LICENSE = \"Licensz\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"Elismerés\"\nTXT_ABOUT_DONATE = \"Támogatás\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"A TrafficMonitor már fut.\"\nTXT_EXIT_THE_PROGRAM = \"&Kilépés a programból\"\nTXT_OPEN_OPTION_SETTINGS = \"Beállítások meg&nyitása\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"Főablak &megjelenítése/elrejtése\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"&Tálcaablak megjelenítése/elrejtése\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Beállítások automatikus adaptálása\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Windows sötét módban használt színbeállítása:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Windows világos módban használt színbeállítása:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"A tálca ablak színének beállításait automatikusan mentse az előbeállítási értékekhez\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Szövegbeállítások megjelenítése\"\nTXT_RESTORE_DEFAULT = \"Visszaállítás alapértelmezettre  min&den felhasználónak\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Alkalmazás beállításai\"\nTXT_CHECK_UPDATE = \"Frissítés keresése indításkor\"\nTXT_CHECK_NOW = \"&Ellenőrizze most\"\nTXT_UPDATE_SOURCE = \"Frissítés forrása:\"\nTXT_AUTO_RUN_CHECK = \"Automatikus futtatás a Windows indításakor\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Automatikus indítás visszaállítása\"\nTXT_LANGUAGE = \"Nyelv:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"Konfiguráció és adatfájlok\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Mentés az Appdata könyvtárba\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Mentés a programkönyvtárba\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Konfigurációs fájlkönyvtár meg&nyitása\"\nTXT_NOTIFICATION_MESSAGE = \"Értesítő üzenet\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"Értesítés a mai forgalom elérésekor\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"Értesítés a memóriahasználat elérésekor\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"Értesítés a CPU hőmérsékletének elérésekor\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"Értesítés a GPU hőmérsékletének elérésekor\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"Értesítés a merevlemez hőmérsékletének elérésekor\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"Értesítés az alaplap hőmérsékletének elérésekor\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Hardver felügyelet\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"GPU\"\nTXT_HARD_DISK = \"Merevlemez\"\nTXT_MAIN_BOARD = \"Alaplap\"\nTXT_SELECT_HDD_STATIC = \"Válassza ki a figyelni kívánt merevlemezt:\"\nTXT_SELECT_CPU_STATIC = \"Válassza ki a figyelni kívánt CPU hőmérsékletet:\"\nTXT_ADVANCED = \"Továbbiak\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Az összes hálózati kapcsolat megjelenítése\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"&Válassza ki a figyelni kívánt kapcsolatot...\"\nTXT_CPU_ACQUISITION_METHOD = \"CPU-használat mérési módszer:\"\nTXT_USE_CPU_TIME_RADIO = \"CPU-idő alapján\"\nTXT_USE_PDH_RADIO = \"A teljesítményszámláló használata\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"A hardvermonitor használata\"\nTXT_MONITORING_INTERVALS = \"Felügyeleti intervallumok:\"\nTXT_MILLISECONDS = \"ezredmásodperc\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"&Visszaállítás alapértelmezettre\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Plug-in kezelés...\"\nTXT_DISPLAY = \"Kijelző\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"Értesítés iko&n megjelenítése\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Év:\"\nTXT_MONTH = \"Hónap:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Korábbi forgalmi statisztikák\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"Nézet típusa:\"\nTXT_FIGURE_VIEW_SCALE = \"Ábranézeti lépték:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Értesítés ikon módosítása\"\nTXT_SELECT_A_ICON = \"Válasszon egy ikont:\"\nTXT_PREVIEW = \"Előnézet\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Automatikus alkalmazkodás a Windows 10/11 sötét/világos módjával\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Főablak színbeállításai\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Főablak elrejtése, ha a program teljes képernyőn fut\"\nTXT_COLOR_AND_FONT = \"Szín és betűtípus\"\nTXT_FONT = \"Betűtípus:\"\nTXT_FONT_SIZE = \"Betűméret:\"\nTXT_SET_FONT_BUTTON = \"Válasszon &betűtípust...\"\nTXT_TEXT_COLOR = \"Szöveg színe:\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"Alapé&rtelmezett szkin visszaállítása\"\nTXT_DISPLAY_TEXT = \"Mejelenő szöveg\"\nTXT_SWITCH_UP_DOWN_CHECK = \"A feltöltés és a letöltés pozíciójának felcserélése\"\nTXT_UNIT_SETTINGS = \"Egység beállításai\"\nTXT_UNIT_SELECTION = \"Egység kiválasztása:\"\nTXT_HIDE_UNIT_CHECK = \"Ne jelenítse meg a sebesség mértékegységét\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Rövid mód a hálózati sebesség megjelenítéséhez\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Ne mutasson százalékot\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Adja meg az egyes elemek színeit\"\nTXT_DOUBLE_CLICK_ACTION = \"Dupla kattintás művelet:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Az értéket és az egységet térközzel válassza el egymástól.\"\nTXT_NETSPEED_UNIT = \"Hálózati sebesség egység:\"\nTXT_UNIT_BYTE_RADIO = \"B (Bájt)\"\nTXT_UNIT_BIT_RADIO = \"b (bit)\"\nTXT_SHOW_TOOL_TIP_CHK = \"Egér eszköztippjének megjelenítése\"\nTXT_EXE_PATH_STATIC = \"Meghatározott alkalmazás:\"\nTXT_BROWSE_BUTTON = \"&Tallózás ...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Megjelenő szöveg beállításai...\"\nTXT_MEMORY_DISPLAY_MODE = \"Memória megjelenítési mód:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Mindig előtérben\"\nTXT_MOUSE_PENETRATE_CHECK = \"Rámutatás egérrel\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Ablak pozíciójának zárolása\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Képernyőhatáron kívüli megjelenítés engedélyezése\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Üzenet\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Csatlakozás részletei\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Beállítási lehetőségek\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Plug-in kezelő\"\nTXT_OPTINS_BUTTON = \"&Beállítások...\"\nTXT_PLUGIN_INFO_BUTTON = \"&Részletek...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Beépülő modulok fejlesztési útmutatója\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"További bővítmények letöltése\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Nyissa meg a bővítménykönyvtárat\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Válassza ki a figyelni kívánt kapcsolatot\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Kijelző beállításai\"\nTXT_MOVE_UP_BUTTON = \"Feljebb\"\nTXT_MOVE_DOWN_BUTTON = \"Lejjebb\"\nTXT_RESTORE_DEFAULT_BUTTON = \"&Visszaállítás alapértelmezettre\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Szkin automatikus váltási beállításai\"\nTXT_SKIN_IN_DARK_MODE = \"Sötét Windows módban használt szkin:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Világos Windows módban használt szkin:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Szkin módosítása\"\nTXT_PREVIEW_GROUP_STATIC = \"Előnézet\"\nTXT_SELECT_A_SKIN = \"Válasszon ki egy szkint\"\nTXT_SKIN_AUTHOR = \"Szkin szerző:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Szkin készítési útmutató\"\nTXT_DOWNLOAD_MORE_SKIN = \"További szkinek letöltése\"\nTXT_OPEN_SKIN_DIR = \"Szkin könyvtár megnyitása\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Szkinek automatikus váltása a Windows sötét / világos színmódjai szerint.\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Automatikus váltási beállítások...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"A tálcaablak színbeállításai\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Előbeállítás\"\nTXT_BACKGROUND_COLOR = \"Háttérszín:\"\nTXT_BACKGROUND_TRANSPARENT = \"Átlátszó háttér\"\nTXT_AUTO_SET_BACK_COLOR = \"A háttérszín automatikus beállítása a tálca színének megfelelően\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Automatikus alkalmazkodás a Windows 10/11 sötét/világos témáihoz\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"Beállítások automatikus adaptálása...\"\nTXT_DISPLAY_SETTINGS = \"Megjelenítés beállításai\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"&Megjelenítési beállítások...\"\nTXT_SPEED_SHORT_MODE = \"Rövid mód a hálózati sebesség megjelenítéséhez\"\nTXT_VALUE_RIGHT_ALIGN = \"Értékek jobbra igazítása\"\nTXT_NET_SPEED_DATA_WIDTH = \"Nettó sebesség adatszélessége:\"\nTXT_CHARACTORS = \"karakterek\"\nTXT_HORIZONTAL_ARRANGE = \"Vízszintes elrendezés\"\nTXT_ITEM_SPACING = \"Elemek térköze:\"\nTXT_VERTICAL_MARGIN = \"Függőleges margó:\"\nTXT_PIXELS = \"képpont \"\nTXT_TASKBAR_WINDOW = \"Tálca ablak\"\nTXT_TASKBAR_WND_ON_LEFT = \"A tálcaablak a tálca bal oldalán jelenik meg.\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"A tálcaablak megjelenítésére szolgáló kijelző:\"\nTXT_WIN11_SETTINGS_BUTTON = \"A Windows11-hez kapcsolódó beállítások\"\nTXT_RESOURCE_USAGE_GRAPH = \"Erőforrás-használati grafikon\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Erőforrás-használati grafikon megjelenítése\"\nTXT_SHOW_DASHED_BOX = \"Szaggatott mező megjelenítése\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Hálózati sebesség grafikon mefjelenítése\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"Hálózati sebesség grafikon maximális értéke:\"\nTXT_USAGE_GRAPH_COLOR = \"Használat grafikon színe:\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"A Windows témaszín követése\"\nTXT_GRAPH_DISPLAY_MODE = \"Grafikon megjelenítési mód:\"\nTXT_BAR_MODE = \"Sáv mód\"\nTXT_PLOT_MODE = \"Nyomtatási mód\"\nTXT_RENDERING_SETTINGS = \"Renderelési beállítások\"\nTXT_RENDERING_SETTINGS_NOTE = \"Megjegyzés: A Direct2D renderelés csak akkor használatos, ha a \"\"Háttér átlátszó\"\" opció be van jelölve, de a \"\"A háttér színének automatikus beállítása a tálca színének megfelelően\"\" opció nincs bejelölve.\"\nTXT_ENABLE_COLOR_EMOJI = \"Színes hangulatjelek engedélyezése\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"A Windows11-hez kapcsolódó beállítások\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"A tálca ablaka az ikon mellett található, nem pedig a tálca oldalán.\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Ablak függőleges eltolása:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Ablak vízszintes eltolása:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Kerülje az átfedést a jobb oldali widgetekkel (jelölje be ezt a lehetőséget, ha a Widgetek a tálca jobb oldalán jelenik meg)\"\nTXT_WIDGETS_WIDTH = \"Widgetek szélessége:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Skála megjelenítése\"\nTXT_USE_LINEAR_SCALE = \"Lineáris skála használata\"\nTXT_USE_LOG_SCALE = \"Logaritmikus skála használata\"\nTXT_FIRST_DAT_OF_WEEEK = \"A hét első napja\"\nTXT_SUNDAY = \"Vasárnap\"\nTXT_MONDAY = \"Hétfő\"\nTXT_GO_TO_TODAY = \"Ugrás a mai napra\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"Szöveg &másolása\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"Hálózati kapcsolatok ki&választása\"\nTXT_AUTO_SELECT = \"&Automatikus kiválasztás\"\nTXT_SELECT_ALL = \"Ö&sszes kiválasztása\"\nTXT_CONNECTION_DETAILS = \"Csatlakozás &részletei\"\nTXT_ALWAYS_ON_TOP = \"&Mindig előtérben\"\nTXT_MOUSE_PENETRATE = \"Rámutatás egérrel\"\nTXT_LOCK_WINDOW_POS = \"Ab&lak pozíciójának zárolása\"\nTXT_SHOW_MORE_INFO = \"További &információ megjelenítése\"\nTXT_SHOW_TASKBAR_WINDOW = \"&Tálcaablak megjelenítése\"\nTXT_SHOW_MAIN_WINDOW = \"Fő&ablak megjelenítése\"\nTXT_WINDOW_OPACITY = \"Ablak átláts&zósága\"\nTXT_OTHER_FUNCTIONS = \"Egyéb &funkciók\"\nTXT_CHANGE_SKIN = \"&Szkin módosítása...\"\nTXT_CHANGE_NOTIFY_ICON = \"Értesítés &ikon módosítása...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Képernyőn kívüli &határok engedélyezése\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"Korábbi for&galmi statisztikák\"\nTXT_PLUGIN_MANAGE = \"Plugin-in kezelő...\"\nTXT_OPTIONS = \"&Beállítások...\"\nTXT_HELP_MENU = \"&Súgó\"\nTXT_HELP = \"&Súgó\"\nTXT_FAQ = \"&Gyakran ismételt kérdések\"\nTXT_UPDATE_LOG = \"Frissítési napló\"\nTXT_ABOUT = \"&Névjegy...\"\nTXT_CHECK_UPDATE = \"&Frissítés keresése...\"\nTXT_EXIT = \"&Kilépés\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"Megjelenítési beállítások...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"Tálcaablak &bezárása\"\nTXT_TASK_MANAGER = \"&Feladatkezelő\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Részletek...\"\nTXT_PLUGIN_OPTIONS = \"&Beállítások...\"\nTXT_PLUGIN_DISABLE = \"Let&iltva\"\n\n;IDR_DISPLAY_ITEM_CONTEXT_MENU\nTXT_RESTORE_DEFAULT = \"Visszaállítás alapértelmezettre\"\n"
  },
  {
    "path": "TrafficMonitor/language/Italian.ini",
    "content": "﻿[general]\nBCP_47 = \"it-IT\"\nDISPLAY_NAME = \"Italiano\"\nTRANSLATOR = \"bovirus\"\nTRANSLATOR_URL = \"bovirus@gmail.com\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"Controllo aggiornamenti non riuscito, controlla la connessione di rete!\"\"\nIDS_CHECK_UPDATE_ERROR = \"Controllo aggiornamenti non riuscito,  ottieni le informazioni errate dal file di aggiornamento remoto, contatta l'autore!\"\nIDS_UPDATE_AVLIABLE = \"Rilevata nuova versione v. %S, vuoi aggiornare?\"\nIDS_UPDATE_AVLIABLE2 = \"Rilevata nuova versione v. %S, Contenuto aggiornamento:\\r\\n%s\\r\\nVuoi aggiornare?\"\nIDS_ALREADY_UPDATED = \"Questa versione è aggiornata.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"Impossibile abilitare l'esecuzione automatica all'avvio di Windows, non è possibile trovare la chiave corrispondente nel registro.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"Scrittura della chiave del registro non riuscita, potresti non avere il permesso di accedere alla chiave!\"\nIDS_AUTORUN_DELETE_FAILED = \"Eliminazione chiave del registro non riuscita, potresti non avere il permesso di accedere alla chiave!\"\nIDS_AN_INSTANCE_RUNNING= \"C'è già un'istanza in esecuzione.\"\nIDS_TRAFFIC_USED_TODAY = \"Traffico usato oggi\"\nIDS_MEMORY_USAGE = \"Uso memoria\"\nIDS_CPU_USAGE = \"Uso CPU\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Invia una email all'autore.\"\nIDS_GOTO_GITHUB = \"Vai alla pagina di questo progetto su GitHub.\"\nIDS_DONATE_ATHOUR = \"Dona all'autore\"\nIDS_UPLOAD = \"Upload\"\nIDS_DOWNLOAD = \"Download\"\nIDS_MEMORY = \"Memoria\"\nIDS_UPLOAD_DISP = \"SU\"\nIDS_DOWNLOAD_DISP = \"GIU'\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"ATTENZIONE: impossibile salvare le impostazioni, impossibile scrivere dati nel file = \"\" <%file_path%> \"\"!\\r\\nL'esecuzione di questo programma come amministratore può risolvere questo problema. \"\nIDS_TRAFICHMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"La dimensione del buffer usata per archiviare le informazioni di connessione non è sufficiente, la connessione è stata re-inizializzata (re-inizializzato <%CNT%> volte).\"\nIDS_CONNECTION_NUM_CHANGED = \"È stata rilevata la modifica del numero di connessioni.\\r\\nLa connessione è stata recuperata.\\r\\n Connessioni precedenti: <%prima%>, connessioni attuali: <%dopo%> (re-inizializzata <%CNT%> volte).\"\nIDS_CONNECTION_NOT_MATCH = \"Potrebbe essersi verificata un'eccezione, la connessione attualmente selezionata è incompatibile con la connessione prevista. La connessione è stata recuperata (re-inizializzato <%CNT%> volte).\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"La finestra non è incorporata correttamente nella barra delle applicazioni, può essere bloccata dal software di sicurezza o il menu di avvio non è chiuso, prova a riavviare Explorer. TrafficMonitor continuerà a provare ma smetterà di ricordare, codice di errore:\"\nIDS_MEMORY_UDAGE_EXCEED= \"È stato raggiunto il limite dell'uso della memoria\"\nIDS_NOTIFY = \"Notifiche\"\nIDS_TODAY_TRAFFIC_EXCEED = \"LRaggiunto limite traffico giornaliero\"\nIDS_DATE = \"Data\"\nIDS_TRAFFIC_USED = \"Traffico totale\"\nIDS_FIGURE = \"Figura\"\nIDS_DEFAULT_ICON = \"Icona predefinita\"\nIDS_ICON = \"Icona\"\nIDS_INTERFACE_NAME = \"Nome scheda di rete\"\nIDS_INTERFACE_DESCRIPTION= \"Descrizione scheda di rete\"\nIDS_CONNECTION_TYPE = \"Tipo connessione\"\nIDS_IF_TYPE_OTHER = \"Altri tipi di rete\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"Rete Ethernet\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Rete token ring\"\nIDS_IF_TYPE_FDDI = \"Rete FDDI (Fiber Distributed Data Interface)\"\nIDS_IF_TYPE_PPP = \"Rete PPP\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"Rete loopback software\"\nIDS_IF_TYPE_ATM = \"Rete ATM\"\nIDS_IF_TYPE_IEEE80211 = \"Rete wireless IEEE 802.11\"\nIDS_IF_TYPE_TUNNEL = \"Rete tipo incapsulamento tunnel\"\nIDS_IF_TYPE_IEEE1394 = \"Rete IEEE 1394 (Firewire) bus seriale alte prestazioni\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"Interfaccia cellulare broadband per dispositivi WiMax\"\nIDS_IF_TYPE_WWANPP = \"Interfaccia cellulare broadband per dispositivi GSM\"\nIDS_IF_TYPE_WWANPP2 = \"Interfaccia cellulare broadband per dispositivi CDMA\"\nIDS_UNKNOW_CONNECTION = \"Rete sconosciuta\"\nIDS_SPEED = \"Velocità\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"Indirizzo fisico scheda\"\nIDS_IP_ADDRESS = \"Indirizzo IP\"\nIDS_SUBNET_MASK = \"MAschera sotto-rete\"\nIDS_DEFAULT_GATEWAY = \"Gateway predefinito\"\nIDS_OPERATIONAL_STATUS = \"Stato connessione\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"La scheda LAN è stata disabilitata\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"La scheda WAN non è connessa\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"cavo di rete scollegato o nessuna connessione\"\nIDS_IF_OPER_STATUS_CONNECTING = \"Scheda WAN che si sta collegando\"\nIDS_IF_OPER_STATUS_CONNECTED = \"Scheda WAN che è connessa al peer remoto\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"La scheda LAN è connessa\"\nIDS_UNKNOW_STATUS = \"Stato sconosciuto\"\nIDS_BYTES_RECEIVED = \"Byte ricevuti\"\nIDS_BYTES_SENT = \"Byte inviati\"\nIDS_BYTES_RECEIVED_SINCE_START= \"Byte ricevuti dal momento dall'avvio del programma\"\nIDS_BYTES_SENT_SINCE_START= \"Byte inviati dal momento dell'avvio del programma\"\nIDS_PROGRAM_ELAPSED_TIME= \"Tempo trascorso dall'avvio del programma\"\nIDS_HOUR_MINUTE_SECOND = \"%d ore, %d minuti, %d secondi\"\nIDS_INTERNET_IP_ADDRESS= \"Indirizzo IP internet\"\nIDS_GET_FAILED = \"Richiesta info fallita\"\nIDS_ITEM = \"Elemento\"\nIDS_VALUE = \"Valore\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"Copia negli appunti fallita!\"\nIDS_SKIN_AUTHOUR = \"Autore tema:\"\nIDS_SPEED_SHORT_MODE_TIP = \"Quando selezionato, la visualizzazione della velocità verrà ridotta di posizione decimale, e l'unità non verrà visualizzata \"\"B\"\".\"\nIDS_AUTO = \"Automatica\"\nIDS_FIXED_AS = \"Corretta come\"\nIDS_OPEN_CONNECTION_DETIAL= \"Visualizza dettagli connessione\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"Visualizza cronologia statistiche traffico\"\nIDS_SHOW_HIDE_MORE_INFO= \"Visualizza/nascondi altre info\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"Visualizza/nascondi uso CPU/memoria\"\nIDS_OPEN_OPTION_SETTINGS= \"Apri impostazioni\"\nIDS_OPEN_TASK_MANAGER = \"Apri task manager\"\nIDS_CHANGE_SKIN = \"Modifica tema\"\nIDS_NONE = \"Nessuno\"\nIDS_FONT_SIZE_WARNING = \"La dimensione del font deve essere compresa tra %d e %d!\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"Attenzione: il colore testo è lo stesso dello sfondo!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"Attenzione: il colore sfondo è lo stesso del testo!\"\nIDS_FOLLOWING_SYSTEM = \"Lingua sistema\"\nIDS_LANGUAGE_CHANGE_INFO = \"Per applicare le impostazioni lingua riavvia l'applicazione.\"\nIDS_MAIN_WINDOW_SETTINGS= \"Finestra principale\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"Finestra barra applicazioni\"\nIDS_GENERAL_SETTINGS = \"Generale\"\nIDS_ACQUIRING = \"Acquisizione\"\nIDS_LIST_VIEW = \"Vista elenco\"\nIDS_CALENDAR_VIEW = \"Vista calendario\"\nIDS_MONDAY = \"Lun\"\nIDS_TUESDAY = \"Mar\"\nIDS_WEDNESDAY = \"Mer\"\nIDS_THURSDAY = \"Gio\"\nIDS_FRIDAY = \"Ven\"\nIDS_SATURDAY = \"Sab\"\nIDS_SUNDAY = \"Dom\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"Totale traffico mese attuale:\"\nIDS_TRAFFIC_USED1 = \"Traffico  usato:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Impossibile inserire nella barra applicazioni, riprova <%cnt%> volte. GetLastError(): <%error_code%>.\"\nIDS_NO_CONNECTION = \"Nessuna connessione\"\nIDS_CONTACT_TRANSLATOR = \"Contatta il traduttore.\"\nIDS_THANKS_DONORS = \"Grazie ai seguenti donatori:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"Si è verificato un errore con la richiesta di= \"\"<%1%>\"\", codice errore: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"Quando questo elemento è selezionato, tutte le schede di rete verranno visualizzate nell'elenco = \"\"Seleziona connessione di rete\"\" nel menu clic destro. Ti suggeriamo di che tu selezioni questo elemento solo quando necessario.\"\nIDS_CFG_DIR_CHANGED_INFO = \"Hai modificato il percorso in cui i file di configurazione e dati vengono salvati. Queste impostazioni verranno applicate dopo il riavvio. Potrebbe essere necessario trasferire manualmente i file di configurazione e dati nel nuovo percorso.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<Doppio clic qui per acquisire.>\"\nIDS_ERROR1 = \"Errore\"\nIDS_ERROR_MESSAGE = \"Messaggio di errore:\"\nIDS_CRASH_INFO = \"Spiacenti, il programma si è sbloccato. Riavvia il programma.\\r\\nSe riscontri questo problema molte volte, prova a disabilitare la funzione di monitoraggio dell'hardware in= \"\"Impostazioni\"\" >= \"\"Impostazioni generali\"\", e disabilita tutti i plugin nella finestra= \"\"Gestione plugin\"\".\\r\\nSe il problema si verifica comunque invia un'email e questo file= \"\"<%1%>\"\" a  bugreport-zhongyang219@outlook.com per aiutare l'autore a individuare il problema. E aggiungere quanto segue al corpo del messaggio:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"Riconoscimenti\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Vuoi salvare l'impostazione del colore della barra delle applicazioni attuale in= \"\"Profilo <%1%>\"\"?\"\nIDS_SPECIFIC_APP = \"Apri l'applicazione specificata\"\nIDS_EXE_FILTER = \"Applicazioni|*.exe|File batch|*.bat||\"\nIDS_PRESET = \"Profilo\"\nIDS_LIGHT_MODE = \"Modo chiaro\"\nIDS_AUTO_ADAPT_TIP_INFO= \"Questa funzione cambierà automaticamente le impostazioni dei colori quando viene selezionato il tema chiaro/scuro di Windows 10. Seleziona= \"\"Imposta\"\" per configurare lo schema del profilo per lo switch automatico.\"\nIDS_WITHOUT_TEMPERATURE= \"Chiaro\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"Il mouse è attivo. Se è necessario disabilitare il mouse, individua l'icona di TrafficMonitor nell'area di notifica del sistema, clic destro del mouse, e disabilita disabilita il mouse nel menu. Seleziona Annulla per evitare future richieste.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"È stata rilevata la perdita di dati nella cronologia del traffico. Il numero attuale di record: <%1%>, <%2%> record sono stati recuperati dal file di backup.\"\nIDS_LEGEND = \"Legenda\"\nIDS_LICENSE_EXPLAIN = \"Quando usi il codice sorgente di questo software, segui le seguenti regole del software open source \"\nIDS_LICENSE = \"Licenza\"\nIDS_DAY_VIEW = \"Vista giorno\"\nIDS_MONTH_VIEW = \"Vista mese\"\nIDS_QUARTER_VIEW = \"Vista trimestre\"\nIDS_YEAR_VIEW = \"Vista anno\"\nIDS_LINEAR_SCALE = \"Lineare\"\nIDS_LOG_SCALE = \"Logaritmica\"\nIDS_CPU_TEMPERATURE = \"Temperatura CPU\"\nIDS_GPU_TEMPERATURE = \"Temperatura GPU\"\nIDS_CPU_FREQ = \"Frequenza CPU\"\nIDS_HDD_TEMPERATURE = \"Temperatura disco fisso\"\nIDS_MAINBOARD_TEMPERATURE= \"Temperatura scheda madre\"\nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"HDD\"\nIDS_MAINBOARD_DISP = \"MBD\"\nIDS_CPU_TEMPERATURE_EXCEED= \"È stata raggiunta la temperatura della CPU\"\nIDS_GPU_TEMPERATURE_EXCEED= \"È stata raggiunta la temperatura della GPU\"\nIDS_HDD_TEMPERATURE_EXCEED= \"È stata raggiunta la temperatura del disco fisso\"\nIDS_MBD_TEMPERATURE_EXCEED= \"È stata raggiunta la temperatura della  scheda madre\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: un lettore musicale locale bello e di facile utilizzo per Windows\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: un semplice editor di testo per Windows\"\nIDS_COLOR = \"Colori\"\nIDS_COLOR_LABEL = \"Colore etichetta\"\nIDS_COLOR_VALUE = \"Colore valore\"\nIDS_GPU_USAGE = \"Uso GPU\"\nIDS_IF_OPER_STATUS_UP = \"Scheda connessa\"\nIDS_IF_OPER_STATUS_DOWN= \"Scheda non connessa\"\nIDS_IF_OPER_STATUS_DORMANT= \"Connessione scheda\"\nIDS_GOTO_GITEE = \"Vai alla pagina su Gitee per questo progetto.\"\nIDS_USAGE_PERCENTAGE = \"Percentuale uso\"\nIDS_MEMORY_USED = \"Memoria usata\"\nIDS_MEMORY_AVAILABLE = \"Memoria disponibile\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \"Nel sistema non è installato .Net Framework v4.5.2 or superiore. La funzione di monitoraggio della temperatura non sarà disponibile. Clic su Annulla per evitare future richieste.\"\nIDS_VERSION_UPDATE = \"Aggiornamento nuova versione\"\nIDS_AVREAGE_TEMPERATURE= \"Temperatura media\"\nIDS_HARDWARE_MONITOR_WARNING = \"Attenzione: stai abilitando la funzione di monitoraggio dell'hardware. La funzione di monitoraggio dell'hardware può essere usata per visualizzare le informazioni sull'uso e sulla temperatura GPU. Prima di attivare la funzione di monitoraggio dell'hardware leggi attentamente quanto segue :\\r\\nTrafficMonitor non è un software di monitoraggio hardware professionale. Non può garantire che le informazioni hardware possano essere ottenute in tutti i computer, né può garantire l'accuratezza delle informazioni hardware ottenute.\\r\\nLa funzione di monitoraggio dell'hardware è implementata dalla terza libreria LibreHardwareMonitor. Dopo l'attivazione del monitoraggio dell'hardware, in alcuni computer possono verificarsi alcuni problemi, inclusi ma non limitati a:\\r\\n* Anormale uso della CPU e della memoria\\r\\n* Crash del programma\\r\\n* Crash del computer\\r\\nAttiva la funzione di monitoraggio dell'hardware dopo aver compreso i rischi di cui sopra. \\r\\nVuoi attivare la funzione di monitoraggio dell'hardware?\"\nIDS_HDD_USAGE = \"Uso disco fisso\"\nIDS_FILE_NAME = \"Nome file\"\nIDS_STATUS = \"Stato\"\nIDS_PLUGIN_LOAD_SUCCEED= \"Caricamento completato\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"Caricamento plugin non riuscito, codice di errore: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"Funzione di acquisizione non riuscita, codice di errore: <%1%>\"\nIDS_PLUGIN_INFO = \"Dettagli plugin\"\nIDS_NAME = \"Nome\"\nIDS_DESCRIPTION = \"Descrizione\"\nIDS_FILE_PATH = \"Percorso file\"\nIDS_ITEM_NUM = \"Numero elementi visualizzati\"\nIDS_ITEM_NAMES = \"Nomi elementi visualizzati\"\nIDS_AUTHOR = \"Autore\"\nIDS_COPYRIGHT = \"Copyright\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"Il plugin non dispone di opzioni di impostazione.\"\nIDS_PLUGIN_NAME = \"Nomi plugin\"\nIDS_DISABLED = \"Disabilitato\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Per applicare questa modifica riavvia il programma.\"\nIDS_VERSION = \"Versione\"\nIDS_DISP_ITEM_ID = \"ID elemento visualizzato\"\nIDS_PLUGIN_API_VERSION = \"Versione API\"\nIDS_WEEK_VIEW = \"Vista settimana\"\nIDS_WEEK_NUM = \"Settimana <%1%>\"\nIDS_URL = \"URL\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"La versione del plugin è troppo bassa.\"\nIDS_MODIFY_PRESET = \"Modifica profilo\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"Selezionano almeno uno!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"Quando è abilitata la funzione= \"\"Adattata automaticamente al tema scuro/chiaro\"\", se questa opzione è spuntata, vengono modificati il colore della finestra della barra delle applicazioni e le impostazioni del colore di sfondo, in accordo con l'attuale tema scuro/chiaro di Windows, e viene salvato automaticamente nel profilo corrispondente.\"\nIDS_TOTAL_NET_SPEED = \"Velocità totale\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"Visualizza grafici di uso delle risorse di CPU/memoria/disco fisso, informazioni sulla temperatura e elementi del plugin.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"Visualizza l'indicatore di velocità per upload, download e velocità totale.\"\nIDS_REFRESH_CONNECTION_LIST= \"Aggiorna elenco connessioni\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"Inizializzazione unzione di monitoraggio dell'hardware non riuscita, il monitoraggio hardware non sarà disponibile!\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Errore nell'ottenere i dati di monitoraggio dell'hardware!\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"Modo esecuzione automatica : Registro\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"Modo esecuzione automatica: pianificazione attività\"\nIDS_PATH = \"Percorso\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"Impostazione esecuzione automatico all'avvio fallita!\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Impossibile aggiornare il contenuto della finestra della barra delle applicazioni, il rendering direct2d è stato disabilitato. Nota: la finestra Impostazioni non può aggiornare immediatamente questa impostazione.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Si è verificato un errore durante il rendering Direct2D e il rendering Direct2D è stato disabilitato. Nota: la finestra Impostazioni potrebbe non aggiornare immediatamente questa impostazione.\"\nIDS_PLUGIN_OPTIONS = \"Opzioni plugin\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"Ottenimento uso CPU la contatore prestazioni fallito, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"Monitor principale\"\nIDS_SECONDARY_DISPLAY = \"Monitor secondario <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"Questo sistema si è riattivato dall'ibernazione, e la connessione è stata re-inizializzata (re-inizializzata <%1%> volte).\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"Aggiornamento disponibile, versione aggiornata: <%1%>\"\nIDS_TRAFFICMONITOR_PLUGIN_NITIFICATION = \"Notifica plugin TrafficMonitor\"\n\nTXT_OK = \"OK\"\nTXT_CANCEL = \"Annulla\"\nTXT_CLOSE = \"Chiudi\"\nTXT_APPLY = \"Applica\"\n\n; Text used for dialog. (Must be started with \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"Info su TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor <%1%>, V<%2%>\"\nTXT_ABOUT_COPYRIGHT = \"Copyright (C) 2017-2025 di ZhongYang\\nData compilazione: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"Lingua: <%1%> (v. 10.06.2025) di <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"Librerie di terze parti usate in questo progetto:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"Altri software dell'autore:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"Contatta l'autore\"\nTXT_ABOUT_LICENSE = \"Licenza\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"Riconoscimenti\"\nTXT_ABOUT_DONATE = \"Dona\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor è già in esecuzione.\"\nTXT_EXIT_THE_PROGRAM = \"E&sci dal programma\"\nTXT_OPEN_OPTION_SETTINGS = \"Imp&ostazioni\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"Visualizza/nascondi &finestra principale\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"Visualizza/nascondi finestra barra applicazioni\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Impostazioni adattamento automatico\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Profilo colore usato con il tema scuro:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Profilo colore usato con il tema chiaro:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"Salvataggio automatico colori barra applicazioni nel profilo\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Impostazioni visualizzazione testo\"\nTXT_RESTORE_DEFAULT = \"Ripristina pre&definiti per tutti\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Impostazioni applicazione\"\nTXT_CHECK_UPDATE = \"Controlla aggiornamenti all'avvio\"\nTXT_CHECK_NOW = \"&Controlla\"\nTXT_UPDATE_SOURCE = \"Aggiornamenti da:\"\nTXT_AUTO_RUN_CHECK = \"Esegui automaticamente all'avvio di Windows\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Disabilita avvio automatico\"\nTXT_LANGUAGE = \"Lingua:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"File configurazione e dati\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Salva nella cartella AppData\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Salva nella cartella del programma\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Apri cartella &file configurazione\"\nTXT_NOTIFICATION_MESSAGE = \"Messaggi notifica\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"Notifica raggiungimento limite traffico giornaliero:\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"Notifica raggiungimento limite uso memoria\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"Notifica raggiungimento limite temperatura CPU\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"Notifica raggiungimento limite temperatura GPU\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"Notifica raggiungimento limite temperatura disco fisso\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"Notifica raggiungimento limite temperatura scheda madre\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Monitoraggio hardware\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"GPU\"\nTXT_HARD_DISK = \"Disco fisso\"\nTXT_MAIN_BOARD = \"Scheda madre\"\nTXT_SELECT_HDD_STATIC = \"Disco fisso da monitorare:\"\nTXT_SELECT_CPU_STATIC = \"Temperatura CPU da monitorare:\"\nTXT_ADVANCED = \"Avanzate\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Visualizza tutte le connessioni di rete\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"&Seleziona connessione da monitorare...\"\nTXT_CPU_ACQUISITION_METHOD = \"Metodo acquisizione uso CPU:\"\nTXT_USE_CPU_TIME_RADIO = \"Basato sul tempo CPU\"\nTXT_USE_PDH_RADIO = \"Usa il contatore prestazioni\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"Usa il monitor hardware\"\nTXT_MONITORING_INTERVALS = \"Intervallo monitoraggio:\"\nTXT_MILLISECONDS = \"millisecondi\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"Ripristina &predefinito\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Gestione plugin...\"\nTXT_DISPLAY = \"Visualizzazione\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"Visualizza icona &notifiche\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Anno:\"\nTXT_MONTH = \"Mese:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Cronologia statistiche traffico\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"Tipo vista:\"\nTXT_FIGURE_VIEW_SCALE = \"Scala visualizzazione:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Modifica icona notifica\"\nTXT_SELECT_A_ICON = \"Seleziona un'icona:\"\nTXT_PREVIEW = \"Anteprima\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Adatta automaticamente a tema scuro/chiaro Windows 10\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Impostazioni colore finestra principale\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Nascondi finestra principale con programma a pieno schermo\"\nTXT_COLOR_AND_FONT = \"Colori e font\"\nTXT_FONT = \"Font:\"\nTXT_FONT_SIZE = \"Dim. font:\"\nTXT_SET_FONT_BUTTON = \"Scegli &font...\"\nTXT_TEXT_COLOR = \"Colore testo:\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"&Ripristina tema predefinito\"\nTXT_DISPLAY_TEXT = \"testo visualizzato\"\nTXT_SWITCH_UP_DOWN_CHECK = \"Scambia posizione upload/download\"\nTXT_UNIT_SETTINGS = \"Impostazioni unità\"\nTXT_UNIT_SELECTION = \"Selezione unità:\"\nTXT_HIDE_UNIT_CHECK = \"Non visualizzare unità velocità\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Modo breve per velocità rete\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Non visualizzare percentuale\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Specifica colore per ogni elemento\"\nTXT_DOUBLE_CLICK_ACTION = \"Azione doppio clic:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Separa valore e unità con spazio\"\nTXT_NETSPEED_UNIT = \"Unità velocità rete:\"\nTXT_UNIT_BYTE_RADIO = \"B (Byte)\"\nTXT_UNIT_BIT_RADIO = \"b (bit)\"\nTXT_SHOW_TOOL_TIP_CHK = \"Visualizza suggerimenti con mouse\"\nTXT_EXE_PATH_STATIC = \"Applicazione specificata:\"\nTXT_BROWSE_BUTTON = \"&Sfoglia...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Impostazioni visualizzazione &testo...\"\nTXT_MEMORY_DISPLAY_MODE = \"Modo visualizzazione memoria:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Sempre in primo piano\"\nTXT_MOUSE_PENETRATE_CHECK = \"Mouse penetrate\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Blocca posizione finestra\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Consenti oltre i confini dello schermo\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Messaggio\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Dettagli connessione\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Impostazioni\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Gestione plugin\"\nTXT_OPTINS_BUTTON = \"Imp&ostazioni...\"\nTXT_PLUGIN_INFO_BUTTON = \"&Dettagli...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Guida sviluppo plugin\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"Download altri plugin\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Apri cartella plugin\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Seleziona connessione da monitorare\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Valori da visualizzare\"\nTXT_MOVE_UP_BUTTON = \"Sposta su\"\nTXT_MOVE_DOWN_BUTTON = \"Sposta giù\"\nTXT_RESTORE_DEFAULT_BUTTON = \"Pre&definite\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Impostazioni switch automatico tema\"\nTXT_SKIN_IN_DARK_MODE = \"Tema usato nel modo Windows scuro:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Tema usato nel modo Windows chiaro:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Modifica tema\"\nTXT_PREVIEW_GROUP_STATIC = \"Anteprima\"\nTXT_SELECT_A_SKIN = \"Seleziona un tema\"\nTXT_SKIN_AUTHOR = \"Autore tema:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Tutorial impostazione tema\"\nTXT_DOWNLOAD_MORE_SKIN = \"Scarica altri temi\"\nTXT_OPEN_SKIN_DIR = \"Apri cartella tema\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Switch automatico in accordo con i modi colore Windows 10 scuro/chiaro.\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Impostazioni switch automatico...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"Impostazioni colori barra applicazioni\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Profilo\"\nTXT_BACKGROUND_COLOR = \"Colore sfondo:\"\nTXT_BACKGROUND_TRANSPARENT = \"Sfondo trasparente\"\nTXT_AUTO_SET_BACK_COLOR = \"Imposta automaticamente colore di sfondo in base al colore barra applicazioni\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Adatta automaticamente  ai temi scuro/chiaro\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"Impo&sta...\"\nTXT_DISPLAY_SETTINGS = \"Valori da visualizzare\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"Valori da v&isualizzare...\"\nTXT_SPEED_SHORT_MODE = \"Visualizzazione velocità rete modo breve\"\nTXT_VALUE_RIGHT_ALIGN = \"Allinea valori a destra\"\nTXT_NET_SPEED_DATA_WIDTH = \"Larghezza dati velocità rete:\"\nTXT_CHARACTORS = \"caratteri\"\nTXT_HORIZONTAL_ARRANGE = \"Adatta orizzontalmente\"\nTXT_ITEM_SPACING = \"Spazio elemento:\"\nTXT_VERTICAL_MARGIN = \"MArgine verticale:\"\nTXT_PIXELS = \"pixel\"\nTXT_TASKBAR_WINDOW = \"Finestra barra applicazioni\"\nTXT_TASKBAR_WND_ON_LEFT = \"La finestra applicazioni appare sulla sinistra della barra applicazioni\"\nTXT_SHOW_TASKBAR_WND_IN_SECONDARY_DISPLAY = \"Visualizza finestra barra applicazioni nel secondo monitor (se disponibile)\"\nTXT_WIN11_SETTINGS_BUTTON = \"Impostazioni relative a Windows 11\"\nTXT_RESOURCE_USAGE_GRAPH = \"Grafico uso risorse\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Visualizza grafico uso risorse\"\nTXT_SHOW_DASHED_BOX = \"Visualizza riquadro tratteggiato\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Visualizza grafico velocità rete\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"Valore max del grafico velocità rete:\"\nTXT_USAGE_GRAPH_COLOR = \"Colore grafico uso:\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"Segui colore tema Windows\"\nTXT_GRAPH_DISPLAY_MODE = \"Modo visualizzazione grafico:\"\nTXT_BAR_MODE = \"Modo barra\"\nTXT_PLOT_MODE = \"Modo disegno\"\nTXT_RENDERING_SETTINGS = \"Impostazioni rendering\"\nTXT_RENDERING_SETTINGS_NOTE = \"Note: il rendering Direct2D viene usato solo quando è selezionato \"\"Background trasparente\"\" ma non è seelzionato \"\"Imposta automaticamente il colore di sfondo in accordo al colore della barra applicazioni\"\".\"\nTXT_ENABLE_COLOR_EMOJI = \"Abilita emoji colorati\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Impostazioni relative a Windows 11\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"Finestra barra applicazioni chiusa nell'icona anziché ai lati della barra applicazioni\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Offset verticale finestra:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Offset orizzontale finestra:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Evita sovrapposizione con widget a destra (spunta questa opzione se i widget appaiono sul lato destro della barra applicazioni)\"\nTXT_WIDGETS_WIDTH = \"Larghezza widget:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Visualizza scala\"\nTXT_USE_LINEAR_SCALE = \"Usa scala lineare\"\nTXT_USE_LOG_SCALE = \"Usa scala logaritmica\"\nTXT_FIRST_DAT_OF_WEEEK = \"Primo giorno della settimana\"\nTXT_SUNDAY = \"Domenica\"\nTXT_MONDAY = \"Lunedì\"\nTXT_GO_TO_TODAY = \"Vai ad oggi\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"&Copia testo\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"&Seleziona connessione di rete\"\nTXT_AUTO_SELECT = \"Selezione &automatica\"\nTXT_SELECT_ALL = \"&Seleziona tutto\"\nTXT_CONNECTION_DETAILS = \"&Dettagli connessione\"\nTXT_ALWAYS_ON_TOP = \"Sempre in primo &piano\"\nTXT_MOUSE_PENETRATE = \"Mo&use Penetrate\"\nTXT_LOCK_WINDOW_POS = \"B&locca posizione finestra\"\nTXT_SHOW_MORE_INFO = \"Visualizza maggiori &info\"\nTXT_SHOW_TASKBAR_WINDOW = \"Visualizza finestra barra applica&zioni\"\nTXT_SHOW_MAIN_WINDOW = \"&Visualizza finestra principale\"\nTXT_WINDOW_OPACITY = \"O&pacità finestra\"\nTXT_OTHER_FUNCTIONS = \"Altre &funzioni\"\nTXT_CHANGE_SKIN = \"Modifica &tema...\"\nTXT_CHANGE_NOTIFY_ICON = \"Modifica icona &notifica...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Consenti fuori dai contorni dello sc&hermo\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"Statistiche cronologia traffico\"\nTXT_PLUGIN_MANAGE = \"Gestione plugin...\"\nTXT_OPTIONS = \"Imp&ostazioni...\"\nTXT_HELP_MENU = \"&Aiuto\"\nTXT_HELP = \"&Guida in linea\"\nTXT_FAQ = \"&FAQ (domande frequenti)\"\nTXT_UPDATE_LOG = \"Elenco novità p&rogramma\"\nTXT_ABOUT = \"&Info programma...\"\nTXT_CHECK_UPDATE = \"&Controllo aggiornamenti...\"\nTXT_EXIT = \"E&sci\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"&Valori da visualizzare...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"&Chiudi finestra barra applicazioni\"\nTXT_TASK_MANAGER = \"&Task Manager\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Dettagli...\"\nTXT_PLUGIN_OPTIONS = \"&Opzioni...\"\nTXT_PLUGIN_DISABLE = \"D&isabilitato\"\n\n;IDR_DISPLAY_ITEM_CONTEXT_MENU\nTXT_RESTORE_DEFAULT = \"&Ripristina predefiniti\"\n"
  },
  {
    "path": "TrafficMonitor/language/Polish.ini",
    "content": "﻿[general]\nBCP_47 = \"pl-PL\"\nDISPLAY_NAME = \"Polish\"\nTRANSLATOR = \"JakubDriver\"\nTRANSLATOR_URL = \"jakubdriver@gmail.com\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"Sprawdź, czy aktualizacja się nie powiodła. Sprawdź połączenie sieciowe!\"\nIDS_CHECK_UPDATE_ERROR = \"Sprawdzenie aktualizacji nie powiodło się i otrzymano błędne informacje ze zdalnego pliku aktualizacji. Skontaktuj się z autorem!\"\nIDS_UPDATE_AVLIABLE = \"Wykryto nową wersję V%s. Czy chcesz przejść do aktualizacji?\"\nIDS_UPDATE_AVLIABLE2 = \"Wykryto nową wersję V%s, aktualizacja zawartości: \\r\\n%s\\r\\nCzy chcesz przejść do aktualizacji?\"\nIDS_ALREADY_UPDATED = \"Już zaktualizowano do najnowszej wersji.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"Nie można uruchomić funkcji automatycznego uruchamiania podczas startu systemu Windows. Nie można znaleźć odpowiedniego klucza w rejestrze.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"Zapis klucza rejestru nie powiódł się, może nie być uprawnień dostępu do klucza!\"\nIDS_AUTORUN_DELETE_FAILED = \"Nie udało się usunąć klucza rejestru. Być może nie masz uprawnień dostępu do klucza!\"\nIDS_AN_INSTANCE_RUNNING= \"Jedna z instancji jest już uruchomiona.\"\nIDS_TRAFFIC_USED_TODAY = \"Ruch używany dzisiaj\"\nIDS_MEMORY_USAGE = \"Wykorzystanie pamięci\"\nIDS_CPU_USAGE = \"Wykorzystanie procesora\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Wyślij e-mail do autora.\"\nIDS_GOTO_GITHUB = \"Przejdź do strony tego projektu na GitHub.\"\nIDS_DONATE_ATHOUR = \"Przekaż autora\"\nIDS_UPLOAD = \"Pobieranie\"\nIDS_DOWNLOAD = \"Pobrane\"\nIDS_MEMORY = \"Pamięć\"\nIDS_UPLOAD_DISP = \"W GÓRĘ\"\nIDS_DOWNLOAD_DISP = \"W DÓŁ\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"Ostrzeżenie: Nie można zapisać ustawień, nie można zapisać danych do pliku= \"\"<%file_path%>\"\"! Uruchomienie tego programu jako administrator może rozwiązać ten problem.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"Rozmiar bufora używanego do przechowywania informacji o połączeniu jest niewystarczający. Połączenie zostało ponownie zainicjowane. (Ponownie zainicjowano <%cnt%> razy).\"\nIDS_CONNECTION_NUM_CHANGED = \"Wykryto zmianę numeru połączenia. Połączenie zostało pobrane. Poprzednie połączenia: <%before%>, teraz połączenia: <%after%>. (<%cnt%> razy zostało ponownie zainicjowane)\"\nIDS_CONNECTION_NOT_MATCH = \"Mógł wystąpić wyjątek, aktualnie wybrane połączenie jest niezgodne z oczekiwanym połączeniem. Połączenie zostało pobrane. (<%cnt%> razy zostało ponownie zainicjowane)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"Okno nie zostało prawidłowo osadzone na pasku zadań, mogło zostać zablokowane przez oprogramowanie zabezpieczające lub menu Start nie zostało zamknięte. Spróbuj ponownie uruchomić Eksploratora. TrafficMonitor będzie próbował dalej, ale przestanie przypominać, kod błędu:\"\nIDS_MEMORY_UDAGE_EXCEED= \"Osiągnięto limit wykorzystania pamięci\"\nIDS_NOTIFY = \"Notyfikować\"\nIDS_TODAY_TRAFFIC_EXCEED = \"Osiągnięto dzisiejszy ruch\"\nIDS_DATE = \"Data\"\nIDS_TRAFFIC_USED = \"Całkowity ruch\"\nIDS_FIGURE = \"Postać\"\nIDS_DEFAULT_ICON = \"Domyślna ikona\"\nIDS_ICON = \"Ikona\"\nIDS_INTERFACE_NAME = \"Nazwa interfejsu\"\nIDS_INTERFACE_DESCRIPTION= \"Opis interfejsu\"\nIDS_CONNECTION_TYPE = \"Typ połączenia\"\nIDS_IF_TYPE_OTHER = \"Inny typ sieci\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"Sieć Ethernet\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Sieć token ring\"\nIDS_IF_TYPE_FDDI = \"Sieć FDDI (Interfejs danych rozproszonych światłowodowych)\"\nIDS_IF_TYPE_PPP = \"Sieć PPP\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"Sieć pętli zwrotnej oprogramowania\"\nIDS_IF_TYPE_ATM = \"ATM sieć\"\nIDS_IF_TYPE_IEEE80211 = \"Sieć bezprzewodowa IEEE 802.11\"\nIDS_IF_TYPE_TUNNEL = \"Tunnel type encapsulation network\"\nIDS_IF_TYPE_IEEE1394 = \"Sieć magistrali szeregowej o wysokiej wydajności IEEE 1394 (Firewire)\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"Mobilny interfejs szerokopasmowy dla urządzeń WiMax\"\nIDS_IF_TYPE_WWANPP = \"Interfejs szerokopasmowy dla urządzeń opartych na technologii GSM\"\nIDS_IF_TYPE_WWANPP2 = \"Mobilny interfejs szerokopasmowy dla urządzeń opartych na technologii CDMA\"\nIDS_UNKNOW_CONNECTION = \"Nieznana sieć\"\nIDS_SPEED = \"Prędkość\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"Adres fizyczny adaptera\"\nIDS_IP_ADDRESS = \"Adres IP\"\nIDS_SUBNET_MASK = \"Maska podsieci\"\nIDS_DEFAULT_GATEWAY = \"Brama domyślna\"\nIDS_OPERATIONAL_STATUS = \"Status połączenia\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"Karta sieciowa LAN została wyłączona\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"Karta WAN nie jest podłączona\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"Odłączony kabel sieciowy lub brak operatora\"\nIDS_IF_OPER_STATUS_CONNECTING = \"Karta WAN, która jest w trakcie łączenia\"\nIDS_IF_OPER_STATUS_CONNECTED = \"Karta sieciowa WAN połączona ze zdalnym komputerem równorzędnym\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"Podłączono adaptery LAN\"\nIDS_UNKNOW_STATUS = \"Nieznany status\"\nIDS_BYTES_RECEIVED = \"Otrzymane bajty\"\nIDS_BYTES_SENT = \"Wysłane bajty\"\nIDS_BYTES_RECEIVED_SINCE_START= \"Bajty odebrane od momentu uruchomienia programu\"\nIDS_BYTES_SENT_SINCE_START= \"Bajty wysłane od momentu uruchomienia programu\"\nIDS_PROGRAM_ELAPSED_TIME= \"Czas trwania programu\"\nIDS_HOUR_MINUTE_SECOND = \"%d godzin, %d minut, %d sekund\"\nIDS_INTERNET_IP_ADDRESS= \"Adres IP Internetu\"\nIDS_GET_FAILED = \"Nie udało się\"\nIDS_ITEM = \"Przedmiot\"\nIDS_VALUE = \"Wartość\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"Kopiowanie do schowka nie powiodło się!\"\nIDS_SKIN_AUTHOUR = \"Autor skórki:\"\nIDS_SPEED_SHORT_MODE_TIP = \"Po zaznaczeniu tej opcji wyświetlana prędkość sieci zostanie zmniejszona o jedno miejsce po przecinku, a jednostka nie będzie wyświetlana jako = \"\"B\"\".\"\nIDS_AUTO = \"Automatyczny\"\nIDS_FIXED_AS = \"Naprawiono jako\"\nIDS_OPEN_CONNECTION_DETIAL= \"Otwórz szczegóły połączenia\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"Otwórz historyczne statystyki ruchu\"\nIDS_SHOW_HIDE_MORE_INFO= \"Pokaż/ukryj więcej informacji\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"Pokaż/ukryj użycie procesora i pamięci\"\nIDS_OPEN_OPTION_SETTINGS= \"Otwórz ustawienia opcji\"\nIDS_OPEN_TASK_MANAGER = \"Otwórz menedżera zadań\"\nIDS_CHANGE_SKIN = \"Zmień skórkę\"\nIDS_NONE = \"Nic\"\nIDS_FONT_SIZE_WARNING = \"Rozmiar czcionki musi zawierać się pomiędzy %d a %d!\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"Ostrzeżenie: Kolor tekstu jest taki sam, jak kolor tła!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"Ostrzeżenie: Kolor tła jest taki sam, jak kolor tekstu!\"\nIDS_FOLLOWING_SYSTEM = \"Następujący system\"\nIDS_LANGUAGE_CHANGE_INFO = \"Aby zastosować ustawienia językowe, uruchom ponownie aplikację.\"\nIDS_MAIN_WINDOW_SETTINGS= \"Ustawienia głównego okna\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"Ustawienia okna paska zadań\"\nIDS_GENERAL_SETTINGS = \"Ustawienia ogólne\"\nIDS_ACQUIRING = \"Nabycie\"\nIDS_LIST_VIEW = \"Widok listy\"\nIDS_CALENDAR_VIEW = \"Widok kalendarza\"\nIDS_MONDAY = \"Pon\"\nIDS_TUESDAY = \"Wto\"\nIDS_WEDNESDAY = \"Śro\"\nIDS_THURSDAY = \"Czw\"\nIDS_FRIDAY = \"Pią\"\nIDS_SATURDAY = \"Sob\"\nIDS_SUNDAY = \"Nie\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"Całkowity ruch w bieżącym miesiącu:\"\nIDS_TRAFFIC_USED1 = \"Wykorzystany ruch:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Nie udało się wstawić do paska zadań, spróbuj ponownie <%cnt%> razy. GetLastError(): <%error_code%>.\"\nIDS_NO_CONNECTION = \"Brak połączenia\"\nIDS_CONTACT_TRANSLATOR = \"Skontaktuj się z tym tłumaczem.\"\nIDS_THANKS_DONORS = \"Dziękujemy następującym darczyńcom:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"Wystąpił błąd podczas żądania= \"\"<%1%>\"\", kod błędu: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"Po zaznaczeniu tej pozycji wszystkie interfejsy sieciowe będą wyświetlane na liście= \"\"Select Network Connections\"\" w menu prawego przycisku myszy. Zaleca się zaznaczenie tej pozycji tylko wtedy, gdy jest to konieczne.\"\nIDS_CFG_DIR_CHANGED_INFO = \"Zmieniono lokalizację, w której zapisano pliki konfiguracji i danych. Zmiana zostanie wprowadzona po ponownym uruchomieniu. Może być konieczne ręczne przeniesienie plików konfiguracji i danych do nowej lokalizacji.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<Kliknij dwukrotnie tutaj, aby pobrać.>\"\nIDS_ERROR1 = \"Błąd\"\nIDS_ERROR_MESSAGE = \"Komunikat o błędzie:\"\nIDS_CRASH_INFO = \"Przepraszamy, program uległ awarii. Uruchom ponownie program. \\r\\nJeśli ten problem występuje wielokrotnie, spróbuj wyłączyć funkcję monitorowania sprzętu w= \"\"Opcje\"\" >= \"\"Ustawienia ogólne\"\", a następnie wyłącz wszystkie wtyczki w= \"\"Menedżer wtyczek\"\". \\r\\nJeśli problem nadal występuje, wyślij ten plik= \"\"<%1%>\"\" na adres bugreport-zhongyang219@outlook.com, aby pomóc autorowi zlokalizować problem. Dodaj również następujący tekst do treści wiadomości:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"Podziękowanie\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Czy na pewno chcesz zapisać bieżące ustawienie koloru paska zadań do= \"\"Ustawienie wstępne <%1%>\"\"?\"\nIDS_SPECIFIC_APP = \"Otwórz określoną aplikację\"\nIDS_EXE_FILTER = \"Aplikacje|*.exe|Pliki wsadowe|*.bat||\"\nIDS_PRESET = \"Ustawienie wstępne\"\nIDS_LIGHT_MODE = \"Tryb światła\"\nIDS_AUTO_ADAPT_TIP_INFO= \"Ta funkcja automatycznie przełączy ustawienia kolorów, gdy zmieni się ciemny/jasny motyw systemu Windows 10. Kliknij przycisk= \"\"Ustawienia Auto Adapt\"\", aby skonfigurować schemat ustawień wstępnych do automatycznego przełączania.\"\nIDS_WITHOUT_TEMPERATURE= \"Lite\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"Włączono funkcję Mouse Penetration. Jeśli chcesz wyłączyć funkcję Mouse Penetration, znajdź ikonę TrafficMonitor w obszarze powiadomień systemowych, kliknij prawym przyciskiem myszy i wyłącz funkcję Mouse Penetration w menu. Kliknij Anuluj, aby nie wyświetlać monitu.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"Wykryto utratę historycznych danych ruchu. Obecna liczba rekordów: <%1%>, <%2%> rekordów została odzyskana z pliku kopii zapasowej.\"\nIDS_LEGEND = \"Legenda\"\nIDS_LICENSE_EXPLAIN = \"Korzystając z kodu źródłowego tego oprogramowania, należy stosować się do następującego protokołu open source.\"\nIDS_LICENSE = \"Licencja\"\nIDS_DAY_VIEW = \"Widok dzienny\"\nIDS_MONTH_VIEW = \"Widok miesięczny\"\nIDS_QUARTER_VIEW = \"Widok kwartowy\"\nIDS_YEAR_VIEW = \"Widok roczny\"\nIDS_LINEAR_SCALE = \"Skala liniowa\"\nIDS_LOG_SCALE = \"Skala logarytmiczna\"\nIDS_CPU_TEMPERATURE = \"CPU Temperatura\"\nIDS_GPU_TEMPERATURE = \"GPU Temperatura\"\nIDS_CPU_FREQ = \"CPU Częstotliwość\"\nIDS_HDD_TEMPERATURE = \"Temperatura dysku twardego\"\nIDS_MAINBOARD_TEMPERATURE= \"Temperatura płyty głównej\"\nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"HDD\"\nIDS_MAINBOARD_DISP = \"MBD\"\nIDS_CPU_TEMPERATURE_EXCEED= \"CPU temperatura została osiągnięta\"\nIDS_GPU_TEMPERATURE_EXCEED= \"GPU temperatura została osiągnięta\"\nIDS_HDD_TEMPERATURE_EXCEED= \"Osiągnięto temperaturę dysku twardego\"\nIDS_MBD_TEMPERATURE_EXCEED= \"Osiągnięto temperaturę płyty głównej\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: Piękny i łatwy w obsłudze lokalny odtwarzacz muzyki dla systemu Windows\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: prosty edytor tekstu dla systemu Windows\"\nIDS_COLOR = \"Kolor\"\nIDS_COLOR_LABEL = \"Kolor etykiety\"\nIDS_COLOR_VALUE = \"Wartość koloru\"\nIDS_GPU_USAGE = \"GPU używanie\"\nIDS_IF_OPER_STATUS_UP = \"Adapter jest podłączony\"\nIDS_IF_OPER_STATUS_DOWN= \"Adapter nie jest podłączony\"\nIDS_IF_OPER_STATUS_DORMANT= \"Adapter się łączy\"\nIDS_GOTO_GITEE = \"Przejdź na stronę Gitee poświęconą temu projektowi.\"\nIDS_USAGE_PERCENTAGE = \"Użyty procent\"\nIDS_MEMORY_USED = \"Użyta pamięć\"\nIDS_MEMORY_AVAILABLE = \"Dostępna pamięć\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \".Net Framework v4.5.2 lub nowszy nie jest zainstalowany w systemie. Funkcja monitorowania temperatury nie będzie dostępna. Kliknij Anuluj, aby nie wyświetlać monitu.\"\nIDS_VERSION_UPDATE = \"Nowa aktualizacja wersji\"\nIDS_AVREAGE_TEMPERATURE= \"Średnia temperatura\"\nIDS_HARDWARE_MONITOR_WARNING = \"Ostrzeżenie: Włączasz funkcję monitorowania sprzętu. Funkcja monitorowania sprzętu może być używana do wyświetlania informacji o temperaturze i wykorzystaniu procesora graficznego. Przeczytaj uważnie poniższe informacje przed włączeniem funkcji monitorowania sprzętu:\\r\\nTrafficMonitor nie jest profesjonalnym oprogramowaniem do monitorowania sprzętu. Nie może zagwarantować, że informacje o sprzęcie można uzyskać na dowolnym komputerze, ani nie może zagwarantować dokładności uzyskanych informacji o sprzęcie.\\r\\nFunkcja monitorowania sprzętu jest implementowana przez trzecią bibliotekę LibreHardwareMonitor. Po włączeniu monitorowania sprzętu na niektórych komputerach mogą wystąpić pewne problemy, w tym, ale nie wyłącznie:\\r\\n* Nieprawidłowe wykorzystanie procesora i pamięci\\r\\n* Awaria programu\\r\\n* Załamanie komputera\\r\\nPodejmij decyzję o włączeniu funkcji monitorowania sprzętu po zapoznaniu się z powyższymi zagrożeniami. \\r\\nCzy na pewno chcesz włączyć funkcję monitorowania sprzętu?\"\nIDS_HDD_USAGE = \"Wykorzystanie dysku twardego\"\nIDS_FILE_NAME = \"Nazwa pliku\"\nIDS_STATUS = \"Status\"\nIDS_PLUGIN_LOAD_SUCCEED= \"Załaduj pomyślnie\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"Ładowanie modułu wtyczki nie powiodło się, kod błędu: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"Nie udało się przejąć funkcji, kod błędu: <%1%>\"\nIDS_PLUGIN_INFO = \"Szczegóły wtyczki\"\nIDS_NAME = \"Nazwa\"\nIDS_DESCRIPTION = \"Opis\"\nIDS_FILE_PATH = \"Ścieżka pliku\"\nIDS_ITEM_NUM = \"Wyświetlana liczba elementów\"\nIDS_ITEM_NAMES = \"Wyświetlane nazwy elementów\"\nIDS_AUTHOR = \"Autor\"\nIDS_COPYRIGHT = \"Prawa autorskie\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"Wtyczka nie udostępnia ustawień opcji.\"\nIDS_PLUGIN_NAME = \"Nazwa wtyczki\"\nIDS_DISABLED = \"Wyłączony\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Aby zastosować tę zmianę, uruchom ponownie program.\"\nIDS_VERSION = \"Wersja\"\nIDS_DISP_ITEM_ID = \"Wyświetlany ID elementu\"\nIDS_PLUGIN_API_VERSION = \"Wersja API\"\nIDS_WEEK_VIEW = \"Widok tygodniowy\"\nIDS_WEEK_NUM = \"Tydzień <%1%>\"\nIDS_URL = \"Url\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"Wersja wtyczki jest za niska.\"\nIDS_MODIFY_PRESET = \"Modyfikuj ustawienia wstępne\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"Wybierz przynajmniej jedną z nich!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"Gdy funkcja= \"\"Automatycznie dostosuj do ciemnego/jasnego motywu systemu Windows 10\"\" jest włączona, a ta opcja jest zaznaczona, po zmianie koloru okna paska zadań i ustawień koloru tła, ustawienia te są automatycznie zapisywane zgodnie z bieżącym ciemnym/jasnym motywem systemu Windows.\"\nIDS_TOTAL_NET_SPEED = \"Całkowita prędkość\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"Wyświetlaj wykresy wykorzystania zasobów procesora/pamięci, dysku twardego, informacje o temperaturze i elementach wtyczek.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"Wyświetla wskaźnik prędkości sieci dla wysyłania, pobierania i całkowitej prędkości sieci.\"\nIDS_REFRESH_CONNECTION_LIST= \"Odśwież listę połączeń\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"Nie udało się zainicjować funkcji monitorowania sprzętu, monitorowanie sprzętu nie będzie dostępne!\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Błąd podczas pobierania danych monitorowania sprzętu!\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"Tryb automatycznego uruchamiania: Rejestr\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"Tryb automatycznego uruchamiania: harmonogram zadań\"\nIDS_PATH = \"Ścieżka\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"Ustawienie automatycznego uruchamiania przy starcie nie powiodło się!\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Nie udało się zaktualizować zawartości okna paska zadań, renderowanie direct2d zostało wyłączone. Uwaga: okno ustawień może nie zaktualizować tego ustawienia natychmiast.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Wystąpił błąd podczas renderowania direct2d i renderowanie direct2d zostało wyłączone. Uwaga: okno ustawień może nie zaktualizować tej regulacji natychmiast.\"\nIDS_PLUGIN_OPTIONS = \"Opcje wtyczki\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"Nie udało się pobrać użycia CPU przez licznik wydajności, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"Główny wyświetlacz\"\nIDS_SECONDARY_DISPLAY = \"Wyświetlacz pomocniczy <%1%>\"\n\nTXT_OK = \"OK\"\nTXT_CANCEL = \"Anuluj\"\nTXT_CLOSE = \"Zamknij\"\nTXT_APPLY = \"Zastosuj\"\n\n; Text used for dialog. (Musi zaczynać się od „TXT_”)\n; CAboutDlg\nTXT_TITLE_ABOUT = \"O TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>, V<%2%>\"\nTXT_ABOUT_COPYRIGHT = \"Prawa autorskie (C) 2017-2025 ZhongYang\\nData ostatniej kompilacji: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%> Tłumaczenie: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"Biblioteki zewnętrzne wykorzystane w tym projekcie:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"Inne oprogramowanie autora:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"Skontaktuj się z autorem\"\nTXT_ABOUT_LICENSE = \"Licencja\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"Potwierdzenie\"\nTXT_ABOUT_DONATE = \"Darowizna\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor jest już uruchomiony.\"\nTXT_EXIT_THE_PROGRAM = \"W&yjdź z programu\"\nTXT_OPEN_OPTION_SETTINGS = \"Otwórz ustawienia &opcji\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"Pokaż/ukryj okno &główne\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"Pokaż/ukryj okno &paska zadań\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Ustawienia automatycznej adaptacji\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Ustawienia kolorów używane w ciemnym trybie systemu Windows:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Ustawienia kolorów używane w jasnym trybie Windows:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"Automatyczne zapisywanie ustawień kolorów okna paska zadań do ustawień wstępnych\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Ustawienia wyświetlania tekstu\"\nTXT_RESTORE_DEFAULT = \"Przywróć &domyślne\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Ustawienia aplikacji\"\nTXT_CHECK_UPDATE = \"Sprawdź dostępność aktualizacji podczas uruchamiania\"\nTXT_CHECK_NOW = \"&Sprawdź teraz\"\nTXT_UPDATE_SOURCE = \"Źródło aktualizacji:\"\nTXT_AUTO_RUN_CHECK = \"Automatyczne uruchamianie podczas uruchamiania systemu Windows\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Zresetuj i autostart\"\nTXT_LANGUAGE = \"Język:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"Pliki konfiguracyjne i danych\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Zapisz w katalogu Appdata\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Zapisz w katalogu programu\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Otwórz katalog plików &konfiguracyjnych\"\nTXT_NOTIFICATION_MESSAGE = \"Wiadomość powiadomienia\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"Powiadom, gdy dzisiejszy ruch zostanie osiągnięty\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"Powiadom, gdy zostanie osiągnięty limit wykorzystania pamięci\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"Powiadom, gdy temperatura CPU zostanie osiągnięta\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"Powiadom, gdy temperatura GPU zostanie osiągnięta\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"Powiadom, gdy temperatura dysku twardego zostanie osiągnięta\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"Powiadom, gdy temperatura płyty głównej zostanie osiągnięta\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Monitorowanie sprzętu\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"GPU\"\nTXT_HARD_DISK = \"Dysk twardy\"\nTXT_MAIN_BOARD = \"Płyta główna\"\nTXT_SELECT_HDD_STATIC = \"Wybierz dysk twardy, który chcesz monitorować:\"\nTXT_SELECT_CPU_STATIC = \"Wybierz temperaturę CPU, którą chcesz monitorować:\"\nTXT_ADVANCED = \"Zaawansowany\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Pokaż wszystkie połączenia sieciowe\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"&Wybierz połączenie do monitorowania...\"\nTXT_CPU_ACQUISITION_METHOD = \"Metoda pozyskiwania danych o wykorzystaniu CPU:\"\nTXT_USE_CPU_TIME_RADIO = \"Na podstawie czasu CPU\"\nTXT_USE_PDH_RADIO = \"Użyj licznika wydajności\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"Korzystanie z monitora sprzętowego\"\nTXT_MONITORING_INTERVALS = \"Interwały monitorowania:\"\nTXT_MILLISECONDS = \"milisekundy\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"&Przywróć domyślne\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Zarządzanie wtyczkami...\"\nTXT_DISPLAY = \"Wyświetlacz\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"Pokaż ikonę &Powiadom\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Rok:\"\nTXT_MONTH = \"Miesiąc:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Historyczne statystyki ruchu\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"Typ widoku:\"\nTXT_FIGURE_VIEW_SCALE = \"Skala widoku figury:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Zmień ikonę powiadomień\"\nTXT_SELECT_A_ICON = \"Wybierz ikonę:\"\nTXT_PREVIEW = \"Wersja zapoznawcza\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Automatyczne dostosowywanie do trybu ciemnego/jasnego systemu Windows 10\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Ustawienia kolorów głównego okna\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Ukryj okno główne, gdy program działa w trybie pełnoekranowym\"\nTXT_COLOR_AND_FONT = \"Kolor i czcionka\"\nTXT_FONT = \"Czcionka:\"\nTXT_FONT_SIZE = \"Rozmiar czcionki:\"\nTXT_SET_FONT_BUTTON = \"Wybierz &Czcionkę...\"\nTXT_TEXT_COLOR = \"Kolor tekstu:\"\nTXT_DISPLAY_TEXT = \"Wyświetl tekst\"\nTXT_SWITCH_UP_DOWN_CHECK = \"Zamień pozycję przesyłania i pobierania\"\nTXT_UNIT_SETTINGS = \"Ustawienia jednostki\"\nTXT_UNIT_SELECTION = \"Wybór jednostki:\"\nTXT_HIDE_UNIT_CHECK = \"Nie pokazuj jednostki prędkości\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Krótki tryb wyświetlania prędkości netto\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Nie pokazuj procentów\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Określ kolory dla każdego elementu\"\nTXT_DOUBLE_CLICK_ACTION = \"Akcja podwójnego kliknięcia:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Oddziel wartość i jednostkę spacją\"\nTXT_NETSPEED_UNIT = \"Jednostka Netspeed:\"\nTXT_UNIT_BYTE_RADIO = \"B (Byte)\"\nTXT_UNIT_BIT_RADIO = \"b (bit)\"\nTXT_SHOW_TOOL_TIP_CHK = \"Pokaż podpowiedź myszy\"\nTXT_EXE_PATH_STATIC = \"Określone zastosowanie:\"\nTXT_BROWSE_BUTTON = \"&Przeglądaj...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Ustawienia wyświetlania &tekstu...\"\nTXT_MEMORY_DISPLAY_MODE = \"Tryb wyświetlania pamięci:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Zawsze na szczycie\"\nTXT_MOUSE_PENETRATE_CHECK = \"Mysz penetruje\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Zablokuj pozycję okna\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Zezwalaj na wyjście poza granice ekranu\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Wiadomość\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Szczegóły połączenia\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Ustawienia opcji\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Zarządzanie wtyczkami\"\nTXT_OPTINS_BUTTON = \"&Opcje...\"\nTXT_PLUGIN_INFO_BUTTON = \"&Bliższe dane...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Przewodnik po tworzeniu wtyczek\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"Pobierz więcej wtyczek\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Otwórz katalog wtyczek\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Wybierz połączenie do monitorowaniar\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Ustawienia wyświetlania\"\nTXT_MOVE_UP_BUTTON = \"Podnieść\"\nTXT_MOVE_DOWN_BUTTON = \"Opuszczać\"\nTXT_RESTORE_DEFAULT_BUTTON = \"Przywróć &Domyślne\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Ustawienia automatycznego przełączania skórek\"\nTXT_SKIN_IN_DARK_MODE = \"Skórka używana w ciemnym trybie Windows:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Skórka używana w jasnym trybie Windows:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Zmień skórkę\"\nTXT_PREVIEW_GROUP_STATIC = \"Wersja zapoznawcza\"\nTXT_SELECT_A_SKIN = \"Wybierz skórkę\"\nTXT_SKIN_AUTHOR = \"Autor skórki:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Samouczek makijażu skóry\"\nTXT_DOWNLOAD_MORE_SKIN = \"Pobierz więcej skórek\"\nTXT_OPEN_SKIN_DIR = \"Otwórz katalog skórek\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Automatycznie przełączaj skórki w zależności od ciemnego / jasnego trybu kolorów systemu Windows.\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Ustawienia automatycznego przełączania...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"Ustawienia kolorów okna paska zadań\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Ustawienie wstępne\"\nTXT_BACKGROUND_COLOR = \"Kolor tła:\"\nTXT_BACKGROUND_TRANSPARENT = \"Tło przezroczyste\"\nTXT_AUTO_SET_BACK_COLOR = \"Automatyczne ustawienie koloru tła zgodnie z kolorem paska zadań\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Automatyczne dostosowywanie do ciemnych/jasnych motywów systemu Windows 10\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"Automatyczne dostosowywanie i ustawienia...\"\nTXT_DISPLAY_SETTINGS = \"Ustawienia wyświetlania\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"&Ustawienia wyświetlania...\"\nTXT_SPEED_SHORT_MODE = \"Krótki tryb wyświetlania prędkości netto\"\nTXT_VALUE_RIGHT_ALIGN = \"Wyrównaj wartości do prawej\"\nTXT_NET_SPEED_DATA_WIDTH = \"Szerokość danych prędkości netto:\"\nTXT_CHARACTORS = \"pismo\"\nTXT_HORIZONTAL_ARRANGE = \"Układ poziomy\"\nTXT_ITEM_SPACING = \"Odstęp między elementami:\"\nTXT_VERTICAL_MARGIN = \"Margines pionowy:\"\nTXT_PIXELS = \"piksele\"\nTXT_TASKBAR_WINDOW = \"Okno paska zadań\"\nTXT_TASKBAR_WND_ON_LEFT = \"Okno paska zadań pojawia się po lewej stronie paska zadań\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"Wyświetlacz pokazujący okno paska zadań:\"\nTXT_SHOW_TASKBAR_WND_IN_SECONDARY_DISPLAY = \"Pokaż okno paska zadań na wyświetlaczu pomocniczym (jeśli istnieje)\"\nTXT_WIN11_SETTINGS_BUTTON = \"Ustawienia związane z systemem Windows 11\"\nTXT_RESOURCE_USAGE_GRAPH = \"Wykres wykorzystania zasobów\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Pokaż wykres wykorzystania zasobów\"\nTXT_SHOW_DASHED_BOX = \"Pokaż przerywane pole\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Pokaż wykres prędkości netto\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"Maksymalna wartość wykresu prędkości netto:\"\nTXT_USAGE_GRAPH_COLOR = \"Kolor wykresu użycia:\"\nTXT_GRAPH_DISPLAY_MODE = \"Tryb wyświetlania wykresu:\"\nTXT_BAR_MODE = \"Tryb paskowy\"\nTXT_PLOT_MODE = \"Tryb fabuły\"\nTXT_RENDERING_SETTINGS = \"Ustawienia renderowania\"\nTXT_RENDERING_SETTINGS_NOTE = \"Uwaga: renderowanie Direct2D jest używane tylko wtedy, gdy zaznaczona jest opcja „Tło przezroczyste”, ale opcja „Automatycznie ustaw kolor tła zgodnie z kolorem paska zadań” nie jest zaznaczona.\"\nTXT_ENABLE_COLOR_EMOJI = \"Włącz kolorowe emoji\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Ustawienia związane z systemem Windows 11\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"Okno paska zadań zamknięte na ikonie zamiast na bokach paska zadań\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Przesunięcie pionowe okna:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Przesunięcie poziome okna:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Unikaj nakładania się z prawymi widżetami (zaznacz tę opcję, jeśli widżety pojawiają się po prawej stronie paska zadań)\"\nTXT_WIDGETS_WIDTH = \"Szerokość widżetów:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Pokaż skalę\"\nTXT_USE_LINEAR_SCALE = \"Użyj skali liniowej\"\nTXT_USE_LOG_SCALE = \"Użyj skali logarytmicznej\"\nTXT_FIRST_DAT_OF_WEEEK = \"Pierwszy dzień tygodnia\"\nTXT_SUNDAY = \"Niedziela\"\nTXT_MONDAY = \"Poniedziałek\"\nTXT_GO_TO_TODAY = \"Przejdź do dzisiaj\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"&Kopiuj tekst\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"&Wybierz połączenia sieciowe\"\nTXT_AUTO_SELECT = \"&Wybór automatyczny\"\nTXT_SELECT_ALL = \"&Zaznacz wszystko\"\nTXT_CONNECTION_DETAILS = \"Połączenie i szczegóły\"\nTXT_ALWAYS_ON_TOP = \"Zawsze na szczycie\"\nTXT_MOUSE_PENETRATE = \"Mysz i penetracja\"\nTXT_LOCK_WINDOW_POS = \"&Zablokuj pozycję okna\"\nTXT_SHOW_MORE_INFO = \"Pokaż więcej &informacje\"\nTXT_SHOW_TASKBAR_WINDOW = \"Pokaż pasek zadań &okno\"\nTXT_SHOW_MAIN_WINDOW = \"Pokaż &Główne okno\"\nTXT_WINDOW_OPACITY = \"Nieprzezroczystość okna\"\nTXT_OTHER_FUNCTIONS = \"Inne &Funkcje\"\nTXT_CHANGE_SKIN = \"Zmień &skórę...\"\nTXT_CHANGE_NOTIFY_ICON = \"Zmień ikonę i powiadom...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Zezwalaj na wyjścia poza ekran i granice\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"&Historyczne statystyki ruchu\"\nTXT_PLUGIN_MANAGE = \"Zarządzanie wtyczkami...\"\nTXT_OPTIONS = \"&Opcje...\"\nTXT_HELP_MENU = \"&Pomoc\"\nTXT_HELP = \"&Pomoc\"\nTXT_FAQ = \"&Często zadawane pytania\"\nTXT_UPDATE_LOG = \"Aktualizuj &dziennik\"\nTXT_ABOUT = \"&b...\"\nTXT_CHECK_UPDATE = \"&Sprawdź dostępność aktualizacji...\"\nTXT_EXIT = \"W&yjście\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"Ust&awienia wyświetlania...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"&Zamknij okno paska zadań\"\nTXT_TASK_MANAGER = \"&Menedżer zadań\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Bliższe dane...\"\nTXT_PLUGIN_OPTIONS = \"&Opcje...\"\nTXT_PLUGIN_DISABLE = \"W&yłączony\""
  },
  {
    "path": "TrafficMonitor/language/Portuguese_Brazilian.ini",
    "content": "[general]\nBCP_47 = \"pt-BR\"\nDISPLAY_NAME = \"Português (Brasil)\"\nTRANSLATOR = \"Cássio de Freitas e Silva, Maison da Silva\"\nTRANSLATOR_URL = \"\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; Tabela de Strings\nIDS_CHECK_UPDATE_FAILD = \"Falha ao verificar atualização; verifique sua conexão de rede!\"\nIDS_CHECK_UPDATE_ERROR = \"Falha ao verificar atualização e obteve informações incorretas do arquivo remoto; entre em contato com o autor!\"\nIDS_UPDATE_AVLIABLE = \"Nova versão V%s detectada; deseja atualizar agora?\"\nIDS_UPDATE_AVLIABLE2 = \"Nova versão V%s detectada, conteúdo da atualização:\\r\\n%s\\r\\nDeseja atualizar agora?\"\nIDS_ALREADY_UPDATED = \"Já está atualizado para a versão mais recente.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"Falha ao configurar execução automática no Windows; a chave correspondente não foi encontrada no Registro.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"Falha ao escrever a chave no Registro, talvez você não tenha permissão de acesso!\"\nIDS_AUTORUN_DELETE_FAILED = \"Falha ao excluir a chave do Registro, talvez você não tenha permissão de acesso!\"\nIDS_AN_INSTANCE_RUNNING= \"Já existe uma instância em execução.\"\nIDS_TRAFFIC_USED_TODAY = \"Tráfego usado hoje\"\nIDS_MEMORY_USAGE = \"Uso de memória\"\nIDS_CPU_USAGE = \"Uso de CPU\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Enviar um e-mail para o autor.\"\nIDS_GOTO_GITHUB = \"Ir para a página do projeto no GitHub.\"\nIDS_DONATE_ATHOUR = \"Doar ao autor\"\nIDS_UPLOAD = \"Upload\"\nIDS_DOWNLOAD = \"Download\"\nIDS_MEMORY = \"Memória\"\nIDS_UPLOAD_DISP = \"UP\"\nIDS_DOWNLOAD_DISP = \"DOWN\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"Aviso: Não foi possível salvar as configurações. Falha ao gravar no arquivo= \\\"<%file_path%>\\\"! Executar como administrador pode resolver o problema.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"O tamanho do buffer para armazenar as informações de conexão é insuficiente; a conexão foi reinicializada. (<%cnt%> vezes reinicializada)\"\nIDS_CONNECTION_NUM_CHANGED = \"Detectada mudança no número de conexões. A conexão foi recuperada. Anteriormente: <%before%>, agora: <%after%>. (<%cnt%> vezes reinicializada)\"\nIDS_CONNECTION_NOT_MATCH = \"Pode ter ocorrido uma exceção; a conexão selecionada não corresponde à esperada. A conexão foi recuperada. (<%cnt%> vezes reinicializada)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"A janela não foi inserida com sucesso na barra de tarefas; talvez esteja bloqueada por um software de segurança ou o menu Iniciar não foi fechado. Tente reiniciar o Explorer. O TrafficMonitor continuará tentando, mas sem exibir alerta. Código de erro:\"\nIDS_MEMORY_UDAGE_EXCEED= \"O uso de memória atingiu o limite configurado\"\nIDS_NOTIFY = \"Notificar\"\nIDS_TODAY_TRAFFIC_EXCEED = \"O tráfego de hoje atingiu o limite configurado\"\nIDS_DATE = \"Data\"\nIDS_TRAFFIC_USED = \"Tráfego total\"\nIDS_FIGURE = \"Gráfico\"\nIDS_DEFAULT_ICON = \"Ícone padrão\"\nIDS_ICON = \"Ícone\"\nIDS_INTERFACE_NAME = \"Nome da interface\"\nIDS_INTERFACE_DESCRIPTION= \"Descrição da interface\"\nIDS_CONNECTION_TYPE = \"Tipo de conexão\"\nIDS_IF_TYPE_OTHER = \"Outro tipo de rede\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"Rede Ethernet\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Rede Token Ring\"\nIDS_IF_TYPE_FDDI = \"Rede FDDI (Fibra)\"\nIDS_IF_TYPE_PPP = \"Rede PPP\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"Rede de loopback de software\"\nIDS_IF_TYPE_ATM = \"Rede ATM\"\nIDS_IF_TYPE_IEEE80211 = \"Rede sem fio IEEE 802.11\"\nIDS_IF_TYPE_TUNNEL = \"Rede de encapsulamento em túnel\"\nIDS_IF_TYPE_IEEE1394 = \"Rede IEEE 1394 (Firewire)\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"Rede banda larga móvel WiMax\"\nIDS_IF_TYPE_WWANPP = \"Rede banda larga móvel (GSM)\"\nIDS_IF_TYPE_WWANPP2 = \"Rede banda larga móvel (CDMA)\"\nIDS_UNKNOW_CONNECTION = \"Rede desconhecida\"\nIDS_SPEED = \"Velocidade\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"Endereço físico do adaptador\"\nIDS_IP_ADDRESS = \"Endereço IP\"\nIDS_SUBNET_MASK = \"Máscara de sub-rede\"\nIDS_DEFAULT_GATEWAY = \"Gateway padrão\"\nIDS_OPERATIONAL_STATUS = \"Status da conexão\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"Adaptador LAN desativado\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"Adaptador WAN não conectado\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"Cabo desconectado ou sem sinal\"\nIDS_IF_OPER_STATUS_CONNECTING = \"Adaptador WAN conectando\"\nIDS_IF_OPER_STATUS_CONNECTED = \"Adaptador WAN conectado\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"Adaptador LAN conectado\"\nIDS_UNKNOW_STATUS = \"Status desconhecido\"\nIDS_BYTES_RECEIVED = \"Bytes recebidos\"\nIDS_BYTES_SENT = \"Bytes enviados\"\nIDS_BYTES_RECEIVED_SINCE_START= \"Bytes recebidos desde o início do programa\"\nIDS_BYTES_SENT_SINCE_START= \"Bytes enviados desde o início do programa\"\nIDS_PROGRAM_ELAPSED_TIME= \"Tempo decorrido do programa\"\nIDS_HOUR_MINUTE_SECOND = \"%d horas, %d minutos, %d segundos\"\nIDS_INTERNET_IP_ADDRESS= \"Endereço IP da Internet\"\nIDS_GET_FAILED = \"Falha ao obter\"\nIDS_ITEM = \"Item\"\nIDS_VALUE = \"Valor\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"Falha ao copiar para a área de transferência!\"\nIDS_SKIN_AUTHOUR = \"Autor do tema:\"\nIDS_SPEED_SHORT_MODE_TIP = \"Quando marcado, a velocidade de rede será reduzida em 1 casa decimal e não exibirá a unidade= 'B'.\"\nIDS_AUTO = \"Automático\"\nIDS_FIXED_AS = \"Fixo como\"\nIDS_OPEN_CONNECTION_DETIAL= \"Abrir detalhes da conexão\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"Abrir histórico de estatísticas de tráfego\"\nIDS_SHOW_HIDE_MORE_INFO= \"Mostrar/ocultar mais informações\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"Mostrar/ocultar uso de CPU e memória\"\nIDS_OPEN_OPTION_SETTINGS= \"Abrir configurações\"\nIDS_OPEN_TASK_MANAGER = \"Abrir gerenciador de tarefas\"\nIDS_CHANGE_SKIN = \"Mudar tema\"\nIDS_NONE = \"Nenhum\"\nIDS_FONT_SIZE_WARNING = \"O tamanho da fonte deve ser entre %d e %d!\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"Aviso: A cor do texto é a mesma que a cor de fundo!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"Aviso: A cor de fundo é a mesma que a cor do texto!\"\nIDS_FOLLOWING_SYSTEM = \"Seguir o sistema\"\nIDS_LANGUAGE_CHANGE_INFO = \"Reinicie o aplicativo para aplicar a configuração de idioma.\"\nIDS_MAIN_WINDOW_SETTINGS= \"Configurações da Janela Principal\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"Configurações da Janela da Barra de Tarefas\"\nIDS_GENERAL_SETTINGS = \"Configurações Gerais\"\nIDS_ACQUIRING = \"Obtendo\"\nIDS_LIST_VIEW = \"Visualização em Lista\"\nIDS_CALENDAR_VIEW = \"Visualização em Calendário\"\nIDS_MONDAY = \"Seg\"\nIDS_TUESDAY = \"Ter\"\nIDS_WEDNESDAY = \"Qua\"\nIDS_THURSDAY = \"Qui\"\nIDS_FRIDAY = \"Sex\"\nIDS_SATURDAY = \"Sáb\"\nIDS_SUNDAY = \"Dom\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"Tráfego total do mês atual:\"\nIDS_TRAFFIC_USED1 = \"Tráfego usado:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Falha ao inserir na barra de tarefas, tentativa <%cnt%>. GetLastError(): <%error_code%>.\"\nIDS_NO_CONNECTION = \"Nenhuma conexão\"\nIDS_CONTACT_TRANSLATOR = \"Contatar este tradutor.\"\nIDS_THANKS_DONORS = \"Agradecimentos aos seguintes doadores:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"Ocorreu um erro ao solicitar= '<%1%>', código de erro: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"Quando esta opção estiver marcada, todas as interfaces de rede serão exibidas na lista= 'Selecionar Conexões de Rede' no menu de clique direito. Recomenda-se marcar apenas quando necessário.\"\nIDS_CFG_DIR_CHANGED_INFO = \"Você alterou o local onde os arquivos de configuração e dados são salvos. Isso terá efeito após reiniciar. Talvez seja necessário transferir os arquivos manualmente para o novo local.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<Clique duas vezes aqui para obter.>\"\nIDS_ERROR1 = \"Erro\"\nIDS_ERROR_MESSAGE = \"Mensagem de Erro:\"\nIDS_CRASH_INFO = \"Desculpe, o programa travou. Por favor, reinicie o programa. \\r\\nSe você encontrar este problema muitas vezes, tente desativar a função de monitoramento de hardware em 'Opções' > 'Configurações Gerais', e desativar todos os plugins no gerenciador de plugins. \\r\\nSe o problema persistir, envie este arquivo= '<%1%>' para bugreport-zhongyang219@outlook.com, ajudando o autor a localizar o problema. Inclua no corpo da mensagem as informações a seguir:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"Reconhecimentos\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Tem certeza de que deseja salvar as configurações de cor da barra de tarefas atual em= 'Predefinição <%1%>'?\"\nIDS_SPECIFIC_APP = \"Abrir aplicativo especificado\"\nIDS_EXE_FILTER = \"Aplicativos|*.exe|Arquivos de lote|*.bat||\"\nIDS_PRESET = \"Predefinição\"\nIDS_LIGHT_MODE = \"Modo claro\"\nIDS_AUTO_ADAPT_TIP_INFO= \"Esta função alternará automaticamente as predefinições de cor conforme o tema Escuro/Claro do Windows 10. Clique em 'Configurações de adaptação automática' para configurar as predefinições.\"\nIDS_WITHOUT_TEMPERATURE= \"Leve\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"Penetração do mouse está ativada. Se precisar desativar, localize o ícone do TrafficMonitor na área de notificação, clique com o botão direito, e desmarque 'Penetração do mouse'. Clique em Cancelar para não exibir mais este aviso.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"Perda de dados de tráfego histórico detectada. Número atual de registros: <%1%>, <%2%> registros foram recuperados do arquivo de backup.\"\nIDS_LEGEND = \"Legenda\"\nIDS_LICENSE_EXPLAIN = \"Siga o protocolo de software livre ao usar o código-fonte deste software.\"\nIDS_LICENSE = \"Licença\"\nIDS_DAY_VIEW = \"Visão diária\"\nIDS_MONTH_VIEW = \"Visão mensal\"\nIDS_QUARTER_VIEW = \"Visão trimestral\"\nIDS_YEAR_VIEW = \"Visão anual\"\nIDS_LINEAR_SCALE = \"Escala linear\"\nIDS_LOG_SCALE = \"Escala logarítmica\"\nIDS_CPU_TEMPERATURE = \"Temperatura da CPU\"\nIDS_GPU_TEMPERATURE = \"Temperatura da GPU\"\nIDS_CPU_FREQ = \"Freq. CPU\"\nIDS_HDD_TEMPERATURE = \"Temperatura do Disco\"\nIDS_MAINBOARD_TEMPERATURE= \"Temperatura da Placa-mãe\"\nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"DISCO\"\nIDS_MAINBOARD_DISP = \"PL.M\"\nIDS_CPU_TEMPERATURE_EXCEED= \"Temperatura da CPU atingiu o limite\"\nIDS_GPU_TEMPERATURE_EXCEED= \"Temperatura da GPU atingiu o limite\"\nIDS_HDD_TEMPERATURE_EXCEED= \"Temperatura do disco atingiu o limite\"\nIDS_MBD_TEMPERATURE_EXCEED= \"Temperatura da placa-mãe atingiu o limite\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: Um player de música local para Windows, bonito e fácil de usar\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: Um editor de texto simples para Windows\"\nIDS_COLOR = \"Cor\"\nIDS_COLOR_LABEL = \"Cor do rótulo\"\nIDS_COLOR_VALUE = \"Cor do valor\"\nIDS_GPU_USAGE = \"Uso de GPU\"\nIDS_IF_OPER_STATUS_UP = \"Adaptador conectado\"\nIDS_IF_OPER_STATUS_DOWN= \"Adaptador não conectado\"\nIDS_IF_OPER_STATUS_DORMANT= \"Adaptador conectando\"\nIDS_GOTO_GITEE = \"Ir para a página do projeto no Gitee.\"\nIDS_USAGE_PERCENTAGE = \"Porcentagem de uso\"\nIDS_MEMORY_USED = \"Memória em uso\"\nIDS_MEMORY_AVAILABLE = \"Memória disponível\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \"O .Net Framework v4.5.2 ou superior não está instalado. A função de monitoramento de temperatura não estará disponível. Clique em Cancelar para não exibir mais este aviso.\"\nIDS_VERSION_UPDATE = \"Nova versão disponível\"\nIDS_AVREAGE_TEMPERATURE= \"Temperatura média\"\nIDS_HARDWARE_MONITOR_WARNING = \"Aviso: você está ativando a função de monitoramento de hardware, que permite exibir temperatura e uso de GPU. Leia atentamente antes de ativar:\\r\\nTrafficMonitor não é um software profissional de monitoramento de hardware. Não há garantia de que as informações de hardware serão obtidas em todos os computadores, nem da precisão dos dados obtidos.\\r\\nO monitoramento de hardware é implementado pela biblioteca LibreHardwareMonitor. Podem ocorrer problemas em alguns computadores, incluindo mas não se limitando a:\\r\\n* Uso anormal de CPU e memória\\r\\n* Travamento do programa\\r\\n* Travamento do computador\\r\\nAtive a função de monitoramento de hardware por sua conta e risco.\\r\\nDeseja realmente ativar a função de monitoramento de hardware?\"\nIDS_HDD_USAGE = \"Uso de disco\"\nIDS_FILE_NAME = \"Nome do arquivo\"\nIDS_STATUS = \"Status\"\nIDS_PLUGIN_LOAD_SUCCEED= \"Carregado com sucesso\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"Falha ao carregar módulo de plug-in, código de erro: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"Falha ao obter função, código de erro: <%1%>\"\nIDS_PLUGIN_INFO = \"Detalhes do plug-in\"\nIDS_NAME = \"Nome\"\nIDS_DESCRIPTION = \"Descrição\"\nIDS_FILE_PATH = \"Caminho do arquivo\"\nIDS_ITEM_NUM = \"Número de itens exibidos\"\nIDS_ITEM_NAMES = \"Nomes dos itens exibidos\"\nIDS_AUTHOR = \"Autor\"\nIDS_COPYRIGHT = \"Direitos autorais\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"O plug-in não fornece configurações adicionais.\"\nIDS_PLUGIN_NAME = \"Nome do plug-in\"\nIDS_DISABLED = \"Desativado\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Reinicie o programa para aplicar essa alteração.\"\nIDS_VERSION = \"Versão\"\nIDS_DISP_ITEM_ID = \"ID do item exibido\"\nIDS_PLUGIN_API_VERSION = \"Versão da API\"\nIDS_WEEK_VIEW = \"Visão semanal\"\nIDS_WEEK_NUM = \"Semana <%1%>\"\nIDS_URL = \"URL\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"A versão do plug-in é muito baixa.\"\nIDS_MODIFY_PRESET = \"Modificar Predefinição\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"Selecione ao menos um!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"Quando a função 'Adaptar automaticamente ao tema Escuro/Claro do Windows 10' estiver ativada, se esta opção estiver marcada, as alterações de cor da janela da barra de tarefas serão salvas automaticamente na predefinição correspondente ao tema atual do Windows.\"\nIDS_TOTAL_NET_SPEED = \"Velocidade total\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"Exibir gráficos de uso de recursos para CPU/memória, temperatura e itens de plug-ins.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"Exibir gráfico de velocidade de rede para envio, recebimento e velocidade total.\"\nIDS_REFRESH_CONNECTION_LIST= \"Atualizar lista de conexões\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"Falha ao inicializar a função de monitoramento de hardware; não estará disponível!\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Erro ao obter dados de monitoramento de hardware!\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"Modo de inicialização automática: Registro\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"Modo de inicialização automática: Tarefa agendada\"\nIDS_PATH = \"Caminho\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"Falha ao definir execução automática!\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Falha ao atualizar o conteúdo da janela da barra de tarefas; a renderização Direct2D foi desativada. Observação: as configurações podem não refletir imediatamente esta mudança.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Ocorreu um erro durante a renderização Direct2D; a renderização Direct2D foi desativada. Observação: as configurações podem não refletir imediatamente esta mudança.\"\nIDS_PLUGIN_OPTIONS = \"Opções do Plug-in\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"Falha ao obter uso da CPU por contadores de desempenho, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"Monitor principal\"\nIDS_SECONDARY_DISPLAY = \"Monitor secundário <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"O sistema retornou do modo de hibernação; a conexão foi reinicializada. (<%1%> vezes)\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"Atualização disponível, versão mais recente: <%1%>\"\nIDS_TRAFFICMONITOR_PLUGIN_NITIFICATION = \"Notificação do Plugin do TrafficMonitor\"\nIDS_SKIN_FILE_ERROR_INFO = \"Falha ao analisar o arquivo do tema!\"\n\nTXT_OK = \"OK\"\nTXT_CANCEL = \"Cancelar\"\nTXT_CLOSE = \"Fechar\"\nTXT_APPLY = \"Aplicar\"\n\n; Texto usado em diálogos (deve começar com \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"Sobre TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>, V<%2%>\"\nTXT_ABOUT_COPYRIGHT = \"Copyright (C) 2017-2025 por ZhongYang\\nData de compilação: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%> Tradutor: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"Bibliotecas de terceiros usadas neste projeto:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"Outros softwares do autor:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"Contatar autor\"\nTXT_ABOUT_LICENSE = \"Licença\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"Reconhecimentos\"\nTXT_ABOUT_DONATE = \"Doar\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"O TrafficMonitor já está em execução.\"\nTXT_EXIT_THE_PROGRAM = \"&Sair do programa\"\nTXT_OPEN_OPTION_SETTINGS = \"Abrir &configurações\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"Mostrar/ocultar &janela principal\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"Mostrar/ocultar &janela da barra de tarefas\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Configurações de adaptação automática\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Predefinição de cor para o modo escuro do Windows:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Predefinição de cor para o modo claro do Windows:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"Salvar automaticamente as configurações de cor da barra de tarefas na predefinição\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Configurações de Texto\"\nTXT_RESTORE_DEFAULT = \"Restaurar &padrão\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Configurações de Aplicativo\"\nTXT_CHECK_UPDATE = \"Verificar atualizações na inicialização\"\nTXT_CHECK_NOW = \"Verificar &agora\"\nTXT_UPDATE_SOURCE = \"Fonte de atualização:\"\nTXT_AUTO_RUN_CHECK = \"Executar automaticamente com o Windows\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Redefinir autoexecução\"\nTXT_LANGUAGE = \"Idioma:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"Configuração e arquivos de dados\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Salvar no diretório AppData\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Salvar no diretório do programa\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Abrir &diretório de configuração\"\nTXT_NOTIFICATION_MESSAGE = \"Mensagem de Notificação\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"Notificar quando o tráfego de hoje atingir\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"Notificar quando o uso de memória atingir\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"Notificar quando a temperatura da CPU atingir\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"Notificar quando a temperatura da GPU atingir\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"Notificar quando a temperatura do Disco atingir\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"Notificar quando a temperatura da Placa-mãe atingir\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Monitoramento de Hardware\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"GPU\"\nTXT_HARD_DISK = \"Disco\"\nTXT_MAIN_BOARD = \"Placa-mãe\"\nTXT_SELECT_HDD_STATIC = \"Selecione o disco a ser monitorado:\"\nTXT_SELECT_CPU_STATIC = \"Selecione a CPU a ser monitorada:\"\nTXT_ADVANCED = \"Avançado\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Mostrar todas as conexões de rede\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"&Selecionar conexões...\"\nTXT_CPU_ACQUISITION_METHOD = \"Método de aquisição do uso de CPU:\"\nTXT_USE_CPU_TIME_RADIO = \"Baseado em tempo de CPU\"\nTXT_USE_PDH_RADIO = \"Usar contador de desempenho\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"Usar monitor de hardware\"\nTXT_MONITORING_INTERVALS = \"Intervalos de monitoramento:\"\nTXT_MILLISECONDS = \"milissegundos\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"&Restaurar padrão\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Gerenciar plug-ins...\"\nTXT_DISPLAY = \"Exibir\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"Mostrar ícone na &área de notificação\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Ano:\"\nTXT_MONTH = \"Mês:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Estatísticas de Tráfego Histórico\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"Tipo de visualização:\"\nTXT_FIGURE_VIEW_SCALE = \"Escala de visualização do gráfico:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Mudar Ícone\"\nTXT_SELECT_A_ICON = \"Selecione um ícone:\"\nTXT_PREVIEW = \"Prévia\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Adaptar automaticamente ao modo Escuro/Claro do Windows 10\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Configurações de Cor da Janela Principal\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Ocultar janela principal quando um programa estiver em tela cheia\"\nTXT_COLOR_AND_FONT = \"Cor e Fonte\"\nTXT_FONT = \"Fonte:\"\nTXT_FONT_SIZE = \"Tamanho da fonte:\"\nTXT_SET_FONT_BUTTON = \"Escolher &Fonte...\"\nTXT_TEXT_COLOR = \"Cor do texto:\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"Restaurar padrão do tema\"\nTXT_DISPLAY_TEXT = \"Exibição de Texto\"\nTXT_SWITCH_UP_DOWN_CHECK = \"Inverter as posições de envio e recebimento\"\nTXT_UNIT_SETTINGS = \"Configurações de unidade\"\nTXT_UNIT_SELECTION = \"Seleção de unidade:\"\nTXT_HIDE_UNIT_CHECK = \"Não mostrar unidade de velocidade\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Modo de exibição reduzido para velocidade\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Não mostrar porcentagem\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Especificar cores para cada item\"\nTXT_DOUBLE_CLICK_ACTION = \"Ação de duplo clique:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Separar valor e unidade com espaço\"\nTXT_NETSPEED_UNIT = \"Unidade de velocidade de rede:\"\nTXT_UNIT_BYTE_RADIO = \"B (Byte)\"\nTXT_UNIT_BIT_RADIO = \"b (bit)\"\nTXT_SHOW_TOOL_TIP_CHK = \"Mostrar dica ao passar o mouse\"\nTXT_EXE_PATH_STATIC = \"Aplicativo especificado:\"\nTXT_BROWSE_BUTTON = \"&Procurar...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Configurações de &Texto...\"\nTXT_MEMORY_DISPLAY_MODE = \"Modo de exibição de memória:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Sempre no topo\"\nTXT_MOUSE_PENETRATE_CHECK = \"Penetração do mouse\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Travar posição da janela\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Permitir sair dos limites da tela\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Mensagem\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Detalhes da Conexão\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Configurações\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Gerenciar Plug-ins\"\nTXT_OPTINS_BUTTON = \"&Opções...\"\nTXT_PLUGIN_INFO_BUTTON = \"&Detalhes...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Guia de desenvolvimento de plug-ins\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"Baixar mais plug-ins\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Abrir diretório de plug-ins\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Selecionar Conexões de Rede\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Configurações de Exibição\"\nTXT_MOVE_UP_BUTTON = \"Mover para Cima\"\nTXT_MOVE_DOWN_BUTTON = \"Mover para Baixo\"\nTXT_RESTORE_DEFAULT_BUTTON = \"Restaurar &Padrão\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Configurações de troca automática de tema\"\nTXT_SKIN_IN_DARK_MODE = \"Tema usado no modo escuro do Windows:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Tema usado no modo claro do Windows:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Mudar Tema\"\nTXT_PREVIEW_GROUP_STATIC = \"Prévia\"\nTXT_SELECT_A_SKIN = \"Selecionar um tema\"\nTXT_SKIN_AUTHOR = \"Autor do tema:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Tutorial de criação de temas\"\nTXT_DOWNLOAD_MORE_SKIN = \"Baixar mais temas\"\nTXT_OPEN_SKIN_DIR = \"Abrir diretório de temas\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Alternar automaticamente conforme modo Escuro/Claro do Windows\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Configurações de troca automática...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"Configurações de Cor da Janela da Barra de Tarefas\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Predefinição\"\nTXT_BACKGROUND_COLOR = \"Cor de fundo:\"\nTXT_BACKGROUND_TRANSPARENT = \"Fundo transparente\"\nTXT_AUTO_SET_BACK_COLOR = \"Definir cor de fundo automaticamente conforme a cor da barra de tarefas\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Adaptar automaticamente ao modo Escuro/Claro do Windows 10\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"Configurações de &Adaptação...\"\nTXT_DISPLAY_SETTINGS = \"Configurações de Exibição\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"&Configurações de exibição...\"\nTXT_SPEED_SHORT_MODE = \"Modo de exibição reduzido de velocidade\"\nTXT_VALUE_RIGHT_ALIGN = \"Alinhar valores à direita\"\nTXT_NET_SPEED_DATA_WIDTH = \"Largura dos dados de velocidade de rede:\"\nTXT_CHARACTORS = \"caracteres\"\nTXT_HORIZONTAL_ARRANGE = \"Organização horizontal\"\nTXT_ITEM_SPACING = \"Espaçamento entre itens:\"\nTXT_VERTICAL_MARGIN = \"Margem vertical:\"\nTXT_PIXELS = \"pixels\"\nTXT_TASKBAR_WINDOW = \"Janela da barra de tarefas\"\nTXT_TASKBAR_WND_ON_LEFT = \"Janela da barra de tarefas à esquerda da barra\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"Tela em que a barra de tarefas será exibida:\"\nTXT_WIN11_SETTINGS_BUTTON = \"Configurações relacionadas ao Windows 11\"\nTXT_RESOURCE_USAGE_GRAPH = \"Gráfico de uso de recursos\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Exibir gráfico de uso de recursos\"\nTXT_SHOW_DASHED_BOX = \"Exibir caixa tracejada\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Exibir gráfico de velocidade de rede\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"Valor máximo do gráfico de velocidade de rede:\"\nTXT_USAGE_GRAPH_COLOR = \"Cor do gráfico de uso:\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"Seguir cor do tema do Windows\"\nTXT_GRAPH_DISPLAY_MODE = \"Modo de exibição do gráfico:\"\nTXT_BAR_MODE = \"Modo barras\"\nTXT_PLOT_MODE = \"Modo plot\"\nTXT_RENDERING_SETTINGS = \"Configurações de renderização\"\nTXT_RENDERING_SETTINGS_NOTE = \"Obs.: A renderização Direct2D só é usada quando 'Fundo transparente' está marcado e 'Definir cor de fundo automaticamente...' não está marcado.\"\nTXT_ENABLE_COLOR_EMOJI = \"Ativar emoji colorido\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Configurações relacionadas ao Windows 11\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"Janela da barra de tarefas próxima ao ícone em vez das extremidades\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Offset vertical da janela:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Offset horizontal da janela:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Evitar sobrepor widgets da direita (marque se os widgets aparecem à direita da barra de tarefas)\"\nTXT_WIDGETS_WIDTH = \"Largura dos widgets:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Mostrar Escala\"\nTXT_USE_LINEAR_SCALE = \"Usar Escala Linear\"\nTXT_USE_LOG_SCALE = \"Usar Escala Logarítmica\"\nTXT_FIRST_DAT_OF_WEEEK = \"Primeiro dia da semana\"\nTXT_SUNDAY = \"Domingo\"\nTXT_MONDAY = \"Segunda-feira\"\nTXT_GO_TO_TODAY = \"Ir para hoje\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"&Copiar Texto\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"&Selecionar Conexões de Rede\"\nTXT_AUTO_SELECT = \"&Seleção Automática\"\nTXT_SELECT_ALL = \"&Selecionar Tudo\"\nTXT_CONNECTION_DETAILS = \"Detalhes da &Conexão\"\nTXT_ALWAYS_ON_TOP = \"Sempre no &Topo\"\nTXT_MOUSE_PENETRATE = \"P&enetração do Mouse\"\nTXT_LOCK_WINDOW_POS = \"&Travar Posição da Janela\"\nTXT_SHOW_MORE_INFO = \"Mostrar Mais &Informações\"\nTXT_SHOW_TASKBAR_WINDOW = \"Mostrar Janela da &Barra de Tarefas\"\nTXT_SHOW_MAIN_WINDOW = \"Mostrar &Janela Principal\"\nTXT_WINDOW_OPACITY = \"O&pacidade da Janela\"\nTXT_OTHER_FUNCTIONS = \"Outras &Funções\"\nTXT_CHANGE_SKIN = \"Mudar &Tema...\"\nTXT_CHANGE_NOTIFY_ICON = \"Mudar &Ícone...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Permitir &Sair dos Limites da Tela\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"Estatísticas de &Tráfego Histórico\"\nTXT_PLUGIN_MANAGE = \"Gerenciar Plug-&ins...\"\nTXT_OPTIONS = \"&Opções...\"\nTXT_HELP_MENU = \"&Ajuda\"\nTXT_HELP = \"&Ajuda\"\nTXT_FAQ = \"&Perguntas Frequentes\"\nTXT_UPDATE_LOG = \"&Log de Atualizações\"\nTXT_ABOUT = \"&Sobre...\"\nTXT_CHECK_UPDATE = \"Verificar &Atualizações...\"\nTXT_EXIT = \"S&air\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"Configurações de &Exibição...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"Fe&char Janela da Barra de Tarefas\"\nTXT_TASK_MANAGER = \"Gerenciador de &Tarefas\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Detalhes...\"\nTXT_PLUGIN_OPTIONS = \"&Opções...\"\nTXT_PLUGIN_DISABLE = \"Desa&tivar\"\n\n;IDR_DISPLAY_ITEM_CONTEXT_MENU\nTXT_RESTORE_DEFAULT = \"&Restaurar Padrão\"\n"
  },
  {
    "path": "TrafficMonitor/language/Russian.ini",
    "content": "﻿[general]\nBCP_47 = \"ru-RU\"\nDISPLAY_NAME = \"Russian\"\nTRANSLATOR = \"Dmitry Yerokhin\"\nTRANSLATOR_URL = \"mailto:erodim@mail.ru\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"Не удалось проверить наличие новой версии. Убедитесь, что есть соединение с Интернетом.\"\nIDS_CHECK_UPDATE_ERROR = \"Не удалось проверить наличие новой версии, получена неверная информация из файла удалённого обновления. Свяжитесь с автором.\"\nIDS_UPDATE_AVLIABLE = \"Доступна новая версия %s, загрузить её?\"\nIDS_UPDATE_AVLIABLE2 = \"Доступна новая версия %s, содержимое: \\r\\n%s\\r\\nВыполнить обновление?\"\nIDS_ALREADY_UPDATED = \"У вас самая новая версия.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"Не удалось включить автозапуск при старте Windows, не найден соответствующий раздел в реестре.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"Не удалось записать ключ реестра, возможно, у вас нет разрешения на доступ к этому ключу.\"\nIDS_AUTORUN_DELETE_FAILED = \"Не удалось удалить ключ реестра, возможно, у вас нет разрешения на доступ к этому ключу.\"\nIDS_AN_INSTANCE_RUNNING= \"Экземпляр уже запущен.\"\nIDS_TRAFFIC_USED_TODAY = \"Трафик за сегодня\"\nIDS_MEMORY_USAGE = \"Использование памяти\"\nIDS_CPU_USAGE = \"Использование ЦП\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Отправить письмо автору.\"\nIDS_GOTO_GITHUB = \"Перейти на страницу проекта на GitHub.\"\nIDS_DONATE_ATHOUR = \"Помочь автору\"\nIDS_UPLOAD = \"Отправка\"\nIDS_DOWNLOAD = \"Загрузка\"\nIDS_MEMORY = \"Память\"\nIDS_UPLOAD_DISP = \"\u0018\"\nIDS_DOWNLOAD_DISP = \"\u0019\"\nIDS_MEMORY_DISP = \"ОЗУ\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"ВНИМАНИЕ: Невозможно сохранить настройки, не удаётся записать данные в файл= \"\"<%file_path%>\"\". Попробуйте запустить программу с правами администратора.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"Недостаточен размер буфера для хранения информации о соединении, оно было повторно инициализировано. (Переинициализаций: <%cnt%>)\"\nIDS_CONNECTION_NUM_CHANGED = \"Изменён номер подключения. Соединение восстановлено. Предыдущие подключения: <%before%>, нынешние: <%after%>. (Переинициализаций: <%cnt%>)\"\nIDS_CONNECTION_NOT_MATCH = \"Возможно, произошло исключение, выбранное сейчас соединение не соответствует ожидаемому соединению. Соединение восстановлено. (Переинициализаций: <%cnt%>)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"Не удалось встроить окно в панель задач, возможно, оно заблокировано защитным ПО, либо не закрыто меню \"Пуск\". Попробуйте перезапустить Проводник. TrafficMonitor будет продолжать попытки, но без напоминаний, код ошибки:\"\nIDS_MEMORY_UDAGE_EXCEED= \"Достигнут предельный уровень использования памяти\"\nIDS_NOTIFY = \"Уведомлять\"\nIDS_TODAY_TRAFFIC_EXCEED = \"Достигнут предельный трафик за сегодня\"\nIDS_DATE = \"Дата\"\nIDS_TRAFFIC_USED = \"Общий трафик\"\nIDS_FIGURE = \"Число\"\nIDS_DEFAULT_ICON = \"Стандартный значок\"\nIDS_ICON = \"Значок\"\nIDS_INTERFACE_NAME = \"Интерфейс\"\nIDS_INTERFACE_DESCRIPTION= \"Описание интерфейса\"\nIDS_CONNECTION_TYPE = \"Тип подключения\"\nIDS_IF_TYPE_OTHER = \"Другой тип сети\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"Сеть Ethernet\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Сеть Token Ring\"\nIDS_IF_TYPE_FDDI = \"Сеть FDDI (Fiber Distributed Data Interface)\"\nIDS_IF_TYPE_PPP = \"Сеть PPP\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"Программная loopback-сеть\"\nIDS_IF_TYPE_ATM = \"Сеть ATM\"\nIDS_IF_TYPE_IEEE80211 = \"Беспроводная сеть IEEE 802.11\"\nIDS_IF_TYPE_TUNNEL = \"Сеть инкапсуляции туннельного типа\"\nIDS_IF_TYPE_IEEE1394 = \"Последовательная высокоскоростная шина IEEE 1394 (FireWire)\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"Мобильный широкополосный интерфейс для устройств WiMax\"\nIDS_IF_TYPE_WWANPP = \"Мобильный широкополосный интерфейс для устройств GSM\"\nIDS_IF_TYPE_WWANPP2 = \"Мобильный широкополосный интерфейс для устройств CDMA\"\nIDS_UNKNOW_CONNECTION = \"Неизвестная сеть\"\nIDS_SPEED = \"Скорость\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"Физический адрес адаптера\"\nIDS_IP_ADDRESS = \"IP-адрес\"\nIDS_SUBNET_MASK = \"Маска подсети\"\nIDS_DEFAULT_GATEWAY = \"Шлюз по умолчанию\"\nIDS_OPERATIONAL_STATUS = \"Состояние подключения\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"Сетевой адаптер отключён\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"WAN-адаптер не подключён\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"сетевой кабель отключён или нет оператора связи\"\nIDS_IF_OPER_STATUS_CONNECTING = \"WAN-адаптер в процессе подключения\"\nIDS_IF_OPER_STATUS_CONNECTED = \"WAN-адаптер, подключённый к удалённому узлу\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"Подключённые сетевые адаптеры\"\nIDS_UNKNOW_STATUS = \"Неизвестное состояние\"\nIDS_BYTES_RECEIVED = \"Получено байт\"\nIDS_BYTES_SENT = \"Отправлено байт\"\nIDS_BYTES_RECEIVED_SINCE_START= \"Получено байт с момента запуска программы\"\nIDS_BYTES_SENT_SINCE_START= \"Отправлено байт с момента запуска программы\"\nIDS_PROGRAM_ELAPSED_TIME= \"Время работы программы\"\nIDS_HOUR_MINUTE_SECOND = \"%d ч, %d мин, %d сек\"\nIDS_INTERNET_IP_ADDRESS= \"IP-адрес в Интернете\"\nIDS_GET_FAILED = \"Получить не удалось\"\nIDS_ITEM = \"Элемент\"\nIDS_VALUE = \"Значение\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"Не удалось скопировать в буфер обмена!\"\nIDS_SKIN_AUTHOUR = \"Автор скина:\"\nIDS_SPEED_SHORT_MODE_TIP = \"Если включено, отображение скорости сети будет уменьшено на 1 знак после запятой, и не будет отображаться= \"\"B\"\".\"\nIDS_AUTO = \"Авто\"\nIDS_FIXED_AS = \"Всегда\"\nIDS_OPEN_CONNECTION_DETIAL= \"Показать сведения о подключении\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"Показать статистику трафика\"\nIDS_SHOW_HIDE_MORE_INFO= \"Показать/скрыть подробности\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"Показать/скрыть использование ЦП и ОЗУ\"\nIDS_OPEN_OPTION_SETTINGS= \"Открыть настройки\"\nIDS_OPEN_TASK_MANAGER = \"Открыть диспетчер задач\"\nIDS_CHANGE_SKIN = \"Сменить скин\"\nIDS_NONE = \"Нет\"\nIDS_FONT_SIZE_WARNING = \"Размер шрифта должен быть между %d и %d.\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"ВНИМАНИЕ: Цвет текста такой же, как и цвет фона!\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"ВНИМАНИЕ: Цвет фона такой же, как и цвет текста!\"\nIDS_FOLLOWING_SYSTEM = \"Как в системе\"\nIDS_LANGUAGE_CHANGE_INFO = \"Перезапустите приложение, чтобы применить языковые настройки.\"\nIDS_MAIN_WINDOW_SETTINGS= \"Главное окно\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"Окно панели задач\"\nIDS_GENERAL_SETTINGS = \"Общие настройки\"\nIDS_ACQUIRING = \"Получение\"\nIDS_LIST_VIEW = \"Список\"\nIDS_CALENDAR_VIEW = \"Календарь\"\nIDS_MONDAY = \"Пн\"\nIDS_TUESDAY = \"Вт\"\nIDS_WEDNESDAY = \"Ср\"\nIDS_THURSDAY = \"Чт\"\nIDS_FRIDAY = \"Пт\"\nIDS_SATURDAY = \"Сб\"\nIDS_SUNDAY = \"Вс\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"Трафик за текущий месяц:\"\nIDS_TRAFFIC_USED1 = \"Трафик:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Не удалось вставить в панель задач, повторов: <%cnt%>. GetLastError(): <%error_code%>.\"\nIDS_NO_CONNECTION = \"Нет соединения\"\nIDS_CONTACT_TRANSLATOR = \"Свяжитесь с переводчиком.\"\nIDS_THANKS_DONORS = \"Благодарим:\"\nIDS_GET_URL_ERROR_LOG_INFO = \"Ошибка при запросе= \"\"<%1%>\"\", код ошибки: <%2%>.\"\nIDS_SHOW_ALL_INFO_TIP = \"Если включено, все сетевые интерфейсы будут отображаться в меню= \"\"Выбрать сетевые подключения\"\" по правой кнопке мыши. Включайте эту опцию только при необходимости.\"\nIDS_CFG_DIR_CHANGED_INFO = \"Вы изменили место сохранения файлов конфигурации и данных. Установка вступит в силу после перезапуска программы. Возможно, вам потребуется вручную перенести файлы конфигурации и данных в новое место.\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<Дважды щёлкните для получения.>\"\nIDS_ERROR1 = \"Ошибка\"\nIDS_ERROR_MESSAGE = \"Сообщение об ошибке:\"\nIDS_CRASH_INFO = \"Сбой программы. Перезапустите её. \\r\\nЕсли проблема регулярно повторяется, отключите функцию мониторинга оборудования в= \"\"Настройки\"\" >= \"\"Общие настройки\"\", а также отключите все плагины в менеджере плагинов. \\r\\nЕсли проблема сохраняется, отправьте файл= \"\"<%1%>\"\" на адрес bugreport-zhongyang219@outlook.com автору, чтобы попытаться найти проблему. И добавьте к тексту сообщения следующее:\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"Благодарности\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Вы действительно хотите сохранить текущую настройку цвета панели задач в= \"\"Пресет <%1%>\"\"?\"\nIDS_SPECIFIC_APP = \"Открыть указанную программу\"\nIDS_EXE_FILTER = \"Программы|*.exe|Пакетные файлы|*.bat||\"\nIDS_PRESET = \"Пресет\"\nIDS_LIGHT_MODE = \"Световой режим\"\nIDS_AUTO_ADAPT_TIP_INFO= \"Эта функция автоматически переключает цветовые настройки при смене тёмных/светлых тем Windows 10. Нажмите кнопку= \"\"Автоадаптация\"\", чтобы настроить схему пресетов для автопереключения.\"\nIDS_WITHOUT_TEMPERATURE= \"Светлая\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"Включён режим 'сквозного' щелчка мышью. Чтобы его выключить, щёлкните правой кнопкой мыши по значку TrafficMonitor в области уведомлений и отключите соответствующий пункт. Нажмите 'Отмена', чтобы больше не показывать.\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"Обнаружена потеря истории трафика. Текущее количество записей: <%1%>, восстановлено записей из резервной копии: <%2%>.\"\nIDS_LEGEND = \"Обозначения\"\nIDS_LICENSE_EXPLAIN = \"Соблюдайте следующий протокол с открытым исходным кодом при использовании исходного кода этого ПО.\"\nIDS_LICENSE = \"Лицензия\"\nIDS_DAY_VIEW = \"День\"\nIDS_MONTH_VIEW = \"Месяц\"\nIDS_QUARTER_VIEW = \"Квартал\"\nIDS_YEAR_VIEW = \"Год\"\nIDS_LINEAR_SCALE = \"Линейная шкала\"\nIDS_LOG_SCALE = \"Логарифмическая шкала\"\nIDS_CPU_TEMPERATURE = \"Температура ЦП\"\nIDS_GPU_TEMPERATURE = \"Температура ГП\"\nIDS_CPU_FREQ = \"Частота ЦП\"\nIDS_HDD_TEMPERATURE = \"Температура диска\"\nIDS_MAINBOARD_TEMPERATURE= \"Температура материнской платы\"\nIDS_GPU_DISP = \"ГП\"\nIDS_HDD_DISP = \"ДСК\"\nIDS_MAINBOARD_DISP = \"МП\"\nIDS_CPU_TEMPERATURE_EXCEED= \"Достигнута предельная температура процессора\"\nIDS_GPU_TEMPERATURE_EXCEED= \"Достигнута предельная температура графического процессора\"\nIDS_HDD_TEMPERATURE_EXCEED= \"Достигнута предельная температура диска\"\nIDS_MBD_TEMPERATURE_EXCEED= \"Достигнута предельная температура материнской платы\"\nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: Красивый и простой в использовании музыкальный проигрыватель для Windows\"\nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: Простой текстовый редактор для Windows\"\nIDS_COLOR = \"Цвет\"\nIDS_COLOR_LABEL = \"Цвет метки\"\nIDS_COLOR_VALUE = \"Цвет значения\"\nIDS_GPU_USAGE = \"Загрузка ГП\"\nIDS_IF_OPER_STATUS_UP = \"Адаптер подключён\"\nIDS_IF_OPER_STATUS_DOWN= \"Адаптер не подключён\"\nIDS_IF_OPER_STATUS_DORMANT= \"Адаптер подключается\"\nIDS_GOTO_GITEE = \"Страница этого проекта на Gitee.\"\nIDS_USAGE_PERCENTAGE = \"Использованный процент\"\nIDS_MEMORY_USED = \"Загрузка памяти\"\nIDS_MEMORY_AVAILABLE = \"Доступно памяти\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \"В системе не установлен .NET Framework 4.5.2 или новее. Функция контроля температуры будет недоступна. Нажмите 'Отмена', чтобы больше не показывать.\"\nIDS_VERSION_UPDATE = \"Обновление версии\"\nIDS_AVREAGE_TEMPERATURE= \"Средняя температура\"\nIDS_HARDWARE_MONITOR_WARNING = \"ВНИМАНИЕ: Вы включаете функцию мониторинга оборудования. Она служит для отображения информации о температуре и использовании графического процессора. Прежде чем включать функцию мониторинга оборудования, внимательно прочтите следующее:\\r\\nTrafficMonitor не является профессиональным ПО для мониторинга аппаратного обеспечения. Мы не гарантируем, что сведения об оборудовании, равно как и точность полученной информации можно получить на любом компьютере.\\r\\nАппаратный мониторинг реализован с помощью сторонней библиотеки LibreHardwareMonitor. После включения аппаратного мониторинга на ряде компьютеров могут возникнуть проблемы, включая следующие (но не ограничиваясь ими):\\r\\n* Повышенная загрузка процессора и памяти\\r\\n* Сбои программы\\r\\n* Сбои компьютера\\r\\nВключайте мониторинг оборудования, только если вы осознаёте эти риски. \\r\\nВы действительно хотите включить мониторинг оборудования?\"\nIDS_HDD_USAGE = \"Загрузка диска\"\nIDS_FILE_NAME = \"Имя файла\"\nIDS_STATUS = \"Состояние\"\nIDS_PLUGIN_LOAD_SUCCEED= \"Загружен успешно\"\nIDS_PLUGIN_MODULE_LOAD_FAILED = \"Подключаемый модуль не загружен, код ошибки: <%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED = \"Не удалось получить доступ к функции, код ошибки: <%1%>\"\nIDS_PLUGIN_INFO = \"О плагине\"\nIDS_NAME = \"Имя\"\nIDS_DESCRIPTION = \"Описание\"\nIDS_FILE_PATH = \"Путь к файлу\"\nIDS_ITEM_NUM = \"Количество отображаемых элементов\"\nIDS_ITEM_NAMES = \"Имена отображаемых элементов\"\nIDS_AUTHOR = \"Автор\"\nIDS_COPYRIGHT = \"Авторские права\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"У этого плагина нет настроек.\"\nIDS_PLUGIN_NAME = \"Имя плагина\"\nIDS_DISABLED = \"Отключено\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Перезапустите программу, чтобы применить это изменение.\"\nIDS_VERSION = \"Версия\"\nIDS_DISP_ITEM_ID = \"ID отображаемого элемента\"\nIDS_PLUGIN_API_VERSION = \"Версия API\"\nIDS_WEEK_VIEW = \"Недельный вид\"\nIDS_WEEK_NUM = \"Неделя <%1%>\"\nIDS_URL = \"URL\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"Слишком старая версия плагина.\"\nIDS_MODIFY_PRESET = \"Изменить пресет\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"Выберите хотя бы один!\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"Когда включена= автоадаптация к тёмной/светлой теме Windows 10 включена, при выборе этой опции смена цвета окна панели задач и цвета фона в соответствии с текущей тёмной/светлой темы автоматически сохраняется в пресет.\"\nIDS_TOTAL_NET_SPEED = \"Общая скорость\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"Отображение графиков использования процессора, памяти, диска, информации о температуре и подключаемых модулей.\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP = Отображение скорости отправки, скачивания и общей.\"\nIDS_REFRESH_CONNECTION_LIST= \"Обновить список подключений\"\nIDS_HARDWARE_MONITOR_INIT_FAILED = \"Не удалось инициализировать функцию аппаратного мониторинга, он будет недоступен.\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Ошибка при получении данных мониторинга оборудования.\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"Автозапуск: Реестр\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"Автозапуск: Планировщик\"\nIDS_PATH = \"Путь\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"Не удалось включить автозапуск.\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Не удалось обновить содержимое окна панели задач, рендеринг Direct2d отключён. В окне настроек эта опция может быть изменена не сразу.\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Ошибка рендеринга Direct2d, рендеринг Direct2d отключён. В окне настроек эта опция может быть изменена не сразу.\"\nIDS_PLUGIN_OPTIONS = \"Настройки плагина\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"Не удалось определить загрузку процессора по счётчику производительности, fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"Основной монитор\"\nIDS_SECONDARY_DISPLAY = \"Вторичный монитор <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"Система была выведена из гибернации, соединение повторно инициализировано. (Переинициализаций: <%1%>)\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"Доступна новая версия: <%1%>\"\nIDS_TRAFFICMONITOR_PLUGIN_NITIFICATION = \"Уведомление плагина TrafficMonitor\"\nIDS_SKIN_FILE_ERROR_INFO = \"Не удалось выполнить синтаксический анализ скин-файла.\"\n\nTXT_OK = \"OK\"\nTXT_CANCEL = \"Отмена\"\nTXT_CLOSE = \"Закрыть\"\nTXT_APPLY = \"Применить\"\n\n; Text used for dialog. (Must be started with \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"О программе TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%> версия <%2%>\"\nTXT_ABOUT_COPYRIGHT = \"Авторские пара (C) 2017-2025 ZhongYang\\nДата компиляции: <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%> Переводчик: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"Использованы сторонние библиотеки:\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"Другие программы автора:\"\nTXT_ABOUT_CONTACT_AUTHOR = \"Связь с автором\"\nTXT_ABOUT_LICENSE = \"Лицензия\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"Благодарности\"\nTXT_ABOUT_DONATE = \"Помочь\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor уже выполняется.\"\nTXT_EXIT_THE_PROGRAM = \"В&ыход из программы\"\nTXT_OPEN_OPTION_SETTINGS = \"&Настройки\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"Показать/скрыть &главное окно\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"Показать/скрыть окно &панели задач\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Настройки автоадаптации\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Пресет, используемый в тёмном режиме:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Пресет, используемый в светлом режиме:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"Автосохранение настроек окна панели задач в пресет\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Настройки текста\"\nTXT_RESTORE_DEFAULT = \"&Все - в стандартные\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Настройки программы\"\nTXT_CHECK_UPDATE = \"Проверять обновления\"\nTXT_CHECK_NOW = \"Провер&ить\"\nTXT_UPDATE_SOURCE = \"Источник:\"\nTXT_AUTO_RUN_CHECK = \"Автозапуск в Windows\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Сброс автозапуска\"\nTXT_LANGUAGE = \"Язык:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"Файлы конфигурации и данных\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Сохранять в AppData\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Сохранять в папке программы\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Открыть папку с &конфигурацией\"\nTXT_NOTIFICATION_MESSAGE = \"Уведомления\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"О превышении дневного трафика\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"О предельной загрузке памяти\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"О предельной температуре ЦП\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"О предельной температуре ГП\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"О предельной температуре диска\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"О предельной температуре материнской платы\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Мониторинг аппаратуры\"\nTXT_CPU = \"ЦП\"\nTXT_GPU = \"ГП\"\nTXT_HARD_DISK = \"Диск\"\nTXT_MAIN_BOARD = \"Материнская плата\"\nTXT_SELECT_HDD_STATIC = \"Диск для мониторинга:\"\nTXT_SELECT_CPU_STATIC = \"Температура ЦП для мониторинга:\"\nTXT_ADVANCED = \"Дополнительные настройки\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Показывать все сетевые подключения\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"Подкл&ючение для отслеживания...\"\nTXT_CPU_ACQUISITION_METHOD = \"Определение загрузки ЦП:\"\nTXT_USE_CPU_TIME_RADIO = \"По времени ЦП\"\nTXT_USE_PDH_RADIO = \"По счётчику производительности\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"Аппаратный мониторинг\"\nTXT_MONITORING_INTERVALS = \"Интервал мониторинга:\"\nTXT_MILLISECONDS = \"мс\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"В ст&андартные\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Плагины...\"\nTXT_DISPLAY = \"Дисплей\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"Показывать значок уведомления\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Год:\"\nTXT_MONTH = \"Месяц:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Статистика трафика\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"Период:\"\nTXT_FIGURE_VIEW_SCALE = \"Шкала:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Значок в области уведомлений\"\nTXT_SELECT_A_ICON = \"Значок:\"\nTXT_PREVIEW = \"Просмотр\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Адаптация к тёмной/светлой теме Windows\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Настройки цвета главного окна\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Скрывать главное окно, если программа в полноэкранном режиме\"\nTXT_COLOR_AND_FONT = \"Цвет и шрифт\"\nTXT_FONT = \"Шрифт:\"\nTXT_FONT_SIZE = \"Размер:\"\nTXT_SET_FONT_BUTTON = \"Вы&брать...\"\nTXT_TEXT_COLOR = \"Цвет текста:\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"&Как в скине\"\nTXT_DISPLAY_TEXT = \"Текст\"\nTXT_SWITCH_UP_DOWN_CHECK = \"Поменять местами отправку и загрузку\"\nTXT_UNIT_SETTINGS = \"Единицы\"\nTXT_UNIT_SELECTION = \"Выбор единиц:\"\nTXT_HIDE_UNIT_CHECK = \"Не показывать единицы\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Краткий вывод скорости\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Не показывать проценты\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Цвета для каждого элемента\"\nTXT_DOUBLE_CLICK_ACTION = \"Двойной щелчок мышью:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Пробел между значением и единицей\"\nTXT_NETSPEED_UNIT = \"Сетевая скорость в:\"\nTXT_UNIT_BYTE_RADIO = \"байтах\"\nTXT_UNIT_BIT_RADIO = \"битах\"\nTXT_SHOW_TOOL_TIP_CHK = \"Подсказки при наведении мыши\"\nTXT_EXE_PATH_STATIC = \"Указанная программа:\"\nTXT_BROWSE_BUTTON = \"О&бзор...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Настройки &текста...\"\nTXT_MEMORY_DISPLAY_MODE = \"Память:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Всегда поверх всех окон\"\nTXT_MOUSE_PENETRATE_CHECK = \"Сквозное нажатие мышью\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Заблокировать место окна\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Выходить за границы экрана\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Сообщение\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Сведения о подключении\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Настройки\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Управление плагинами\"\nTXT_OPTINS_BUTTON = \"Оп&ции...\"\nTXT_PLUGIN_INFO_BUTTON = \"Св&едения...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Разработчику плагинов\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"Загрузить плагины\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Открыть папку плагинов\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Выберите подключение для мониторинга\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Параметры вывода\"\nTXT_MOVE_UP_BUTTON = \"Выше\"\nTXT_MOVE_DOWN_BUTTON = \"Ниже\"\nTXT_RESTORE_DEFAULT_BUTTON = \"В &стандартные\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Автопереключение скинов\"\nTXT_SKIN_IN_DARK_MODE = \"Скин для тёмного режима Windows:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Скин для светлого режима Windows:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Сменить скин\"\nTXT_PREVIEW_GROUP_STATIC = \"Просмотр\"\nTXT_SELECT_A_SKIN = \"Скин\"\nTXT_SKIN_AUTHOR = \"Автор скина:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Как сделать скин\"\nTXT_DOWNLOAD_MORE_SKIN = \"Загрузить ещё скины\"\nTXT_OPEN_SKIN_DIR = \"Открыть папку скина\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Автопереключение скинов при тёмной/светлой теме\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Настройки переключения...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"Цвета в панели задач\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Пресет\"\nTXT_BACKGROUND_COLOR = \"Цвет фона:\"\nTXT_BACKGROUND_TRANSPARENT = \"Прозрачный фон\"\nTXT_AUTO_SET_BACK_COLOR = \"Цвет фона соответствует цвету панели задач\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Адаптация с тёмной/светлой теме Windows\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"&Настройки адаптации...\"\nTXT_DISPLAY_SETTINGS = \"Настройки вывода\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"Настройки &вывода...\"\nTXT_SPEED_SHORT_MODE = \"Краткий вывод скорости сети\"\nTXT_VALUE_RIGHT_ALIGN = \"Выравнивать значения вправо\"\nTXT_NET_SPEED_DATA_WIDTH = \"Ширина данных скорости:\"\nTXT_CHARACTORS = \"симв.\"\nTXT_HORIZONTAL_ARRANGE = \"Горизонтальное расположение\"\nTXT_ITEM_SPACING = \"Между элементами:\"\nTXT_VERTICAL_MARGIN = \"Вертик. поле:\"\nTXT_PIXELS = \"пкс\"\nTXT_TASKBAR_WINDOW = \"Окно панели задач\"\nTXT_TASKBAR_WND_ON_LEFT = \"Окно в левой части панели задач\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"Монитор для вывода окна панели задач:\"\nTXT_WIN11_SETTINGS_BUTTON = \"Установки для Windows 11\"\nTXT_RESOURCE_USAGE_GRAPH = \"График использования ресурсов\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Показывать график использования ресурсов\"\nTXT_SHOW_DASHED_BOX = \"Показывать пунктирную рамку\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Показывать график скорости сети\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"Макс. скорость сети на графике:\"\nTXT_USAGE_GRAPH_COLOR = \"Цвет графика:\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"Как в теме Windows\"\nTXT_GRAPH_DISPLAY_MODE = \"Тип графика:\"\nTXT_BAR_MODE = \"Столбцы\"\nTXT_PLOT_MODE = \"Кривая\"\nTXT_RENDERING_SETTINGS = \"Рендеринг\"\nTXT_RENDERING_SETTINGS_NOTE = \"Рендеринг Direct2D применим, только если включён прозрачный фон и выключена автоподстройка цвета фона по цвету панели задач.\"\nTXT_ENABLE_COLOR_EMOJI = \"Использовать цветные эмодзи\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Установки для Windows 11\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"Окно ближе к значку, а не к краям панели задач\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Вертикальное смещение:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Горизонтальное смещение:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Не перекрывать виджеты (включите, если виджеты в правой части панели задач)\"\nTXT_WIDGETS_WIDTH = \"Ширина виджетов:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Вывод шкалы\"\nTXT_USE_LINEAR_SCALE = \"Линейная\"\nTXT_USE_LOG_SCALE = \"Логарифмическая\"\nTXT_FIRST_DAT_OF_WEEEK = \"1-й день недели\"\nTXT_SUNDAY = \"Воскресенье\"\nTXT_MONDAY = \"Понедельник\"\nTXT_GO_TO_TODAY = \"К сегодня\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"С&копировать текст\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"Выбор сетевы&х подключений\"\nTXT_AUTO_SELECT = \"&Автовыбор\"\nTXT_SELECT_ALL = \"&Выбрать все\"\nTXT_CONNECTION_DETAILS = \"Све&дения о подключении\"\nTXT_ALWAYS_ON_TOP = \"Вс&егда поверх всех окон\"\nTXT_MOUSE_PENETRATE = \"Прозрачны&й режим для мыши\"\nTXT_LOCK_WINDOW_POS = \"За&блокировать положение окна\"\nTXT_SHOW_MORE_INFO = \"Показать &больше сведений\"\nTXT_SHOW_TASKBAR_WINDOW = \"Показать окно пане&ли задач\"\nTXT_SHOW_MAIN_WINDOW = \"Показать &главное окно\"\nTXT_WINDOW_OPACITY = \"Прозра&чность окна\"\nTXT_OTHER_FUNCTIONS = \"&Другие функции\"\nTXT_CHANGE_SKIN = \"Сменить ски&н...\"\nTXT_CHANGE_NOTIFY_ICON = \"Сменить &значок...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Разре&шить выходить за пределы экрана\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"&История трафика\"\nTXT_PLUGIN_MANAGE = \"Управление плагинами...\"\nTXT_OPTIONS = \"&Настройки...\"\nTXT_HELP_MENU = \"&Справка\"\nTXT_HELP = \"&Справка\"\nTXT_FAQ = \"&Вопросы и ответы\"\nTXT_UPDATE_LOG = \"&Журнал обновлений\"\nTXT_ABOUT = \"&О программе...\"\nTXT_CHECK_UPDATE = \"&Проверить наличие новой версии...\"\nTXT_EXIT = \"В&ыход\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"&Параметры вывода...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"Закр&ыть окно панели задач\"\nTXT_TASK_MANAGER = \"&Диспетчер задач\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Сведения...\"\nTXT_PLUGIN_OPTIONS = \"&Опции...\"\nTXT_PLUGIN_DISABLE = \"О&тключено\"\n\n;IDR_DISPLAY_ITEM_CONTEXT_MENU\nTXT_RESTORE_DEFAULT = \"&Восстановить стандартные\"\n"
  },
  {
    "path": "TrafficMonitor/language/Simplified_Chinese.ini",
    "content": "﻿[general]\nBCP_47 = \"zh-CN\"\nDISPLAY_NAME = \"简体中文\"\nTRANSLATOR = \"\"\nTRANSLATOR_URL = \"\"\nDEFAULT_FONT = \"微软雅黑\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"检查更新失败，请检查你的网络连接！\"\nIDS_CHECK_UPDATE_ERROR = \"检查更新失败，从远程更新文件获取到了错误的信息，请联系作者！\"\nIDS_UPDATE_AVLIABLE = \"检测到新版本 V%s，是否前往更新？\"\nIDS_UPDATE_AVLIABLE2 = \"检测到新版本 V%s，更新内容：\\r\\n%s\\r\\n是否前往更新？\"\nIDS_ALREADY_UPDATED = \"当前已经是最新版本。\"\nIDS_AUTORUN_FAILED_NO_KEY= \"无法实现开机自启动，在注册表中找不到相应的键值！\"\nIDS_AUTORUN_FAILED_NO_ACCESS= \"注册表项写入失败，可能该键值没有权限访问！\"\nIDS_AUTORUN_DELETE_FAILED= \"注册表项删除失败，可能该键值没有权限访问！\"\nIDS_AN_INSTANCE_RUNNING= \"已经有一个程序正在运行。\"\nIDS_TRAFFIC_USED_TODAY = \"今日已使用流量\"\nIDS_MEMORY_USAGE = \"内存利用率\"\nIDS_CPU_USAGE = \"CPU利用率\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"向作者发送电子邮件\"\nIDS_GOTO_GITHUB = \"转到此项目在GitHub上的页面\"\nIDS_DONATE_ATHOUR = \"捐助作者\"\nIDS_UPLOAD = \"上传\"\nIDS_DOWNLOAD = \"下载\"\nIDS_MEMORY = \"内存\"\nIDS_UPLOAD_DISP = \"上传\"\nIDS_DOWNLOAD_DISP = \"下载\"\nIDS_MEMORY_DISP = \"内存\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"警告：无法保存设置，无法向文件 “<%file_path%>” 写入数据！以管理员身份运行程序可能会解决问题。\"\nIDS_TRAFFICMONITOR = \"流量监控器\"\nIDS_INSUFFICIENT_BUFFER= \"用于储存连接信息的缓冲区大小不够，已重新初始化连接。(已重新初始化<%cnt%>次)\"\nIDS_CONNECTION_NUM_CHANGED = \"检测到连接数发生变化，已重新获取连接。先前连接数：<%before%>，现在连接数：<%after%>。(已重新初始化<%cnt%>次)\"\nIDS_CONNECTION_NOT_MATCH = \"可能出现了异常，当前选择的连接和期望的连接不一致，已重新获取连接。(已重新初始化<%cnt%>次)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"窗口没有成功嵌入任务栏，可能已被安全软件阻止或者开始菜单未关闭，请尝试重启资源管理器。TrafficMonitor将继续尝试但不再提醒，错误代码：\"\nIDS_MEMORY_UDAGE_EXCEED= \"内存使用率已达到\"\nIDS_NOTIFY = \"通知\"\nIDS_TODAY_TRAFFIC_EXCEED= \"今日已经使用流量已达到\"\nIDS_DATE = \"日期\"\nIDS_TRAFFIC_USED = \"总流量\"\nIDS_FIGURE = \"图表\"\nIDS_DEFAULT_ICON = \"默认图标\"\nIDS_ICON = \"图标\"\nIDS_INTERFACE_NAME = \"接口名\"\nIDS_INTERFACE_DESCRIPTION= \"接口描述\"\nIDS_CONNECTION_TYPE = \"连接类型\"\nIDS_IF_TYPE_OTHER = \"其他类型网络\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"以太网网络\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"令牌环网络\"\nIDS_IF_TYPE_FDDI = \"光纤分布式数据接口 (FDDI) 网络\"\nIDS_IF_TYPE_PPP = \"PPP 网络\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"软件环回网络\"\nIDS_IF_TYPE_ATM = \"ATM 网络\"\nIDS_IF_TYPE_IEEE80211 = \"IEEE 802.11 无线网络\"\nIDS_IF_TYPE_TUNNEL = \"隧道类型封装网络\"\nIDS_IF_TYPE_IEEE1394 = \"IEEE 1394 (Firewire) 高性能串行总线网络\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"对于 WiMax 设备的移动宽带\"\nIDS_IF_TYPE_WWANPP = \"基于 GSM 网络设备的移动宽带\"\nIDS_IF_TYPE_WWANPP2 = \"基于 CDMA 的设备移动宽带\"\nIDS_UNKNOW_CONNECTION = \"未知网络\"\nIDS_SPEED = \"速度\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"适配器物理地址\"\nIDS_IP_ADDRESS = \"IP地址\"\nIDS_SUBNET_MASK = \"子网掩码\"\nIDS_DEFAULT_GATEWAY = \"默认网关\"\nIDS_OPERATIONAL_STATUS = \"连接状态\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"LAN 适配器已被禁用\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"WAN 适配器未连接\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"网络电缆断开连接或无载体\"\nIDS_IF_OPER_STATUS_CONNECTING= \"WAN 适配器正在连接\"\nIDS_IF_OPER_STATUS_CONNECTED= \"WAN 适配器连接到远程对等方\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"LAN 适配器已连接\"\nIDS_UNKNOW_STATUS = \"未知状态\"\nIDS_BYTES_RECEIVED = \"已接收字节数\"\nIDS_BYTES_SENT = \"已发送字节数\"\nIDS_BYTES_RECEIVED_SINCE_START= \"自程序启动以来已接收字节数\"\nIDS_BYTES_SENT_SINCE_START= \"自程序启动以来已发送字节数\"\nIDS_PROGRAM_ELAPSED_TIME= \"程序已运行时间\"\nIDS_HOUR_MINUTE_SECOND = \"%d小时%d分%d秒\"\nIDS_INTERNET_IP_ADDRESS= \"外网IP地址\"\nIDS_GET_FAILED = \"获取失败\"\nIDS_ITEM = \"项目\"\nIDS_VALUE = \"值\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"复制到剪贴板失败！\"\nIDS_SKIN_AUTHOUR = \"皮肤作者：\"\nIDS_SPEED_SHORT_MODE_TIP= \"勾选后，网速显示的小数点位数将减少1位，并且单位不显示“B”\"\nIDS_AUTO = \"自动\"\nIDS_FIXED_AS = \"固定为\"\nIDS_OPEN_CONNECTION_DETIAL= \"打开连接详情\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"打开历史流量统计\"\nIDS_SHOW_HIDE_MORE_INFO= \"显示/隐藏更多信息\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"显示/隐藏CPU和内存利用率\"\nIDS_OPEN_OPTION_SETTINGS= \"打开选项设置\"\nIDS_OPEN_TASK_MANAGER = \"打开任务管理器\"\nIDS_CHANGE_SKIN = \"更换皮肤\"\nIDS_NONE = \"无\"\nIDS_FONT_SIZE_WARNING = \"字体大小必须在 %d~%d 之间！\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING= \"警告：文字颜色和背景色相同！\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING= \"警告：背景色和文字颜色相同！\"\nIDS_FOLLOWING_SYSTEM = \"跟随系统\"\nIDS_LANGUAGE_CHANGE_INFO= \"请重新启动程序使语言设置生效。\"\nIDS_MAIN_WINDOW_SETTINGS= \"主窗口设置\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"任务栏窗口设置\"\nIDS_GENERAL_SETTINGS = \"常规设置\"\nIDS_ACQUIRING = \"正在获取\"\nIDS_LIST_VIEW = \"列表视图\"\nIDS_CALENDAR_VIEW = \"日历视图\"\nIDS_MONDAY = \"一\"\nIDS_TUESDAY = \"二\"\nIDS_WEDNESDAY = \"三\"\nIDS_THURSDAY = \"四\"\nIDS_FRIDAY = \"五\"\nIDS_SATURDAY = \"六\"\nIDS_SUNDAY = \"日\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"当前月总流量:\"\nIDS_TRAFFIC_USED1 = \"已使用流量:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"嵌入任务栏失败，已重试 <%cnt%> 次，GetLastError(): <%error_code%>。\"\nIDS_NO_CONNECTION = \"无连接\"\nIDS_CONTACT_TRANSLATOR = \"联系此翻译者\"\nIDS_THANKS_DONORS = \"感谢以下捐赠者：\"\nIDS_GET_URL_ERROR_LOG_INFO= \"请求“<%1%>”时出现了错误，错误代码：<%2%>。\"\nIDS_SHOW_ALL_INFO_TIP = \"开启此项后，右键菜单中的“选择网络连接”列表中会显示出所有的网络接口。建议仅在需要的时候开启此项。\"\nIDS_CFG_DIR_CHANGED_INFO = \"你更改了配置文件和数据文件的保存位置，重启后生效。你可能需要手动将配置文件和数据文件转移到新的位置。\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<双击此处获取>\"\nIDS_ERROR1 = \"错误\"\nIDS_ERROR_MESSAGE = \"错误信息：\"\nIDS_CRASH_INFO = \"很抱歉，程序出现了错误，请重新启动程序。\\r\\n如果你多次遇到这个问题，请尝试到“选项”>“常规设置”中禁用硬件监控功能，并且到“插件管理”对话框中禁用所有插件。\\r\\n如果问题仍然存在，请将此文件 “<%1%>” 通过电子邮件发送到 bugreport-zhongyang219@outlook.com，以帮助作者确定问题所在。并将以下内容添加到邮件正文中：\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"鸣谢\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY= \"确实要把当前任务栏颜色设置保存到“预设<%1%>”吗？\"\nIDS_SPECIFIC_APP = \"打开指定应用程序\"\nIDS_EXE_FILTER = \"应用程序|*.exe|批处理文件|*.bat||\"\nIDS_PRESET = \"预设\"\nIDS_LIGHT_MODE = \"浅色模式\"\nIDS_AUTO_ADAPT_TIP_INFO= \"此功能可以在Windows10深色/浅色主题改变时自动切换颜色预设方案，点击“自动适应设置”按钮以配置自动切换的预设方案。\"\nIDS_WITHOUT_TEMPERATURE= \"Lite\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"已开启鼠标穿透，如果需要关闭鼠标穿透，请在右下角系统通知区域找到TrafficMonitor的图标，点击鼠标右键，在菜单中关闭鼠标穿透。点击取消不再提示。\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"检测到历史流量数据丢失，当前记录个数：<%1%>，已从备份文件恢复<%2%>条记录。\"\nIDS_LEGEND = \"图例\"\nIDS_LICENSE_EXPLAIN = \"使用本软件的源代码时请遵守以下开源协议。\"\nIDS_LICENSE = \"开源协议\"\nIDS_DAY_VIEW = \"日视图\"\nIDS_MONTH_VIEW = \"月视图\"\nIDS_QUARTER_VIEW = \"季视图\"\nIDS_YEAR_VIEW = \"年视图\"\nIDS_LINEAR_SCALE = \"线性比例\"\nIDS_LOG_SCALE = \"对数比例\"\nIDS_CPU_TEMPERATURE = \"CPU温度\"\nIDS_GPU_TEMPERATURE = \"显卡温度\"\nIDS_CPU_FREQ = \"CPU频率\"\nIDS_HDD_TEMPERATURE = \"硬盘温度\"\nIDS_MAINBOARD_TEMPERATURE= \"主板温度\"\nIDS_GPU_DISP = \"显卡\"\nIDS_HDD_DISP = \"硬盘\"\nIDS_MAINBOARD_DISP = \"主板\"\nIDS_CPU_TEMPERATURE_EXCEED= \"CPU温度已达到\"\nIDS_GPU_TEMPERATURE_EXCEED= \"显卡温度已达到\"\nIDS_HDD_TEMPERATURE_EXCEED= \"硬盘温度已达到\"\nIDS_MBD_TEMPERATURE_EXCEED= \"主板温度已达到\"\nIDS_MUSICPLAYER2_DESCRIPTION= \"MusicPlayer2: 美观易用的 Windows 本地音乐播放器\"\nIDS_SIMPLENOTEPAD_DESCRIPTION= \"SimpleNotePad: 简洁的 Windows 文本编辑器\"\nIDS_COLOR = \"颜色\"\nIDS_COLOR_LABEL = \"标签颜色\"\nIDS_COLOR_VALUE = \"数值颜色\"\nIDS_GPU_USAGE = \"显卡利用率\"\nIDS_IF_OPER_STATUS_UP = \"适配器已连接\"\nIDS_IF_OPER_STATUS_DOWN= \"适配器已断开\"\nIDS_IF_OPER_STATUS_DORMANT= \"适配器正在连接\"\nIDS_GOTO_GITEE = \"转到此项目在Gitee上的页面\"\nIDS_USAGE_PERCENTAGE = \"已使用百分比\"\nIDS_MEMORY_USED = \"内存已使用\"\nIDS_MEMORY_AVAILABLE = \"内存可用\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \"检测到系统中未安装 .Net Framework 4.5.2 或更高版本，温度监控功能将不可用。点击取消不再提示。\"\nIDS_VERSION_UPDATE = \"版本更新\"\nIDS_AVREAGE_TEMPERATURE= \"平均温度\"\nIDS_HARDWARE_MONITOR_WARNING = \"警告：你正在开启硬件监控功能，硬件监控功能可以用于显示温度和显卡利用率信息。在开启硬件监控功能前请仔细阅读以下事项：\\r\\nTrafficMonitor不是专业的硬件监控软件，它不能保证在任何一台电脑上都能够获取到硬件信息，也无法保证获取到的硬件信息的准确性。\\r\\n硬件监控功能是通过第三库LibreHardwareMonitor实现的，开启硬件监控后在某些电脑中可能会出现一些问题，包括但不限于：\\r\\n* CPU和内存占用异常\\r\\n* 程序崩溃\\r\\n* 电脑死机\\r\\n请在知晓以上风险再决定开启硬件监控功能。\\r\\n确实要开启硬件监控功能吗？\"\nIDS_HDD_USAGE = \"硬盘利用率\"\nIDS_FILE_NAME = \"文件名\"\nIDS_STATUS = \"状态\"\nIDS_PLUGIN_LOAD_SUCCEED= \"加载成功\"\nIDS_PLUGIN_MODULE_LOAD_FAILED= \"插件模块加载失败，故障代码：<%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED= \"函数获取失败，故障代码：<%1%>\"\nIDS_PLUGIN_INFO = \"插件详细信息\"\nIDS_NAME = \"名称\"\nIDS_DESCRIPTION = \"描述\"\nIDS_FILE_PATH = \"文件路径\"\nIDS_ITEM_NUM = \"显示项目个数\"\nIDS_ITEM_NAMES = \"显示项目名称\"\nIDS_AUTHOR = \"作者\"\nIDS_COPYRIGHT = \"版权\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"该插件没有提供选项设置。\"\nIDS_PLUGIN_NAME = \"插件名称\"\nIDS_DISABLED = \"已禁用\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO= \"请重新启动程序以应用此更改。\"\nIDS_VERSION = \"版本\"\nIDS_DISP_ITEM_ID = \"显示项目ID\"\nIDS_PLUGIN_API_VERSION = \"接口版本\"\nIDS_WEEK_VIEW = \"周视图\"\nIDS_WEEK_NUM = \"第 <%1%> 周\"\nIDS_URL = \"链接\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"插件版本过低\"\nIDS_MODIFY_PRESET = \"修改预设方案\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"请至少选择一项！\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"在开启了“自动适应Windows10深色/浅色主题”功能时，如果勾选此项，则会在任务栏窗口颜色、背景颜色等设置更改时，根据当前Windows的深色/浅色主题，自动保存到对应的预设中。\"\nIDS_TOTAL_NET_SPEED = \"总网速\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP= \"在CPU/内存硬盘利用率、温度信息、以及插件项目上显示资源占用图\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP= \"在上传、下载和总网速上显示网速指示\"\nIDS_REFRESH_CONNECTION_LIST= \"刷新网络连接列表\"\nIDS_HARDWARE_MONITOR_INIT_FAILED= \"硬件监控功能初始化失败，硬件监控将无法使用！\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR= \"获取硬件监控数据时出现了错误！\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"开机自动运行方式：注册表\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"开机自动运行方式：任务计划\"\nIDS_PATH = \"路径\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"设置开机自动运行失败！\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"更新任务栏窗口内容失败，已禁用Direct2D渲染。注意：设置窗口可能不会立刻更新这一调整。\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Direct2D渲染过程中出现错误，已禁用Direct2D渲染。注意：设置窗口可能不会立刻更新这一调整。\"\nIDS_PLUGIN_OPTIONS = \"插件选项\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"使用性能计数器获取CPU利用率失败，fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"主显示器\"\nIDS_SECONDARY_DISPLAY = \"副显示器 <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"系统已从休眠状态恢复，已重新初始化连接。（已重新初始化<%1%>次）\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"有更新，最新版本：<%1%>\"\nIDS_TRAFFICMONITOR_PLUGIN_NITIFICATION = \"TrafficMonitor 插件通知\"\nIDS_SKIN_FILE_ERROR_INFO = \"皮肤文件解析失败！\"\n\nTXT_OK = \"确定\"\nTXT_CANCEL = \"取消\"\nTXT_CLOSE = \"关闭\"\nTXT_APPLY = \"应用\"\n\n; 用于对话框中的字符串（必须以 TXT_ 开头）\n; CAboutDlg\nTXT_TITLE_ABOUT = \"关于 TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>，<%2%> 版\"\nTXT_ABOUT_COPYRIGHT = \"Copyright (C) 2017-2025 By ZhongYang\\n最后编译日期：<compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%>翻译: <%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"本项目使用的第三方库：\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"作者的其他软件：\"\nTXT_ABOUT_CONTACT_AUTHOR = \"联系作者\"\nTXT_ABOUT_LICENSE = \"开源协议\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"鸣谢\"\nTXT_ABOUT_DONATE = \"捐助\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor已经在运行。\"\nTXT_EXIT_THE_PROGRAM = \"退出程序(&X)\"\nTXT_OPEN_OPTION_SETTINGS = \"打开选项设置(&O)\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"显示/隐藏主窗口(&M)\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"显示/隐藏任务栏窗口(&T)\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"自动适应设置\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"深色Windows模式下使用的颜色预设：\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"浅色Windows模式下使用的颜色预设：\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"自动保存任务栏窗口颜色设置到预设\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"显示文本设置\"\nTXT_RESTORE_DEFAULT = \"全部恢复默认(&D)\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"应用程序设置\"\nTXT_CHECK_UPDATE = \"启动时检查更新\"\nTXT_CHECK_NOW = \"立即检查(&C)\"\nTXT_UPDATE_SOURCE = \"更新源：\"\nTXT_AUTO_RUN_CHECK = \"开机时自动运行\"\nTXT_RESET_AUTO_RUN_BUTTON = \"重新设置开机自动运行\"\nTXT_LANGUAGE = \"语言:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"配置和数据文件\"\nTXT_SAVE_TO_APPDATA_RADIO = \"保存到 Appdata 目录\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"保存到程序所在目录\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"打开配置文件所在目录(&D)\"\nTXT_NOTIFICATION_MESSAGE = \"通知消息\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"今日已使用流量达到\"\nTXT_TODAY_TRAFFIC_BACK = \"时通知\"\nTXT_MEMORY_USAGE_TIP_CHECK = \"内存利用率达到\"\nTXT_MEMORY_USAGE_BACK = \"% 时通知\"\nTXT_CPU_TEMP_TIP_CHECK = \"CPU 温度达到\"\nTXT_CPU_TEMP_BACK = \"°C 时通知\"\nTXT_GPU_TEMP_TIP_CHECK = \"显卡温度达到\"\nTXT_GPU_TEMP_BACK = \"°C 时通知\"\nTXT_HDD_TEMP_TIP_CHECK = \"硬盘温度达到\"\nTXT_HDD_TEMP_BACK = \"°C 时通知\"\nTXT_MBD_TEMP_TIP_CHECK = \"主板温度达到\"\nTXT_MBD_TEMP_BACK = \"°C 时通知\"\nTXT_HARDWARE_MONITORING = \"硬件监控\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"显卡\"\nTXT_HARD_DISK = \"硬盘\"\nTXT_MAIN_BOARD = \"主板\"\nTXT_SELECT_HDD_STATIC = \"选择监控的硬盘：\"\nTXT_SELECT_CPU_STATIC = \"选择监控的CPU温度：\"\nTXT_ADVANCED = \"高级\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"显示所有网络连接\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"选择要监控的网络连接(&S)...\"\nTXT_CPU_ACQUISITION_METHOD = \"CPU使用率获取方式：\"\nTXT_USE_CPU_TIME_RADIO = \"基于CPU使用时间\"\nTXT_USE_PDH_RADIO = \"使用性能计数器\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"使用硬件监控\"\nTXT_MONITORING_INTERVALS = \"监控时间间隔：\"\nTXT_MILLISECONDS = \"毫秒\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"恢复默认(&R)\"\nTXT_PLUGIN_MANAGE_BUTTON = \"插件管理(&P)...\"\nTXT_DISPLAY = \"显示\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"显示通知区图标\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"年：\"\nTXT_MONTH = \"月：\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"历史流量统计\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"统计方式：\"\nTXT_FIGURE_VIEW_SCALE = \"图表显示比例：\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"更换通知区图标\"\nTXT_SELECT_A_ICON = \"选择图标：\"\nTXT_PREVIEW = \"预览\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"根据Windows10深浅色模式自动适应\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"主窗口颜色设置\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"有程序全屏运行时隐藏主窗口\"\nTXT_COLOR_AND_FONT = \"颜色和字体\"\nTXT_FONT = \"字体：\"\nTXT_FONT_SIZE = \"字体大小：\"\nTXT_SET_FONT_BUTTON = \"选择字体(&F)...\"\nTXT_TEXT_COLOR = \"文本颜色：\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"恢复皮肤默认(&R)\"\nTXT_DISPLAY_TEXT = \"显示文本\"\nTXT_SWITCH_UP_DOWN_CHECK = \"交换上传和下载的位置\"\nTXT_UNIT_SETTINGS = \"单位设置\"\nTXT_UNIT_SELECTION = \"单位选择：\"\nTXT_HIDE_UNIT_CHECK = \"不显示网速单位\"\nTXT_SPEED_SHORT_MODE_CHECK = \"网速显示简洁模式\"\nTXT_HIDE_PERCENTAGE_CHECK = \"不显示百分号\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"指定每个项目的颜色\"\nTXT_DOUBLE_CLICK_ACTION = \"双击动作:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"数值和单位用空格分隔\"\nTXT_NETSPEED_UNIT = \"网速单位：\"\nTXT_UNIT_BYTE_RADIO = \"B (字节)\"\nTXT_UNIT_BIT_RADIO = \"b (比特)\"\nTXT_SHOW_TOOL_TIP_CHK = \"显示鼠标提示\"\nTXT_EXE_PATH_STATIC = \"指定应用程序：\"\nTXT_BROWSE_BUTTON = \"浏览(&B)...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"显示文本设置(&T)...\"\nTXT_MEMORY_DISPLAY_MODE = \"内存显示方式：\"\nTXT_ALWAYS_ON_TOP_CHECK = \"总是置顶\"\nTXT_MOUSE_PENETRATE_CHECK = \"鼠标穿透\"\nTXT_LOCK_WINDOW_POS_CHECK = \"锁定窗口位置\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"允许超出屏幕边界\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"消息\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"连接详情\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"选项设置\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"插件管理\"\nTXT_OPTINS_BUTTON = \"选项(&O)...\"\nTXT_PLUGIN_INFO_BUTTON = \"详细信息(&I)...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"插件开发指南\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"更多插件下载\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"打开插件目录\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"选择要监控的网络连接\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"显示设置\"\nTXT_MOVE_UP_BUTTON = \"上移\"\nTXT_MOVE_DOWN_BUTTON = \"下移\"\nTXT_RESTORE_DEFAULT_BUTTON = \"恢复默认\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"皮肤自动切换设置\"\nTXT_SKIN_IN_DARK_MODE = \"深色Windows模式下使用的皮肤：\"\nTXT_SKIN_IN_LIGHT_MODE = \"浅色Windows模式下使用的皮肤：\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"更换皮肤\"\nTXT_PREVIEW_GROUP_STATIC = \"预览\"\nTXT_SELECT_A_SKIN = \"选择皮肤：\"\nTXT_SKIN_AUTHOR = \"皮肤作者\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"皮肤制作教程\"\nTXT_DOWNLOAD_MORE_SKIN = \"更多皮肤下载\"\nTXT_OPEN_SKIN_DIR = \"打开皮肤目录\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"根据Windows深浅色模式自动切换皮肤\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"自动切换设置...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"任务栏窗口颜色设置\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"预设方案(&P)\"\nTXT_BACKGROUND_COLOR = \"背景颜色：\"\nTXT_BACKGROUND_TRANSPARENT = \"背景透明\"\nTXT_AUTO_SET_BACK_COLOR = \"根据任务栏颜色自动设置背景色\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"自动适应Windows10深色/浅色主题\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"自动适应设置(&S)...\"\nTXT_DISPLAY_SETTINGS = \"显示设置\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"显示设置(&O)...\"\nTXT_SPEED_SHORT_MODE = \"网速显示简洁模式\"\nTXT_VALUE_RIGHT_ALIGN = \"数值右对齐\"\nTXT_NET_SPEED_DATA_WIDTH = \"网速数据宽度：\"\nTXT_CHARACTORS = \"字符\"\nTXT_HORIZONTAL_ARRANGE = \"水平排列\"\nTXT_ITEM_SPACING = \"项目间距：\"\nTXT_VERTICAL_MARGIN = \"垂直间距：\"\nTXT_PIXELS = \"像素\"\nTXT_TASKBAR_WINDOW = \"任务栏窗口\"\nTXT_TASKBAR_WND_ON_LEFT = \"任务栏窗口显示在任务栏的左侧\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"显示任务栏窗口的显示器：\"\nTXT_WIN11_SETTINGS_BUTTON = \"Windows11 相关设置\"\nTXT_RESOURCE_USAGE_GRAPH = \"资源占用图\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"显示资源占用图\"\nTXT_SHOW_DASHED_BOX = \"显示虚线框\"\nTXT_SHOW_NET_SPEED_GRAPH = \"显示网速占用图\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"网速占用图显示最大值：\"\nTXT_USAGE_GRAPH_COLOR = \"占用图颜色：\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"跟随 Windows 主题颜色\"\nTXT_GRAPH_DISPLAY_MODE = \"占用图类型：\"\nTXT_BAR_MODE = \"柱状图\"\nTXT_PLOT_MODE = \"横向滚动图\"\nTXT_RENDERING_SETTINGS = \"渲染设置\"\nTXT_RENDERING_SETTINGS_NOTE = \"注意：只有在勾选“背景透明”且不勾选“根据任务栏颜色自动设置背景色”时才会使用Direct2D渲染\"\nTXT_ENABLE_COLOR_EMOJI = \"使用彩色emoji\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Windows11 相关设置\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"任务栏窗口靠近图标而不是靠近任务栏的两侧\"\nTXT_WINDOW_VERTICAL_OFFSET = \"窗口垂直偏移：\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"窗口水平偏移：\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"避免与右侧小组件重叠（如果小组件出现在任务栏的右侧，请勾选此项）\"\nTXT_WIDGETS_WIDTH = \"小组件宽度：\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"显示比例\"\nTXT_USE_LINEAR_SCALE = \"使用线性比例\"\nTXT_USE_LOG_SCALE = \"使用对数比例\"\nTXT_FIRST_DAT_OF_WEEEK = \"一周的第一天\"\nTXT_SUNDAY = \"星期日\"\nTXT_MONDAY = \"星期一\"\nTXT_GO_TO_TODAY = \"转到今天\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"复制文本(&C)\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"选择网络连接(&S)\"\nTXT_AUTO_SELECT = \"自动选择(&A)\"\nTXT_SELECT_ALL = \"选择全部(&S)\"\nTXT_CONNECTION_DETAILS = \"连接详情(&I)\"\nTXT_ALWAYS_ON_TOP = \"总是置顶(&T)\"\nTXT_MOUSE_PENETRATE = \"鼠标穿透(&U)\"\nTXT_LOCK_WINDOW_POS = \"锁定窗口位置(&L)\"\nTXT_SHOW_MORE_INFO = \"显示更多信息(&C)\"\nTXT_SHOW_TASKBAR_WINDOW = \"显示任务栏窗口(&W)\"\nTXT_SHOW_MAIN_WINDOW = \"显示主窗口(&M)\"\nTXT_WINDOW_OPACITY = \"窗口不透明度(&P)\"\nTXT_OTHER_FUNCTIONS = \"其他功能(&E)\"\nTXT_CHANGE_SKIN = \"更换皮肤(&S)...\"\nTXT_CHANGE_NOTIFY_ICON = \"更换通知区图标(&N)...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"允许超出屏幕边界(&B)\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"历史流量统计(&H)\"\nTXT_PLUGIN_MANAGE = \"插件管理(&P)...\"\nTXT_OPTIONS = \"选项(&O)...\"\nTXT_HELP_MENU = \"帮助(&H)\"\nTXT_HELP = \"帮助(&H)\"\nTXT_FAQ = \"常见问题(&F)\"\nTXT_UPDATE_LOG = \"更新日志(&L)\"\nTXT_ABOUT = \"关于(&A)...\"\nTXT_CHECK_UPDATE = \"检查更新(&C)...\"\nTXT_EXIT = \"退出(&X)\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"显示设置(&P)...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"关闭任务栏窗口(&C)\"\nTXT_TASK_MANAGER = \"任务管理器(&T)\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"详细信息(&D)...\"\nTXT_PLUGIN_OPTIONS = \"选项(&O)...\"\nTXT_PLUGIN_DISABLE = \"禁用(&I)\"\n\n;IDR_DISPLAY_ITEM_CONTEXT_MENU\nTXT_RESTORE_DEFAULT = \"恢复默认(&R)\"\n"
  },
  {
    "path": "TrafficMonitor/language/Traditional_Chinese.ini",
    "content": "﻿[general]\nBCP_47 = \"zh-TW\"\nDISPLAY_NAME = \"繁體中文\"\nTRANSLATOR = \"GT Wang\"\nTRANSLATOR_URL = \"http://mkvq.blogspot.com/\"\nDEFAULT_FONT = \"Microsoft JhengHei\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"檢查更新失敗，請檢查你的網路連線！\"\nIDS_CHECK_UPDATE_ERROR = \"檢查更新失敗，從遠端更新檔得到了錯誤的資訊，請聯絡作者！\"\nIDS_UPDATE_AVLIABLE = \"檢測到新版本 V%s，是否前往更新？\"\nIDS_UPDATE_AVLIABLE2 = \"檢測到新版本 V%s，更新內容：\\r\\n%s\\r\\n是否前往更新？\"\nIDS_ALREADY_UPDATED = \"目前已是最新版本。\"\nIDS_AUTORUN_FAILED_NO_KEY= \"無法實現開機自行啟動，在登錄檔中找不到相應的鍵值\"\nIDS_AUTORUN_FAILED_NO_ACCESS= \"登錄機碼寫入失敗，可能該鍵值沒有權限存取\"\nIDS_AUTORUN_DELETE_FAILED= \"登錄機碼刪除失敗，可能該鍵值沒有權限存取\"\nIDS_AN_INSTANCE_RUNNING= \"已有一個程式正在執行。\"\nIDS_TRAFFIC_USED_TODAY = \"今日已使用流量\"\nIDS_MEMORY_USAGE = \"記憶體使用量\"\nIDS_CPU_USAGE = \"CPU使用量\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"傳送電子郵件給作者\"\nIDS_GOTO_GITHUB = \"前往此專案在 GitHub 上的頁面\"\nIDS_DONATE_ATHOUR = \"贊助作者\"\nIDS_UPLOAD = \"上傳\"\nIDS_DOWNLOAD = \"下載\"\nIDS_MEMORY = \"記憶體\"\nIDS_UPLOAD_DISP = \"上傳\"\nIDS_DOWNLOAD_DISP = \"下載\"\nIDS_MEMORY_DISP = \"記憶體\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"警告：無法儲存設定，無法向檔案「<%file_path%>」寫入資料！以管理員身份執行程式可能會解決問題。\"\nIDS_TRAFFICMONITOR = \"流量監視器\"\nIDS_INSUFFICIENT_BUFFER= \"用於儲存連線資訊的緩衝區大小不夠，已重新初始化連線。(已重新初始化<%cnt%>次)\"\nIDS_CONNECTION_NUM_CHANGED = \"檢測到連線數發生變化，已重新取得連線。先前連線數：<%before%>，現在連線數：<%after%>。(已重新初始化<%cnt%>次)\"\nIDS_CONNECTION_NOT_MATCH = \"可能出現了異常，目前選擇的連線和期望的連線不一致，已重新取得連線。(已重新初始化<%cnt%>次)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"視窗沒有成功嵌入工作列，可能已被防毒軟體阻止或者開始功能表未關閉，請嘗試重啟 explorer。TrafficMonitor 會繼續嘗試但不再提醒，錯誤代碼：\"\nIDS_MEMORY_UDAGE_EXCEED= \"記憶體使用率已達到\"\nIDS_NOTIFY = \"通知\"\nIDS_TODAY_TRAFFIC_EXCEED= \"今日已使用流量已達到\"\nIDS_DATE = \"日期\"\nIDS_TRAFFIC_USED = \"總流量\"\nIDS_FIGURE = \"圖表\"\nIDS_DEFAULT_ICON = \"預設圖示\"\nIDS_ICON = \"圖示\"\nIDS_INTERFACE_NAME = \"介面名稱\"\nIDS_INTERFACE_DESCRIPTION= \"介面描述\"\nIDS_CONNECTION_TYPE = \"連線類型\"\nIDS_IF_TYPE_OTHER = \"其他類型的網路\"\nIDS_IF_TYPE_ETHERNET_CSMACD= \"乙太網路\"\nIDS_IF_TYPE_ISO88025_TOKENRING= \"Token Ring 網路\"\nIDS_IF_TYPE_FDDI = \"光纖分散式資料介面 (FDDI) 網路\"\nIDS_IF_TYPE_PPP = \"PPP 網路\"\nIDS_IF_TYPE_SOFTWARE_LOOPBACK= \"軟體 LoopBack 網路\"\nIDS_IF_TYPE_ATM = \"ATM 網路\"\nIDS_IF_TYPE_IEEE80211 = \"IEEE 802.11 無線網路\"\nIDS_IF_TYPE_TUNNEL = \"隧道式封裝網路\"\nIDS_IF_TYPE_IEEE1394 = \"IEEE 1394 (Firewire) 高效能串列匯流排網路\"\nIDS_IF_TYPE_IEEE80216_WMAN= \"對於 WiMax 設備的行動寬頻介面\"\nIDS_IF_TYPE_WWANPP = \"基於 GSM 設備的行動寬頻介面\"\nIDS_IF_TYPE_WWANPP2 = \"基於 CDMA 設備的行動寬頻介面\"\nIDS_UNKNOW_CONNECTION = \"未知網路\"\nIDS_SPEED = \"速度\"\nIDS_ADAPTER_PHYSICAL_ADDRESS= \"實體位址 (MAC)\"\nIDS_IP_ADDRESS = \"IP 位址\"\nIDS_SUBNET_MASK = \"子網路遮罩\"\nIDS_DEFAULT_GATEWAY = \"預設閘道\"\nIDS_OPERATIONAL_STATUS = \"連線狀態\"\nIDS_IF_OPER_STATUS_NON_OPERATIONAL= \"LAN 介面卡已停用\"\nIDS_IF_OPER_STATUS_UNREACHABLE= \"WAN 介面卡未連線\"\nIDS_IF_OPER_STATUS_DISCONNECTED= \"網路連線中斷或無載體\"\nIDS_IF_OPER_STATUS_CONNECTING= \"WAN 介面卡正在連線\"\nIDS_IF_OPER_STATUS_CONNECTED= \"WAN 介面卡連線到遠端對等方\"\nIDS_IF_OPER_STATUS_OPERATIONAL= \"LAN 介面卡已連線\"\nIDS_UNKNOW_STATUS = \"未知狀態\"\nIDS_BYTES_RECEIVED = \"已接收位元組數\"\nIDS_BYTES_SENT = \"已傳送的位元組數\"\nIDS_BYTES_RECEIVED_SINCE_START= \"自程式啟動以來已接收位元組數\"\nIDS_BYTES_SENT_SINCE_START= \"自程式啟動以來已傳送的位元組數\"\nIDS_PROGRAM_ELAPSED_TIME= \"程式已執行時間\"\nIDS_HOUR_MINUTE_SECOND = \"%d小時%d分%d秒\"\nIDS_INTERNET_IP_ADDRESS= \"外網 IP 位址\"\nIDS_GET_FAILED = \"取得失敗\"\nIDS_ITEM = \"項目\"\nIDS_VALUE = \"值\"\nIDS_COPY_TO_CLIPBOARD_FAILED= \"複製到剪貼簿失敗！\"\nIDS_SKIN_AUTHOUR = \"面板作者：\"\nIDS_SPEED_SHORT_MODE_TIP= \"勾選後，網速顯示的小數點位數將減少1位，並且單位不顯示「B」\"\nIDS_AUTO = \"自動\"\nIDS_FIXED_AS = \"固定為\"\nIDS_OPEN_CONNECTION_DETIAL= \"開啟連線詳細資料\"\nIDS_OPEN_HISTORICAL_TRAFFIC= \"開啟歷史流量統計\"\nIDS_SHOW_HIDE_MORE_INFO= \"顯示/隱藏更多資訊\"\nIDS_SHOW_HIDE_CPU_MEMORY= \"顯示/隱藏 CPU 和記憶體使用量\"\nIDS_OPEN_OPTION_SETTINGS= \"開啟設定選項\"\nIDS_OPEN_TASK_MANAGER = \"開啟工作管理員\"\nIDS_CHANGE_SKIN = \"更換面板\"\nIDS_NONE = \"無\"\nIDS_FONT_SIZE_WARNING = \"字型大小必須在 %d~%d 之間！\"\nIDS_SAME_TEXT_BACK_COLOR_WARNING= \"警告：文字色彩和背景色相同！\"\nIDS_SAME_BACK_TEXT_COLOR_WARNING= \"警告：背景色和文字色彩相同！\"\nIDS_FOLLOWING_SYSTEM = \"跟隨系統\"\nIDS_LANGUAGE_CHANGE_INFO= \"請重新啟動程式使語言設定生效。\"\nIDS_MAIN_WINDOW_SETTINGS= \"主視窗設定\"\nIDS_TASKBAR_WINDOW_SETTINGS= \"工作列視窗設定\"\nIDS_GENERAL_SETTINGS = \"一般設定\"\nIDS_ACQUIRING = \"正在取得\"\nIDS_LIST_VIEW = \"清單檢視\"\nIDS_CALENDAR_VIEW = \"日曆檢視\"\nIDS_MONDAY = \"一\"\nIDS_TUESDAY = \"二\"\nIDS_WEDNESDAY = \"三\"\nIDS_THURSDAY = \"四\"\nIDS_FRIDAY = \"五\"\nIDS_SATURDAY = \"六\"\nIDS_SUNDAY = \"日\"\nIDS_CURRENT_MONTH_TOTAL_TRAFFIC= \"目前月總流量:\"\nIDS_TRAFFIC_USED1 = \"已使用流量:\"\nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"嵌入工作列失敗，已重試 <%cnt%> 次，GetLastError(): <%error_code%>。\"\nIDS_NO_CONNECTION = \"無連線\"\nIDS_CONTACT_TRANSLATOR = \"聯絡此譯者\"\nIDS_THANKS_DONORS = \"感謝以下贊助者：\"\nIDS_GET_URL_ERROR_LOG_INFO= \"請求「<%1%>」時出現了錯誤，錯誤程式碼：<%2%>。\"\nIDS_SHOW_ALL_INFO_TIP = \"開啟此項後，右鍵選單中的「選擇網路連線」清單中會顯示出所有的網路介面。建議僅在需要的時候開啟此項。\"\nIDS_CFG_DIR_CHANGED_INFO = \"您修改了設定檔和資料檔的儲存位置，重新啟動後生效。你可能需要手動將設定檔和資料檔轉移到新的位置。\"\nIDS_DOUBLE_CLICK_TO_ACQUIRE= \"<按兩下此處取得>\"\nIDS_ERROR1 = \"錯誤\"\nIDS_ERROR_MESSAGE = \"錯誤資訊：\"\nIDS_CRASH_INFO = \"很抱歉，程式出現了錯誤，請重新啟動程式。\\r\\n如果你多次遇到這個問題，請嘗試到“選項”>“常規設定”中禁用硬體監控功能，並且到“外掛管理”對話方塊中禁用所有外掛。\\r\\n如果問題仍然存在，請將此檔案「<%1%>」透過電子郵件寄送到 bugreport-zhongyang219@outlook.com，以幫助作者確定問題所在。並將以下內容加入到信件內文中：\"\nIDS_TITLE_ACKNOWLEDGEMENT= \"鳴謝\"\nIDS_SAVE_DEFAULT_STYLE_INQUIRY= \"確定要把目前工作列色彩設定儲存到「預設 <%1%> 」嗎？\"\nIDS_SPECIFIC_APP = \"開啟指定應用程式\"\nIDS_EXE_FILTER = \"應用程式|*.exe|批處理檔案|*.bat||\"\nIDS_PRESET = \"預設\"\nIDS_LIGHT_MODE = \"淺色模式\"\nIDS_AUTO_ADAPT_TIP_INFO= \"此功能可以在 Windows10 深色/淺色主題改變時自動切換色彩預設方案，點選「自動適應設定」按鈕以配置用於自動切換的預設方案。\"\nIDS_WITHOUT_TEMPERATURE= \"Lite\"\nIDS_MOUSE_PENETRATE_TIP_INFO = \"已開啟滑鼠穿透，如果需要關閉滑鼠穿透，請在右下角系統通知區域找到 TrafficMonitor 的圖示，點選滑鼠右鍵，在選單中關閉滑鼠穿透。點選「取消」不再提示。\"\nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"偵測到歷史流量資料遺失，目前記錄個數：<%1%>，已從備份檔案恢復<%2%>條記錄。\"\nIDS_LEGEND = \"圖例\"\nIDS_LICENSE_EXPLAIN = \"使用本軟體的原始程式碼時請遵守以下開源協定。\"\nIDS_LICENSE = \"開源協定\"\nIDS_DAY_VIEW = \"日檢視\"\nIDS_MONTH_VIEW = \"月檢視\"\nIDS_QUARTER_VIEW = \"季檢視\"\nIDS_YEAR_VIEW = \"年檢視\"\nIDS_LINEAR_SCALE = \"線性比例\"\nIDS_LOG_SCALE = \"對數比例\"\nIDS_CPU_TEMPERATURE = \"CPU 溫度\"\nIDS_GPU_TEMPERATURE = \"顯示卡溫度\"\nIDS_CPU_FREQ = \"CPU頻率\"\nIDS_HDD_TEMPERATURE = \"硬碟溫度\"\nIDS_MAINBOARD_TEMPERATURE= \"主機板溫度\"\nIDS_GPU_DISP = \"顯示卡\"\nIDS_HDD_DISP = \"硬碟\"\nIDS_MAINBOARD_DISP = \"主機板\"\nIDS_CPU_TEMPERATURE_EXCEED= \"CPU 溫度已達到\"\nIDS_GPU_TEMPERATURE_EXCEED= \"顯示卡溫度已達到\"\nIDS_HDD_TEMPERATURE_EXCEED= \"硬碟溫度已達到\"\nIDS_MBD_TEMPERATURE_EXCEED= \"主機板溫度已達到\"\nIDS_MUSICPLAYER2_DESCRIPTION= \"MusicPlayer2: 美觀易用的 Windows 本機音樂播放器\"\nIDS_SIMPLENOTEPAD_DESCRIPTION= \"SimpleNotePad: 簡潔的 Windows 文字編輯器\"\nIDS_COLOR = \"色彩\"\nIDS_COLOR_LABEL = \"標籤色彩\"\nIDS_COLOR_VALUE = \"數值色彩\"\nIDS_GPU_USAGE = \"顯示卡使用量\"\nIDS_IF_OPER_STATUS_UP = \"介面卡已連線\"\nIDS_IF_OPER_STATUS_DOWN= \"介面卡未連線\"\nIDS_IF_OPER_STATUS_DORMANT= \"介面卡正在連線\"\nIDS_GOTO_GITEE = \"前往此專案在 Gitee 上的頁面\"\nIDS_USAGE_PERCENTAGE = \"已使用百分比\"\nIDS_MEMORY_USED = \"記憶體已使用\"\nIDS_MEMORY_AVAILABLE = \"記憶體可用\"\nIDS_DOTNET_NOT_INSTALLED_TIP = \"偵測到系統中未安裝 .Net Framework 4.5.2 或更高版本，溫度監控功能將不可用。點選取消不再提示。\"\nIDS_VERSION_UPDATE = \"版本更新\"\nIDS_AVREAGE_TEMPERATURE= \"平均溫度\"\nIDS_HARDWARE_MONITOR_WARNING = \"警告：你正在開啟硬體監控功能，硬體監控功能可以用於顯示溫度和顯示卡利用率資訊。在開啟硬體監控功能前請仔細閱讀以下事項：\\r\\nTrafficMonitor 不是專業的硬體監控軟體，它不能保證在任何一臺電腦上都能夠取得到硬體資訊，也無法保證取得到的硬體資訊的準確性。\\r\\n硬體監控功能是透過第三方程式庫 LibreHardwareMonitor 實現的，開啟硬體監控後在某些電腦中可能會出現一些問題，包括但不限於：\\r\\n* CPU 和記憶體佔用異常\\r\\n* 程式當掉\\r\\n* 電腦當機\\r\\n請在知曉以上風險再決定開啟硬體監控功能。\\r\\n確定要開啟硬體監控功能嗎？\"\nIDS_HDD_USAGE = \"硬碟使用量\"\nIDS_FILE_NAME = \"檔名\"\nIDS_STATUS = \"狀態\"\nIDS_PLUGIN_LOAD_SUCCEED= \"載入成功\"\nIDS_PLUGIN_MODULE_LOAD_FAILED= \"外掛模組載入失敗，故障程式碼：<%1%>\"\nIDS_PLUGIN_FUNCTION_GET_FAILED= \"函式獲取失敗，故障程式碼：<%1%>\"\nIDS_PLUGIN_INFO = \"外掛詳細資訊\"\nIDS_NAME = \"名稱\"\nIDS_DESCRIPTION = \"描述\"\nIDS_FILE_PATH = \"檔案路徑\"\nIDS_ITEM_NUM = \"顯示專案個數\"\nIDS_ITEM_NAMES = \"顯示專案名稱\"\nIDS_AUTHOR = \"作者\"\nIDS_COPYRIGHT = \"版權\"\nIDS_PLUGIN_NO_OPTIONS_INFO= \"該外掛沒有提供選項設定。\"\nIDS_PLUGIN_NAME = \"外掛名稱\"\nIDS_DISABLED = \"已停用\"\nIDS_RESTART_TO_APPLY_CHANGE_INFO= \"請重新啟動程式以套用此更改。\"\nIDS_VERSION = \"版本\"\nIDS_DISP_ITEM_ID = \"顯示專案 ID\"\nIDS_PLUGIN_API_VERSION = \"介面版本\"\nIDS_WEEK_VIEW = \"週檢視\"\nIDS_WEEK_NUM = \"第 <%1%> 週\"\nIDS_URL = \"連結\"\nIDS_PLUGIN_VERSION_NOT_SUPPORT= \"外掛版本過低\"\nIDS_MODIFY_PRESET = \"修改預設方案\"\nIDS_SELECT_AT_LEASE_ONE_WARNING= \"請至少選擇一項！\"\nIDS_AUTO_SAVE_TO_PRESET_TIP = \"在開啟了｢自動適應Windows 10 深色/淺色主題｣功能時，如果勾選此項，則會在工作列視窗色彩、背景色彩等設定更改時，根據目前 Windows 的深色/淺色主題，自動儲存到對應的預設中。\"\nIDS_TOTAL_NET_SPEED = \"總網速\"\nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP= \"在CPU/記憶體硬碟利用率、溫度資訊、以及外掛條目上顯示資源佔用圖\"\nIDS_SHOW_NET_SPEED_GRAPH_TIP= \"在上傳、下載和總網速上顯示網速指示\"\nIDS_REFRESH_CONNECTION_LIST= \"重新整理網路連線清單\"\nIDS_HARDWARE_MONITOR_INIT_FAILED= \"硬體監控功能初始化失敗，硬體監控將無法使用！\"\nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR= \"取得硬體監控資料時出現了錯誤！\"\nIDS_AUTO_RUN_METHOD_REGESTRY= \"開機自動執行方式：登錄檔\"\nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE= \"開機自動執行方式：工作排程\"\nIDS_PATH = \"路徑\"\nIDS_SET_AUTO_RUN_FAILED_WARNING= \"設定開機自動執行失敗！\"\nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"更新工作列視窗內容失敗，已禁用Direct2D渲染。 注意：設定視窗可能不會立刻更新這一調整。\"\nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Direct2D渲染過程中出現錯誤，已禁用Direct2D渲染。 注意：設定視窗可能不會立刻更新這一調整。\"\nIDS_PLUGIN_OPTIONS = \"外掛選項\"\nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"使用效能計數器獲取CPU利用率失敗，fullCounterPath=<%1%>\"\nIDS_PRIMARY_DISPLAY = \"主顯示器\"\nIDS_SECONDARY_DISPLAY = \"副顯示器 <%1%>\"\nIDS_RESTORE_FROM_SLEEP_LOG = \"系統已從休眠狀態恢復，已重新初始化連線。（已重新初始化<%1%>次）\"\nIDS_PLUGIN_NEW_VERSION_INFO = \"有更新，最新版本：<%1%>\"\nIDS_TRAFFICMONITOR_PLUGIN_NITIFICATION = \"TrafficMonitor 外掛通知\"\nIDS_SKIN_FILE_ERROR_INFO = \"面板文件解析失敗！\"\n\nTXT_OK = \"確定\"\nTXT_CANCEL = \"取消\"\nTXT_CLOSE = \"關閉\"\nTXT_APPLY = \"套用\"\n\n; Text used for dialog. (Must be started with \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"關於 TrafficMonitor\"\nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>，<%2%> 版\"\nTXT_ABOUT_COPYRIGHT = \"Copyright (C) 2017-2025 By ZhongYang\\n最後編譯日期:  <compile_date>\"\nTXT_ABOUT_TRANSLATOR = \"<%1%>翻譯：<%2%>\"\nTXT_ABOUT_THIRD_PARTY_LIB = \"此項目中使用的第三方程式庫：\"\nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"作者的其他軟體：\"\nTXT_ABOUT_CONTACT_AUTHOR = \"聯絡作者\"\nTXT_ABOUT_LICENSE = \"開源協定\"\nTXT_ABOUT_ACKNOWLEDGEMENT = \"鳴謝\"\nTXT_ABOUT_DONATE = \"贊助\"\n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor 已經在執行。\"\nTXT_EXIT_THE_PROGRAM = \"結束程式(&X)\"\nTXT_OPEN_OPTION_SETTINGS = \"開啟選項設定(&O)\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"顯示/隱藏主視窗(&M)\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"顯示/隱藏工作列視窗(&T)\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"自动适应设置\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"深色 Windows 模式下使用的色彩預設：\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"淺色 Windows 模式下使用的色彩預設：\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"自動儲存工作列視窗色彩設定到預設\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"顯示文字設定\"\nTXT_RESTORE_DEFAULT = \"全部還原預設(&D)\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"應用程式設定\"\nTXT_CHECK_UPDATE = \"啟動時檢查更新\"\nTXT_CHECK_NOW = \"立即檢查(&C)\"\nTXT_UPDATE_SOURCE = \"更新來源：\"\nTXT_AUTO_RUN_CHECK = \"開機時自動執行\"\nTXT_RESET_AUTO_RUN_BUTTON = \"重新設定開機自動執行\"\nTXT_LANGUAGE = \"語言:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"設定檔和資料檔\"\nTXT_SAVE_TO_APPDATA_RADIO = \"儲存到 Appdata 目錄\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"儲存到程式所在目錄\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"開啟設定檔所在目錄(&D)\"\nTXT_NOTIFICATION_MESSAGE = \"通知訊息\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"今日已使用流量達到\"\nTXT_TODAY_TRAFFIC_BACK = \"時通知\"\nTXT_MEMORY_USAGE_TIP_CHECK = \"記憶體使用量達到\"\nTXT_MEMORY_USAGE_BACK = \"% 時通知\"\nTXT_CPU_TEMP_TIP_CHECK = \"CPU 溫度達到\"\nTXT_CPU_TEMP_BACK = \"°C 時通知\"\nTXT_GPU_TEMP_TIP_CHECK = \"顯示卡溫度達到\"\nTXT_GPU_TEMP_BACK = \"°C 時通知\"\nTXT_HDD_TEMP_TIP_CHECK = \"硬碟溫度達到\"\nTXT_HDD_TEMP_BACK = \"°C 時通知\"\nTXT_MBD_TEMP_TIP_CHECK = \"主機板溫度達到\"\nTXT_MBD_TEMP_BACK = \"°C 時通知\"\nTXT_HARDWARE_MONITORING = \"硬體監控\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"顯示卡\"\nTXT_HARD_DISK = \"硬碟\"\nTXT_MAIN_BOARD = \"主機板\"\nTXT_SELECT_HDD_STATIC = \"選擇監控的硬碟：\"\nTXT_SELECT_CPU_STATIC = \"選擇監控的 CPU 溫度：\"\nTXT_ADVANCED = \"進階\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"顯示所有網路連線\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"選擇要監控的網路連線(&S)...\"\nTXT_CPU_ACQUISITION_METHOD = \"CPU 使用量取得方式：\"\nTXT_USE_CPU_TIME_RADIO = \"基於 CPU 使用時間\"\nTXT_USE_PDH_RADIO = \"使用效能計數器\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"使用硬體監控\"\nTXT_MONITORING_INTERVALS = \"監控時間間隔：\"\nTXT_MILLISECONDS = \"毫秒\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"還原預設(&D)\"\nTXT_PLUGIN_MANAGE_BUTTON = \"外掛管理(&P)...\"\nTXT_DISPLAY = \"顯示\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"顯示通知區域圖示\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"年：\"\nTXT_MONTH = \"月：\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"歷史流量統計\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"統計方式：\"\nTXT_FIGURE_VIEW_SCALE = \"圖表顯示比例：\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"更換通知區域圖示\"\nTXT_SELECT_A_ICON = \"選擇圖示：\"\nTXT_PREVIEW = \"預覽\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"根據 Windows 10 深淺色模式自動適應\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"主視窗色彩設定\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"當程式全螢幕執行時隱藏主視窗\"\nTXT_COLOR_AND_FONT = \"色彩和字型\"\nTXT_FONT = \"字型：\"\nTXT_FONT_SIZE = \"字型大小：\"\nTXT_SET_FONT_BUTTON = \"選擇字型(&F)...\"\nTXT_TEXT_COLOR = \"文字色彩：\"\nTXT_RESOTRE_SKIN_DEFAULT_BUTTON = \"恢復面板預設(&R)\"\nTXT_DISPLAY_TEXT = \"顯示文字\"\nTXT_SWITCH_UP_DOWN_CHECK = \"交換上傳和下載的位置\"\nTXT_UNIT_SETTINGS = \"單位設定\"\nTXT_UNIT_SELECTION = \"單位選擇：\"\nTXT_HIDE_UNIT_CHECK = \"不顯示網速單位\"\nTXT_SPEED_SHORT_MODE_CHECK = \"網速顯示簡潔模式\"\nTXT_HIDE_PERCENTAGE_CHECK = \"不顯示 % 符號\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"指定每個項目的色彩\"\nTXT_DOUBLE_CLICK_ACTION = \"按兩下動作:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"數值和單位用空格分隔\"\nTXT_NETSPEED_UNIT = \"網速單位：\"\nTXT_UNIT_BYTE_RADIO = \"B (位元組)\"\nTXT_UNIT_BIT_RADIO = \"b (位元)\"\nTXT_SHOW_TOOL_TIP_CHK = \"顯示游標提示\"\nTXT_EXE_PATH_STATIC = \"指定應用程式：\"\nTXT_BROWSE_BUTTON = \"瀏覽(&B)...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"顯示文字設定(&T)...\"\nTXT_MEMORY_DISPLAY_MODE = \"記憶體顯示方式：\"\nTXT_ALWAYS_ON_TOP_CHECK = \"最上層顯示\"\nTXT_MOUSE_PENETRATE_CHECK = \"游標穿透\"\nTXT_LOCK_WINDOW_POS_CHECK = \"鎖定視窗位置\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"允許超出螢幕邊界\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"消息\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"連線詳細資料\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"設定選項\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"外掛管理\"\nTXT_OPTINS_BUTTON = \"選項(&O)...\"\nTXT_PLUGIN_INFO_BUTTON = \"詳細資訊(&I)...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"外掛開發指南\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"更多外掛下載\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"開啟外掛目錄\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"選擇要監控的網路連線\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"顯示設定\"\nTXT_MOVE_UP_BUTTON = \"上移\"\nTXT_MOVE_DOWN_BUTTON = \"下移\"\nTXT_RESTORE_DEFAULT_BUTTON = \"還原預設\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"面板自動切換設定\"\nTXT_SKIN_IN_DARK_MODE = \"深色Windows模式下使用的面板：\"\nTXT_SKIN_IN_LIGHT_MODE = \"淺色Windows模式下使用的面板：\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"更換面板\"\nTXT_PREVIEW_GROUP_STATIC = \"預覽\"\nTXT_SELECT_A_SKIN = \"選擇面板\"\nTXT_SKIN_AUTHOR = \"面板作者\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"面板製作教學\"\nTXT_DOWNLOAD_MORE_SKIN = \"更多面板下載\"\nTXT_OPEN_SKIN_DIR = \"開啟面板目錄\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"根據Windows深淺色模式自動切換面板\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"自動切換設定...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"工作列視窗色彩設定\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"預設方案(&P)\"\nTXT_BACKGROUND_COLOR = \"背景色彩:\"\nTXT_BACKGROUND_TRANSPARENT = \"背景透明\"\nTXT_AUTO_SET_BACK_COLOR = \"根據工作列色彩自動設定背景色\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"自動適應 Windows 10 深色/淺色主題\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"自動適應設定(&S)...\"\nTXT_DISPLAY_SETTINGS = \"顯示設定\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"顯示設定(&O)...\"\nTXT_SPEED_SHORT_MODE = \"網速顯示簡潔模式\"\nTXT_VALUE_RIGHT_ALIGN = \"數值向右對齊\"\nTXT_NET_SPEED_DATA_WIDTH = \"網速占用位數：\"\nTXT_CHARACTORS = \"字元\"\nTXT_HORIZONTAL_ARRANGE = \"水平排列\"\nTXT_ITEM_SPACING = \"條目間距\"\nTXT_VERTICAL_MARGIN = \"垂直間距：\"\nTXT_PIXELS = \"像素\"\nTXT_TASKBAR_WINDOW = \"工作列視窗\"\nTXT_TASKBAR_WND_ON_LEFT = \"工作列視窗顯示在工作列的左側\"\nTXT_DISPLAY_TO_SHOW_TASKBAR_WND = \"顯示工作列視窗的顯示器：\"\nTXT_WIN11_SETTINGS_BUTTON = \"Windows11 相關設定\"\nTXT_RESOURCE_USAGE_GRAPH = \"資源佔用圖例\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"顯示資源佔用圖例\"\nTXT_SHOW_DASHED_BOX = \"顯示虛線框\"\nTXT_SHOW_NET_SPEED_GRAPH = \"顯示網速佔用圖例\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"網速佔用圖例最大值：\"\nTXT_USAGE_GRAPH_COLOR = \"佔用圖例色彩：\"\nTXT_GRAPH_DISPLAY_MODE = \"佔用圖例型別：\"\nTXT_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK = \"跟隨 Windows 主題顏色\"\nTXT_BAR_MODE = \"柱狀圖\"\nTXT_PLOT_MODE = \"橫向捲動圖\"\nTXT_RENDERING_SETTINGS = \"渲染設定\"\nTXT_RENDERING_SETTINGS_NOTE = \"注意：只有在勾選“背景透明”且不勾選“根據工作列顏色自動設定背景色”時才會使用Direct2D渲染\"\nTXT_ENABLE_COLOR_EMOJI = \"使用彩色emoji\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Windows11 相關設定\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"工作列視窗靠近圖示而不是靠近工作列的兩側\"\nTXT_WINDOW_VERTICAL_OFFSET = \"視窗垂直偏移：\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"視窗水平偏移：\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"避免與右側小工具重疊（如果小工具出現在工作列的右側，請勾選此項）\"\nTXT_WIDGETS_WIDTH = \"小工具宽度：\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"顯示比例\"\nTXT_USE_LINEAR_SCALE = \"使用線性比例\"\nTXT_USE_LOG_SCALE = \"使用對數比例\"\nTXT_FIRST_DAT_OF_WEEEK = \"一週的第一天\"\nTXT_SUNDAY = \"星期日\"\nTXT_MONDAY = \"星期一\"\nTXT_GO_TO_TODAY = \"轉到今天\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"複製文字(&C)\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"選擇網路連線(&S)\"\nTXT_AUTO_SELECT = \"自動選擇(&A)\"\nTXT_SELECT_ALL = \"選擇全部(&S)\"\nTXT_CONNECTION_DETAILS = \"連線細節(&I)\"\nTXT_ALWAYS_ON_TOP = \"最上層顯示(&T)\"\nTXT_MOUSE_PENETRATE = \"游標穿透(&U)\"\nTXT_LOCK_WINDOW_POS = \"鎖定視窗位置(&L)\"\nTXT_SHOW_MORE_INFO = \"顯示更多資訊(&C)\"\nTXT_SHOW_TASKBAR_WINDOW = \"顯示工作列視窗(&W)\"\nTXT_SHOW_MAIN_WINDOW = \"顯示主視窗(&M)\"\nTXT_WINDOW_OPACITY = \"視窗不透明度(&P)\"\nTXT_OTHER_FUNCTIONS = \"其他功能(&E)\"\nTXT_CHANGE_SKIN = \"更換面板(&S)...\"\nTXT_CHANGE_NOTIFY_ICON = \"更換通知區域圖示(&N)...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"允許超出螢幕邊界(&B)\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"歷史流量統計(&H)\"\nTXT_PLUGIN_MANAGE = \"外掛管理(&P)...\"\nTXT_OPTIONS = \"選項(&O)...\"\nTXT_HELP_MENU = \"說明(&H)\"\nTXT_HELP = \"說明(&H)\"\nTXT_FAQ = \"常見問題(&F)\"\nTXT_UPDATE_LOG = \"更新記錄(&L)\"\nTXT_ABOUT = \"關於(&A)...\"\nTXT_CHECK_UPDATE = \"檢查更新(&C)...\"\nTXT_EXIT = \"結束(&X)\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"顯示設定(&P)...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"關閉工作列視窗(&C)\"\nTXT_TASK_MANAGER = \"工作管理員(&T)\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"詳細資訊(&D)...\"\nTXT_PLUGIN_OPTIONS = \"選項(&O)...\"\nTXT_PLUGIN_DISABLE = \"停用(&I)\"\n\n;IDR_DISPLAY_ITEM_CONTEXT_MENU\nTXT_RESTORE_DEFAULT = \"還原預設(&R)\"\n"
  },
  {
    "path": "TrafficMonitor/language/Turkish.ini",
    "content": "﻿[general]\nBCP_47 = \"tr-TR\"\nDISPLAY_NAME = \"Turkish\"\nTRANSLATOR = \"hberkayaktas\"\nTRANSLATOR_URL = \"https://hberkayaktas.github.io/\"\nDEFAULT_FONT = \"Segoe UI\"\n\n[text]\n; String Table\nIDS_CHECK_UPDATE_FAILD = \"Güncelleme denetleme başarısız oldu, lütfen ağ bağlantınızı kontrol edin!\"\nIDS_CHECK_UPDATE_ERROR = \"Güncelleme denetleme başarısız oldu ve uzaktaki güncelleme dosyasından yanlış bilgi alındı, lütfen yazar ile iletişime geçin!\"\nIDS_UPDATE_AVLIABLE = \"Yeni sürüm V%s tespit edildi, güncelleme yapmak istiyor musunuz?\"\nIDS_UPDATE_AVLIABLE2 = \"Yeni sürüm V%s tespit edildi, güncelleme içeriği: \\r\\n%s\\r\\nGüncellemek istiyor musunuz?\"\nIDS_ALREADY_UPDATED = \"Zaten en son sürüme güncellendi.\"\nIDS_AUTORUN_FAILED_NO_KEY = \"Windows başlangıcında otomatik çalıştırma yapılamıyor, kayıt defterinde ilgili anahtar bulunamadı.\"\nIDS_AUTORUN_FAILED_NO_ACCESS = \"Kayıt defteri anahtarına yazma başarısız oldu, anahtara erişim izni olmayabilir!\"\nIDS_AUTORUN_DELETE_FAILED = \"Kayıt defteri anahtarını silme başarısız oldu, anahtara erişim izni olmayabilir!\"\nIDS_AN_INSTANCE_RUNNING= \"Zaten çalışan bir örneği var.\"\nIDS_TRAFFIC_USED_TODAY = \"Bugün kullanılan trafik\"\nIDS_MEMORY_USAGE = \"Bellek kullanımı\"\nIDS_CPU_USAGE = \"CPU kullanımı\"\nIDS_SEND_EMAIL_TO_ATHOUR= \"Yazara e-posta gönder.\"\nIDS_GOTO_GITHUB = \"Bu projenin GitHub sayfasına git.\"\nIDS_DONATE_ATHOUR = \"Yazara bağış yap\"\nIDS_UPLOAD = \"Yükleme\"\nIDS_DOWNLOAD = \"İndirme\"\nIDS_MEMORY = \"Bellek\"\nIDS_UPLOAD_DISP = \"UP\"\nIDS_DOWNLOAD_DISP = \"DN\"\nIDS_MEMORY_DISP = \"MEM\"\nIDS_CONNOT_SAVE_CONFIG_WARNING = \"Uyarı: Ayarlar kaydedilemedi, \"\"<%file_path%>\"\" dosyasına veri yazılamıyor! Bu programı yönetici olarak çalıştırmak sorunu çözebilir.\"\nIDS_TRAFFICMONITOR = \"TrafficMonitor\"\nIDS_INSUFFICIENT_BUFFER= \"Bağlantı bilgilerini depolamak için kullanılan tampon belleğin boyutu yeterli değil, bağlantı yeniden başlatıldı. (<%cnt%> kez yeniden başlatıldı)\"\nIDS_CONNECTION_NUM_CHANGED = \"Bağlantı sayısında değişiklik tespit edildi. Bağlantı yeniden alındı. Önceki bağlantılar: <%before%>, şu anki bağlantılar: <%after%>. (<%cnt%> kez yeniden başlatıldı)\"\nIDS_CONNECTION_NOT_MATCH = \"Bir hata meydana gelmiş olabilir, seçili bağlantı beklenen bağlantıyla uyuşmuyor. Bağlantı yeniden alındı. (<%cnt%> kez yeniden başlatıldı)\"\nIDS_CONNOT_INSERT_TO_TASKBAR = \"Pencere görev çubuğuna başarıyla yerleştirilemedi, güvenlik yazılımı tarafından engellenmiş olabilir veya başlangıç menüsü kapatılmamış olabilir, lütfen Explorer'ı yeniden başlatmayı deneyin. TrafficMonitor denemeye devam edecek ancak bildirim yapmayacak, hata kodu:\"\nIDS_MEMORY_UDAGE_EXCEED= \"Bellek kullanımı sınırına ulaşıldı\"\nIDS_NOTIFY = \"Bildirim\"\nIDS_TODAY_TRAFFIC_EXCEED = \"Bugün kullanılan trafik sınırına ulaşıldı\"\nIDS_DATE = \"Tarih\"\nIDS_TRAFFIC_USED = \"Toplam trafik\"\nIDS_FIGURE = \"Grafik\"\nIDS_DEFAULT_ICON = \"Varsayılan Simge\"\nIDS_ICON = \"Simge\"\nIDS_INTERFACE_NAME = \"Arayüz adı\"\nIDS_INTERFACE_DESCRIPTION= \"Arayüz açıklaması\"\nIDS_CONNECTION_TYPE = \"Bağlantı türü\"\nIDS_IF_TYPE_OTHER = \"Diğer ağ türü\"  \nIDS_IF_TYPE_ETHERNET_CSMACD = \"Ethernet ağı\"  \nIDS_IF_TYPE_ISO88025_TOKENRING = \"Token ring ağı\"  \nIDS_IF_TYPE_FDDI = \"Fiber Dağıtılmış Veri Arabirimi (FDDI) ağı\"  \nIDS_IF_TYPE_PPP = \"PPP ağı\"  \nIDS_IF_TYPE_SOFTWARE_LOOPBACK = \"Yazılımsal loopback ağı\"  \nIDS_IF_TYPE_ATM = \"ATM ağı\"  \nIDS_IF_TYPE_IEEE80211 = \"IEEE 802.11 kablosuz ağı\"  \nIDS_IF_TYPE_TUNNEL = \"Tünel tipi kapsülleme ağı\"  \nIDS_IF_TYPE_IEEE1394 = \"IEEE 1394 (Firewire) yüksek performanslı seri veri yolu ağı\"  \nIDS_IF_TYPE_IEEE80216_WMAN = \"WiMax cihazları için mobil geniş bant arayüzü\"  \nIDS_IF_TYPE_WWANPP = \"GSM tabanlı cihazlar için mobil geniş bant arayüzü\"  \nIDS_IF_TYPE_WWANPP2 = \"CDMA tabanlı cihazlar için mobil geniş bant arayüzü\"  \nIDS_UNKNOW_CONNECTION = \"Bilinmeyen ağ\"  \nIDS_SPEED = \"Hız\"  \nIDS_ADAPTER_PHYSICAL_ADDRESS = \"Adaptör fiziksel adresi\"  \nIDS_IP_ADDRESS = \"IP adresi\"  \nIDS_SUBNET_MASK = \"Alt ağ maskesi\"  \nIDS_DEFAULT_GATEWAY = \"Varsayılan ağ geçidi\"  \nIDS_OPERATIONAL_STATUS = \"Bağlantı durumu\"  \nIDS_IF_OPER_STATUS_NON_OPERATIONAL = \"LAN adaptörü devre dışı bırakıldı\"  \nIDS_IF_OPER_STATUS_UNREACHABLE = \"WAN adaptörü bağlı değil\"  \nIDS_IF_OPER_STATUS_DISCONNECTED = \"Ağ kablosu bağlantısı kesildi veya taşıyıcı yok\"  \nIDS_IF_OPER_STATUS_CONNECTING = \"WAN adaptörü bağlantı kuruluyor\"  \nIDS_IF_OPER_STATUS_CONNECTED = \"WAN adaptörü uzak uç noktayla bağlantılı\"  \nIDS_IF_OPER_STATUS_OPERATIONAL = \"LAN adaptörü bağlı\"  \nIDS_UNKNOW_STATUS = \"Bilinmeyen durum\"  \nIDS_BYTES_RECEIVED = \"Alınan bayt\"  \nIDS_BYTES_SENT = \"Gönderilen bayt\"  \nIDS_BYTES_RECEIVED_SINCE_START = \"Program başladığından beri alınan bayt\"  \nIDS_BYTES_SENT_SINCE_START = \"Program başladığından beri gönderilen bayt\"  \nIDS_PROGRAM_ELAPSED_TIME = \"Program çalışma süresi\"  \nIDS_HOUR_MINUTE_SECOND = \"%d saat, %d dakika, %d saniye\"  \nIDS_INTERNET_IP_ADDRESS = \"İnternet IP adresi\"  \nIDS_GET_FAILED = \"Alma başarısız oldu\"  \nIDS_ITEM = \"Öğe\"  \nIDS_VALUE = \"Değer\"  \nIDS_COPY_TO_CLIPBOARD_FAILED = \"Panoya kopyalama başarısız!\"  \nIDS_SKIN_AUTHOUR = \"Tema yazarı:\"  \nIDS_SPEED_SHORT_MODE_TIP = \"İşaretlendiğinde, ağ hız göstergesi 1 ondalık basamağa düşürülür ve birim olarak \"\"B\"\" gösterilmez.\"  \nIDS_AUTO = \"Otomatik\"  \nIDS_FIXED_AS = \"Sabit olarak\"  \nIDS_OPEN_CONNECTION_DETIAL = \"Bağlantı ayrıntılarını aç\"  \nIDS_OPEN_HISTORICAL_TRAFFIC = \"Geçmiş trafik istatistiklerini aç\"  \nIDS_SHOW_HIDE_MORE_INFO = \"Daha fazla bilgiyi göster/gizle\"  \nIDS_SHOW_HIDE_CPU_MEMORY = \"CPU ve bellek kullanımını göster/gizle\"  \nIDS_OPEN_OPTION_SETTINGS = \"Seçenek ayarlarını aç\"  \nIDS_OPEN_TASK_MANAGER = \"Görev yöneticisini aç\"  \nIDS_CHANGE_SKIN = \"Temayı değiştir\"  \nIDS_NONE = \"Yok\"  \nIDS_FONT_SIZE_WARNING = \"Yazı tipi boyutu %d ile %d arasında olmalıdır!\"  \nIDS_SAME_TEXT_BACK_COLOR_WARNING = \"Uyarı: Metin rengi, arka plan rengi ile aynı!\"  \nIDS_SAME_BACK_TEXT_COLOR_WARNING = \"Uyarı: Arka plan rengi, metin rengi ile aynı!\"  \nIDS_FOLLOWING_SYSTEM = \"Sistemi takip et\"  \nIDS_LANGUAGE_CHANGE_INFO = \"Dil ayarını uygulamak için lütfen uygulamayı yeniden başlatın.\"  \nIDS_MAIN_WINDOW_SETTINGS = \"Ana Pencere Ayarları\"  \nIDS_TASKBAR_WINDOW_SETTINGS = \"Görev Çubuğu Pencere Ayarları\"  \nIDS_GENERAL_SETTINGS = \"Genel Ayarlar\"  \nIDS_ACQUIRING = \"Alınıyor\"  \nIDS_LIST_VIEW = \"Liste Görünümü\"  \nIDS_CALENDAR_VIEW = \"Takvim Görünümü\"  \nIDS_MONDAY = \"Pzt\"  \nIDS_TUESDAY = \"Sal\"  \nIDS_WEDNESDAY = \"Çar\"  \nIDS_THURSDAY = \"Per\"  \nIDS_FRIDAY = \"Cum\"  \nIDS_SATURDAY = \"Cmt\"  \nIDS_SUNDAY = \"Paz\"  \nIDS_CURRENT_MONTH_TOTAL_TRAFFIC = \"Bu ayın toplam trafiği:\"  \nIDS_TRAFFIC_USED1 = \"Kullanılan trafik:\"  \nIDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG = \"Görev çubuğuna ekleme başarısız oldu, <%cnt%> kez yeniden denendi. GetLastError(): <%error_code%>.\"  \nIDS_NO_CONNECTION = \"Bağlantı Yok\"  \nIDS_CONTACT_TRANSLATOR = \"Bu çevirmenle iletişime geçin.\"  \nIDS_THANKS_DONORS = \"Aşağıdaki bağışçılara teşekkürler:\"  \nIDS_GET_URL_ERROR_LOG_INFO = \"İstek yapılırken bir hata oluştu= \"\"<%1%>\"\", hata kodu: <%2%>.\"  \nIDS_SHOW_ALL_INFO_TIP = \"Bu öğe işaretlendiğinde, tüm ağ arabirimleri sağ tıklama menüsündeki= \"\"Ağ Bağlantılarını Seç\"\" listesinde görüntülenecektir. Bu öğeyi yalnızca gerektiğinde işaretlemeniz önerilir.\"  \nIDS_CFG_DIR_CHANGED_INFO = \"Yapılandırma ve veri dosyalarının kaydedildiği konumu değiştirdiniz. Değişiklik, program yeniden başlatıldığında geçerli olacaktır. Yapılandırma ve veri dosyalarını yeni konuma manuel olarak aktarmanız gerekebilir.\"  \nIDS_DOUBLE_CLICK_TO_ACQUIRE = \"<Almak için buraya çift tıklayın.>\"  \nIDS_ERROR1 = \"Hata\"  \nIDS_ERROR_MESSAGE = \"Hata Mesajı:\"  \nIDS_CRASH_INFO = \"Üzgünüz, program çöktü. Lütfen programı yeniden başlatın. \\r\\nBu sorunu birçok kez yaşarsanız, \"\"Seçenekler\"\" >= \"\"Genel Ayarlar\"\" bölümünde donanım izleme işlevini devre dışı bırakmayı ve \"\"Eklenti Yöneticisi\"\" penceresinde tüm eklentileri kapatmayı deneyin. \\r\\nSorun devam ederse, lütfen bu dosyayı= \"\"<%1%>\"\" adresine e-posta ile gönderin: bugreport-zhongyang219@outlook.com. Mesaj gövdesine aşağıdakileri ekleyin:\"  \nIDS_TITLE_ACKNOWLEDGEMENT = \"Teşekkür\"  \nIDS_SAVE_DEFAULT_STYLE_INQUIRY = \"Mevcut görev çubuğu renk ayarını= \"\"Ön Ayar <%1%>\"\" olarak kaydetmek istediğinizden emin misiniz?\"  \nIDS_SPECIFIC_APP = \"Belirtilen uygulamayı aç\"  \nIDS_EXE_FILTER = \"Uygulamalar|*.exe|Toplu iş dosyaları|*.bat||\"  \nIDS_PRESET = \"Ön Ayar\"  \nIDS_LIGHT_MODE = \"Açık Mod\"  \nIDS_AUTO_ADAPT_TIP_INFO = \"Bu işlev, Windows 10 koyu/açık temaları değiştiğinde renk ön ayarlarını otomatik olarak değiştirecektir. Otomatik geçiş için ön ayar şemasını yapılandırmak için= \"\"Otomatik Uyum Ayarları\"\" düğmesine tıklayın.\"  \nIDS_WITHOUT_TEMPERATURE = \"Hafif\"  \nIDS_MOUSE_PENETRATE_TIP_INFO = \"Fare geçişi etkinleştirildi. Fare geçişini kapatmak için sistem bildirim alanındaki TrafficMonitor simgesini bulun, sağ tıklayın ve menüden fare geçişini kapatın. Bu uyarıyı bir daha göstermemek için İptal'e tıklayın.\"  \nIDS_HISTORY_TRAFFIC_LOST_ERROR_LOG = \"Tarihsel trafik verisi kaybı tespit edildi. Mevcut kayıt sayısı: <%1%>, <%2%> kayıt yedek dosyadan geri yüklendi.\"  \nIDS_LEGEND = \"Açıklamalar\"  \nIDS_LICENSE_EXPLAIN = \"Bu yazılımın kaynak kodunu kullanırken aşağıdaki açık kaynak protokolüne uymanız gerekmektedir.\"  \nIDS_LICENSE = \"Lisans\"  \nIDS_DAY_VIEW = \"Günlük Görünüm\"  \nIDS_MONTH_VIEW = \"Aylık Görünüm\"  \nIDS_QUARTER_VIEW = \"Çeyrek Görünüm\"  \nIDS_YEAR_VIEW = \"Yıllık Görünüm\"  \nIDS_LINEAR_SCALE = \"Doğrusal Ölçek\"  \nIDS_LOG_SCALE = \"Logaritmik Ölçek\"  \nIDS_CPU_TEMPERATURE = \"CPU Sıcaklığı\"  \nIDS_GPU_TEMPERATURE = \"GPU Sıcaklığı\"  \nIDS_CPU_FREQ = \"CPU Frekansı\"  \nIDS_HDD_TEMPERATURE = \"Sabit Disk Sıcaklığı\"  \nIDS_MAINBOARD_TEMPERATURE = \"Anakart Sıcaklığı\"  \nIDS_GPU_DISP = \"GPU\"\nIDS_HDD_DISP = \"HDD\"\nIDS_MAINBOARD_DISP = \"MBD\"\nIDS_CPU_TEMPERATURE_EXCEED = \"CPU sıcaklığına ulaşıldı\"  \nIDS_GPU_TEMPERATURE_EXCEED = \"GPU sıcaklığına ulaşıldı\"  \nIDS_HDD_TEMPERATURE_EXCEED = \"Sabit disk sıcaklığına ulaşıldı\"  \nIDS_MBD_TEMPERATURE_EXCEED = \"Anakart sıcaklığına ulaşıldı\"  \nIDS_MUSICPLAYER2_DESCRIPTION = \"MusicPlayer2: Windows için güzel ve kullanımı kolay bir yerel müzik çalar\"  \nIDS_SIMPLENOTEPAD_DESCRIPTION = \"SimpleNotePad: Windows için basit bir metin düzenleyici\"  \nIDS_COLOR = \"Renk\"  \nIDS_COLOR_LABEL = \"Etiket rengi\"  \nIDS_COLOR_VALUE = \"Değer rengi\"  \nIDS_GPU_USAGE = \"GPU kullanımı\"  \nIDS_IF_OPER_STATUS_UP = \"Adaptör bağlı\"  \nIDS_IF_OPER_STATUS_DOWN = \"Adaptör bağlı değil\"  \nIDS_IF_OPER_STATUS_DORMANT = \"Adaptör bağlanıyor\"  \nIDS_GOTO_GITEE = \"Bu proje için Gitee sayfasına git.\"  \nIDS_USAGE_PERCENTAGE = \"Kullanım yüzdesi\"  \nIDS_MEMORY_USED = \"Kullanılan bellek\"  \nIDS_MEMORY_AVAILABLE = \"Kullanılabilir bellek\"  \nIDS_DOTNET_NOT_INSTALLED_TIP = \".Net Framework v4.5.2 veya daha yüksek sürümü sistemde yüklü değil. Sıcaklık izleme fonksiyonu kullanılamayacak. Artık bu uyarıyı görmek istemiyorsanız, İptal'e tıklayın.\"  \nIDS_VERSION_UPDATE = \"Yeni sürüm güncellemesi\"  \nIDS_AVREAGE_TEMPERATURE = \"Ortalama Sıcaklık\"  \nIDS_HARDWARE_MONITOR_WARNING = \"Uyarı: Donanım izleme fonksiyonunu açıyorsunuz. Donanım izleme fonksiyonu, sıcaklık ve GPU kullanımı bilgilerini görüntülemek için kullanılabilir. Donanım izleme fonksiyonunu açmadan önce aşağıdakileri dikkatlice okuyun:\\r\\nTrafficMonitor, profesyonel bir donanım izleme yazılımı değildir. Donanım bilgilerini her bilgisayarda alabileceğini garanti edemez ve alınan donanım bilgilerinin doğruluğunu garanti edemez.\\r\\nDonanım izleme fonksiyonu, üçüncü taraf kütüphane LibreHardwareMonitor tarafından uygulanmaktadır. Donanım izleme açıldığında, bazı bilgisayarlarda bazı sorunlar oluşabilir, bunlar arasında ancak bunlarla sınırlı olmamak üzere:\\r\\n* Anormal CPU ve bellek kullanımı\\r\\n* Program çökmesi\\r\\n* Bilgisayarın çökmesi\\r\\nYukarıdaki riskleri fark ettikten sonra donanım izleme fonksiyonunu açmaya karar verin.\\r\\nDonanım izleme fonksiyonunu gerçekten açmak istiyor musunuz?\"  \nIDS_HDD_USAGE = \"Sabit Disk kullanımı\"  \nIDS_FILE_NAME = \"Dosya adı\"  \nIDS_STATUS = \"Durum\"  \nIDS_PLUGIN_LOAD_SUCCEED = \"Yükleme başarılı\"  \nIDS_PLUGIN_MODULE_LOAD_FAILED = \"Eklenti modülü yükleme başarısız, hata kodu: <%1%>\"  \nIDS_PLUGIN_FUNCTION_GET_FAILED = \"Fonksiyon edinme başarısız, hata kodu: <%1%>\"  \nIDS_PLUGIN_INFO = \"Eklenti bilgileri\"  \nIDS_NAME = \"Ad\"  \nIDS_DESCRIPTION = \"Açıklama\"  \nIDS_FILE_PATH = \"Dosya yolu\"  \nIDS_ITEM_NUM = \"Gösterilen öğe sayısı\"  \nIDS_ITEM_NAMES = \"Gösterilen öğe adları\"  \nIDS_AUTHOR = \"Yazar\"  \nIDS_COPYRIGHT = \"Telif hakkı\"  \nIDS_PLUGIN_NO_OPTIONS_INFO = \"Eklenti seçenek ayarları sunmamaktadır.\"  \nIDS_PLUGIN_NAME = \"Eklenti adı\"  \nIDS_DISABLED = \"Devre dışı\"  \nIDS_RESTART_TO_APPLY_CHANGE_INFO = \"Bu değişikliği uygulamak için programı yeniden başlatmanız gerekiyor.\"  \nIDS_VERSION = \"Sürüm\"  \nIDS_DISP_ITEM_ID = \"Gösterilen öğe kimliği\"  \nIDS_PLUGIN_API_VERSION = \"API sürümü\"  \nIDS_WEEK_VIEW = \"Haftalık görünüm\"  \nIDS_WEEK_NUM = \"Hafta <%1%>\"  \nIDS_URL = \"URL\"  \nIDS_PLUGIN_VERSION_NOT_SUPPORT = \"Eklenti sürümü çok düşük.\"  \nIDS_MODIFY_PRESET = \"Ön ayarı değiştir\"  \nIDS_SELECT_AT_LEASE_ONE_WARNING = \"Lütfen en az birini seçin!\"  \nIDS_AUTO_SAVE_TO_PRESET_TIP = \"Windows 10 karanlık/aydınlık tema fonksiyonu etkinleştirildiğinde, bu seçenek işaretli ise, görev çubuğu pencere rengi ve arka plan rengi ayarları değiştirildiğinde, mevcut Windows karanlık/aydınlık temaya göre otomatik olarak ilgili ön ayara kaydedilecektir.\"  \nIDS_TOTAL_NET_SPEED = \"Toplam hız\"  \nIDS_SHOW_RESOURCE_USAGE_GRAPH_TIP = \"CPU/bellek sabit disk kullanım grafikleri, sıcaklık bilgileri ve eklenti öğeleri üzerine kaynak kullanımı grafiklerini görüntüle.\"  \nIDS_SHOW_NET_SPEED_GRAPH_TIP = \"Yükleme, indirme ve toplam ağ hızı göstergelerini görüntüle.\"  \nIDS_REFRESH_CONNECTION_LIST = \"Bağlantı listesini yenile\"  \nIDS_HARDWARE_MONITOR_INIT_FAILED = \"Donanım izleme fonksiyonu başlatılamadı, donanım izleme kullanılamayacak!\"  \nIDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR = \"Donanım izleme verisi alındı hatası!\"  \nIDS_AUTO_RUN_METHOD_REGESTRY = \"Otomatik başlatma modu: Kayıt defteri\"  \nIDS_AUTO_RUN_METHOD_TASK_SCHEDULE = \"Otomatik başlatma modu: Görev planı\"  \nIDS_PATH = \"Yol\"  \nIDS_SET_AUTO_RUN_FAILED_WARNING = \"Başlangıçta otomatik çalıştırma ayarlanamadı!\"  \nIDS_UPDATE_TASKBARDLG_FAILED_TIP = \"Görev çubuğu penceresinin içeriği güncellenemedi, direct2d render işlemi devre dışı bırakıldı. Not: ayar penceresi bu ayar değişikliğini hemen güncellemeyebilir.\"  \nIDS_D2DDRAWCOMMON_ERROR_TIP = \"Direct2d render işlemi sırasında bir hata oluştu ve direct2d render devre dışı bırakıldı. Not: ayar penceresi bu ayar değişikliğini hemen güncellemeyebilir.\"  \nIDS_PLUGIN_OPTIONS = \"Eklenti Seçenekleri\"  \nIDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG = \"Performans sayacından CPU kullanımı alınamadı, fullCounterPath=<%1%>\"  \n\nTXT_OK = \"Tamam\"  \nTXT_CANCEL = \"İptal\"  \nTXT_CLOSE = \"Kapat\"  \nTXT_APPLY = \"Uygula\"  \n\n; Text used for dialog. (Must be started with \"TXT_\")\n; CAboutDlg\nTXT_TITLE_ABOUT = \"TrafficMonitor Hakkında\"  \nTXT_ABOUT_VERSION = \"TrafficMonitor<%1%>, V<%2%>\"  \nTXT_ABOUT_COPYRIGHT = \"Copyright (C) 2017-2025 ZhongYang'a aittir\\nSon derleme tarihi: <compile_date>\"  \nTXT_ABOUT_TRANSLATOR = \"<%1%> Çevirmen: <%2%>\"  \nTXT_ABOUT_THIRD_PARTY_LIB = \"Bu projede kullanılan üçüncü taraf kütüphaneler:\"  \nTXT_ABOUT_AUTHOR_S_OTHER_SOFTWARE = \"Yazarın diğer yazılımları:\"  \nTXT_ABOUT_CONTACT_AUTHOR = \"Yazarla iletişime geç\"  \nTXT_ABOUT_LICENSE = \"Lisans\"  \nTXT_ABOUT_ACKNOWLEDGEMENT = \"Teşekkür\"  \nTXT_ABOUT_DONATE = \"Bağış Yap\"  \n\n; CAppAlreadyRuningDlg\nTXT_TRAFFICMONITOR_ALREAD_RUNING = \"TrafficMonitor zaten çalışıyor.\"\nTXT_EXIT_THE_PROGRAM = \"Programı &kapat\"\nTXT_OPEN_OPTION_SETTINGS = \"&Seçenek ayarlarını aç\"\nTXT_SHOW_HIDE_MAIN_WINDOW = \"Ana pencereyi &göster/gizle\"\nTXT_SHOW_HIDE_TASKBAR_WINDOW = \"Görev çubuğu penceresini &göster/gizle\"\n\n; CAutoAdaptSettingsDlg\nTXT_TITLE_AUTO_ADATP_SETTINGS = \"Otomatik uyum ayarları\"\nTXT_COLOR_PRESET_IN_DARK_MODE = \"Koyu Windows modunda kullanılan renk ön ayarı:\"\nTXT_COLOR_PRESET_IN_LIGHT_MODE = \"Açık Windows modunda kullanılan renk ön ayarı:\"\nTXT_AUTO_SAVE_TO_PRESET_CHECK = \"Görev çubuğu pencere renk ayarlarını otomatik olarak ön ayara kaydet\"\n\n; CDisplayTextSettingDlg\nTXT_TITLE_DISPLAY_TEXT_SETTING = \"Metin Görüntüleme Ayarları\"\nTXT_RESTORE_DEFAULT = \"&Varsayılanı Geri Yükle\"\n\n; CGeneralSettingsDlg\nTXT_APPLICATION_SETTINGS = \"Uygulama Ayarları\"\nTXT_CHECK_UPDATE = \"Başlangıçta güncellemeleri kontrol et\"\nTXT_CHECK_NOW = \"&Şimdi kontrol et\"\nTXT_UPDATE_SOURCE = \"Güncelleme kaynağı:\"\nTXT_AUTO_RUN_CHECK = \"Windows başladığında otomatik çalışsın\"\nTXT_RESET_AUTO_RUN_BUTTON = \"Otomatik çalışmayı sıfırla\"\nTXT_LANGUAGE = \"Dil:\"\nTXT_CONFIGURATION_AND_DATA_FILES = \"Konfigürasyon ve veri dosyaları\"\nTXT_SAVE_TO_APPDATA_RADIO = \"Appdata dizinine kaydet\"\nTXT_SAVE_TO_PROGRAM_DIR_RADIO = \"Program dizinine kaydet\"\nTXT_OPEN_CONFIG_PATH_BUTTON = \"Konfigürasyon dosyası &dizinini aç\"\nTXT_NOTIFICATION_MESSAGE = \"Bildirim Mesajı\"\nTXT_TODAY_TRAFFIC_TIP_CHECK = \"Bugün trafik limitine ulaşıldığında bildir\"\nTXT_TODAY_TRAFFIC_BACK = \" \"\nTXT_MEMORY_USAGE_TIP_CHECK = \"Bellek kullanımı limitine ulaşıldığında bildir\"\nTXT_MEMORY_USAGE_BACK = \"%\"\nTXT_CPU_TEMP_TIP_CHECK = \"CPU sıcaklık limiti aşıldığında bildir\"\nTXT_CPU_TEMP_BACK = \"°C\"\nTXT_GPU_TEMP_TIP_CHECK = \"GPU sıcaklık limiti aşıldığında bildir\"\nTXT_GPU_TEMP_BACK = \"°C\"\nTXT_HDD_TEMP_TIP_CHECK = \"Hard disk sıcaklık limiti aşıldığında bildir\"\nTXT_HDD_TEMP_BACK = \"°C\"\nTXT_MBD_TEMP_TIP_CHECK = \"Ana kart sıcaklık limiti aşıldığında bildir\"\nTXT_MBD_TEMP_BACK = \"°C\"\nTXT_HARDWARE_MONITORING = \"Donanım İzleme\"\nTXT_CPU = \"CPU\"\nTXT_GPU = \"GPU\"\nTXT_HARD_DISK = \"Hard disk\"\nTXT_MAIN_BOARD = \"Ana kart\"\nTXT_SELECT_HDD_STATIC = \"İzlenecek hard diski seç:\"\nTXT_SELECT_CPU_STATIC = \"İzlenecek CPU sıcaklığını seç:\"\nTXT_ADVANCED = \"Gelişmiş\"\nTXT_SHOW_ALL_CONNECTION_CHECK = \"Tüm ağ bağlantılarını göster\"\nTXT_SELECT_CONNECTIONS_BUTTON = \"&İzlenecek bağlantıyı seç...\"\nTXT_CPU_ACQUISITION_METHOD = \"CPU kullanımı edinme yöntemi:\"\nTXT_USE_CPU_TIME_RADIO = \"CPU zamanına göre\"\nTXT_USE_PDH_RADIO = \"Performans sayaçlarını kullan\"\nTXT_USE_HARDWARE_MONITOR_RADIO = \"Donanım izleyicisini kullan\"\nTXT_MONITORING_INTERVALS = \"İzleme aralıkları:\"\nTXT_MILLISECONDS = \"milisaniye\"\nTXT_RESTORE_DEFAULT_TIME_SPAN_BUTTON = \"&Varsayılanı geri yükle\"\nTXT_PLUGIN_MANAGE_BUTTON = \"Eklenti yönet...\"\nTXT_DISPLAY = \"Görüntü\"\nTXT_SHOW_NOTIFY_ICON_CHECK = \"Bildirim simgesini &göster\"\n\n; CHistoryTrafficCalendarDlg\nTXT_YEAR = \"Yıl:\"\nTXT_MONTH = \"Ay:\"\n\n; CHistoryTrafficDlg\nTXT_TITLE_HISTORY_TRAFFIC = \"Geçmiş Trafik İstatistikleri\"\n\n; CHistoryTrafficListDlg\nTXT_VIEW_TYPE = \"Görünüm tipi:\"\nTXT_FIGURE_VIEW_SCALE = \"Şekil görünüm ölçeği:\"\n\n; CIconSelectDlg\nTXT_TITLE_CHANGE_ICON = \"Bildirim Simgesini Değiştir\"\nTXT_SELECT_A_ICON = \"Bir simge seçin:\"\nTXT_PREVIEW = \"Önizleme\"\nTXT_NOTIFY_ICON_AUTO_ADAPT_CHECK = \"Windows 10 karanlık/aydınlık moduna göre otomatik uyum sağla\"\n\n; CMainWndColorDlg\nTXT_TITLE_MAIN_COLOR_DIALOG = \"Ana Pencere Renk Ayarları\"\n\n; CMainWndSettingsDlg\nTXT_FULLSCREEN_HIDE_CHECK = \"Program tam ekran çalışırken ana pencereyi gizle\"\nTXT_COLOR_AND_FONT = \"Renk ve Yazı Tipi\"\nTXT_FONT = \"Yazı Tipi:\"\nTXT_FONT_SIZE = \"Yazı Tipi Boyutu:\"\nTXT_SET_FONT_BUTTON = \"Yazı Tipini Seç...\"\nTXT_TEXT_COLOR = \"Metin Rengi:\"\nTXT_DISPLAY_TEXT = \"Metin Görüntüle\"\nTXT_SWITCH_UP_DOWN_CHECK = \"Yükleme ve indirme konumlarını değiştir\"\nTXT_UNIT_SETTINGS = \"Birim Ayarları\"\nTXT_UNIT_SELECTION = \"Birim seçimi:\"\nTXT_HIDE_UNIT_CHECK = \"Hız birimini göstermemek\"\nTXT_SPEED_SHORT_MODE_CHECK = \"Ağ hızı görüntüsü için kısa mod\"\nTXT_HIDE_PERCENTAGE_CHECK = \"Yüzdeyi göstermemek\"\nTXT_SPECIFY_EACH_ITEM_COLOR_CHECK = \"Her öğe için renkleri belirt\"\nTXT_DOUBLE_CLICK_ACTION = \"Çift tıklama işlemi:\"\nTXT_SEPARATE_VALUE_UNIT_CHECK = \"Değer ve birimi boşlukla ayır\"\nTXT_NETSPEED_UNIT = \"Ağ Hızı Birimi:\"\nTXT_UNIT_BYTE_RADIO = \"B (Bayt)\"\nTXT_UNIT_BIT_RADIO = \"b (bit)\"\nTXT_SHOW_TOOL_TIP_CHK = \"Fare ipucu göster\"\nTXT_EXE_PATH_STATIC = \"Belirtilen uygulama:\"\nTXT_BROWSE_BUTTON = \"&Gözat...\"\nTXT_DISPLAY_TEXT_SETTING_BUTTON = \"Metin Görüntüleme Ayarları...\"\nTXT_MEMORY_DISPLAY_MODE = \"Bellek görüntüleme modu:\"\nTXT_ALWAYS_ON_TOP_CHECK = \"Her zaman üstte\"\nTXT_MOUSE_PENETRATE_CHECK = \"Fare delme\"\nTXT_LOCK_WINDOW_POS_CHECK = \"Pencere konumunu kilitle\"\nTXT_ALOW_OUT_OF_BORDER_CHECK = \"Ekran sınırlarının dışına çıkmaya izin ver\"\n\n; CMessageDlg\nTXT_TITLE_MESSAGE_DLG = \"Mesaj\"\n\n; CNetworkInfoDlg\nTXT_TITLE_NETWORK_INFO_DLG = \"Bağlantı Detayları\"\n\n; COptionsDlg\nTXT_TITLE_OPTION = \"Seçenek Ayarları\"\n\n; CPluginManagerDlg\nTXT_TITLE_PLUGIN_MANAGE = \"Eklenti Yönetimi\"\nTXT_OPTINS_BUTTON = \"&Seçenekler...\"\nTXT_PLUGIN_INFO_BUTTON = \"&Detaylar...\"\nTXT_PLUGIN_DEV_GUID_STATIC = \"Eklenti geliştirme kılavuzu\"\nTXT_PLUGIN_DOWNLOAD_STATIC = \"Daha fazla eklenti indir\"\nTXT_OPEN_PLUGIN_DIR_STATIC = \"Eklenti dizinini aç\"\n\n;CSelectConnectionsDlg\nTXT_TITLE_SELECTION_CONNECTION = \"Bağlantıyı seçin ve izleyin\"\n\n; CSetItemOrderDlg\nTXT_TITLE_SELECT_ORDER_DIALOG = \"Görüntü Ayarları\"\nTXT_MOVE_UP_BUTTON = \"Yukarı Taşı\"\nTXT_MOVE_DOWN_BUTTON = \"Aşağı Taşı\"\nTXT_RESTORE_DEFAULT_BUTTON = \"Varsayılanı &Geri Yükle\"\n\n; CSkinAutoAdaptSettingDlg\nTXT_TITLE_SKIN_AUTO_ADAPTT_DLG = \"Cilt otomatik geçiş ayarları\"\nTXT_SKIN_IN_DARK_MODE = \"Karanlık Windows modunda kullanılan cilt:\"\nTXT_SKIN_IN_LIGHT_MODE = \"Aydınlık Windows modunda kullanılan cilt:\"\n\n; CSkinDlg\nTXT_TITLE_SKIN_DLG = \"Cilt Değiştir\"\nTXT_PREVIEW_GROUP_STATIC = \"Önizleme\"\nTXT_SELECT_A_SKIN = \"Bir cilt seç\"\nTXT_SKIN_AUTHOR = \"Cilt yazarı:\"\nTXT_SKIN_MAKING_UP_TUTORIAL = \"Cilt yapma eğitimi\"\nTXT_DOWNLOAD_MORE_SKIN = \"Daha fazla cilt indir\"\nTXT_OPEN_SKIN_DIR = \"Cilt dizinini aç\"\nTXT_SKIN_AUTO_ADAPT_CHECK = \"Windows karanlık / aydınlık renk modlarına göre ciltleri otomatik olarak değiştir.\"\nTXT_SKIN_AUTO_ADAPT_BUTTON = \"Otomatik geçiş ayarları...\"\n\n; CTaskbarColorDlg\nTXT_TITLE_TASKBAR_COLOR_DLG = \"Görev Çubuğu Penceresi Renk Ayarları\"\n\n; CTaskBarSettingsDlg\nTXT_PRESET = \"&Ön Ayar\"\nTXT_BACKGROUND_COLOR = \"Arka plan rengi:\"\nTXT_BACKGROUND_TRANSPARENT = \"Arka plan şeffaf\"\nTXT_AUTO_SET_BACK_COLOR = \"Görev çubuğu rengine göre arka plan rengini otomatik olarak ayarla\"\nTXT_AUTO_ADAPT_LIGHT_THEME = \"Windows 10 karanlık/aydınlık temalarına otomatik uyum sağla\"\nTXT_AUTO_ADAPT_SETTINGS_BUTTON = \"Otomatik Uyarlama &ayarları...\"\nTXT_DISPLAY_SETTINGS = \"Görüntü Ayarları\"\nTXT_DISPLAY_SETTINGS_BUTTON = \"&Görüntü ayarları...\"\nTXT_SPEED_SHORT_MODE = \"Kısa modda ağ hızı gösterimi\"\nTXT_VALUE_RIGHT_ALIGN = \"Değerleri sağa hizala\"\nTXT_NET_SPEED_DATA_WIDTH = \"Ağ hızı veri genişliği:\"\nTXT_CHARACTORS = \"karakterler\"\nTXT_HORIZONTAL_ARRANGE = \"Yatay düzen\"\nTXT_ITEM_SPACING = \"Öğe aralığı:\"\nTXT_VERTICAL_MARGIN = \"Dikey Margin:\"\nTXT_PIXELS = \"piksel\"\nTXT_TASKBAR_WINDOW = \"Görev Çubuğu Penceresi\"\nTXT_TASKBAR_WND_ON_LEFT = \"Görev çubuğu penceresi görev çubuğunun sol tarafında görünür\"\nTXT_SHOW_TASKBAR_WND_IN_SECONDARY_DISPLAY = \"Görev çubuğu penceresini ikincil ekranda göster (varsa)\"\nTXT_WIN11_SETTINGS_BUTTON = \"Windows11 ile ilgili ayarlar\"\nTXT_RESOURCE_USAGE_GRAPH = \"Kaynak kullanım grafiği\"\nTXT_SHOW_RESOURCE_USAGE_GRAPH = \"Kaynak kullanım grafiğini göster\"\nTXT_SHOW_DASHED_BOX = \"Kesikli kutuyu göster\"\nTXT_SHOW_NET_SPEED_GRAPH = \"Ağ hızı grafiğini göster\"\nTXT_NET_SPEED_GRAPH_MAX_VALUE = \"Ağ hızı grafiğinin maksimum değeri:\"\nTXT_USAGE_GRAPH_COLOR = \"Kullanım grafiği rengi:\"\nTXT_GRAPH_DISPLAY_MODE = \"Grafik görüntüleme modu:\"\nTXT_BAR_MODE = \"Çubuk modu\"\nTXT_PLOT_MODE = \"Çizim modu\"\nTXT_RENDERING_SETTINGS = \"Render ayarları\"\nTXT_RENDERING_SETTINGS_NOTE = \"Not: Arka plan şeffaf olarak işaretlendiğinde ve \\\"Görev çubuğu rengine göre arka plan rengini otomatik olarak ayarla\\\" işaretlenmediğinde Direct2D render kullanılır.\"\nTXT_ENABLE_COLOR_EMOJI = \"Renkli emojileri etkinleştir\"\n\n; CWin11TaskbarSettingDlg\nTXT_TITLE_WIN11_TASKBAR_SETTING = \"Windows11 ile ilgili ayarlar\"\nTXT_TASKBAR_WINDOWS_CLOSE_TO_ICON = \"Görev çubuğu penceresini görev çubuğunun yanları yerine simgesine yakın kapat\"\nTXT_WINDOW_VERTICAL_OFFSET = \"Pencere dikey ofseti:\"\nTXT_WINDOW_HORIZONTAL_OFFSET = \"Pencere yatay ofseti:\"\nTXT_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK = \"Sağdaki widget'larla örtüşmeyi önle (Widget'lar görev çubuğunun sağ tarafında görünüyorsa bu seçeneği işaretleyin)\"\nTXT_WIDGETS_WIDTH = \"Widget'lar genişliği:\"\n\n[menu]\n; IDR_HISTORY_TRAFFIC_MENU\nTXT_SHOW_SCALE = \"Ölçeği Göster\"\nTXT_USE_LINEAR_SCALE = \"Doğrusal Ölçek Kullan\"\nTXT_USE_LOG_SCALE = \"Logaritmik Ölçek Kullan\"\nTXT_FIRST_DAT_OF_WEEEK = \"Haftanın ilk günü\"\nTXT_SUNDAY = \"Pazar\"\nTXT_MONDAY = \"Pazartesi\"\nTXT_GO_TO_TODAY = \"Bugüne Git\"\n\n; IDR_INFO_MENU\nTXT_COPY_TEXT = \"&Copy Text\"\n\n; IDR_MENU1\nTXT_SELECT_CONNECTIONS = \"&Ağ Bağlantılarını Seç\"\nTXT_AUTO_SELECT = \"&Otomatik Seç\"\nTXT_SELECT_ALL = \"&Hepsini Seç\"\nTXT_CONNECTION_DETAILS = \"Bağlantı &Detayları\"\nTXT_ALWAYS_ON_TOP = \"Her Zaman &Üstte\"\nTXT_MOUSE_PENETRATE = \"Fare &Penetrasyonu\"\nTXT_LOCK_WINDOW_POS = \"&Pencere Konumunu Kilitle\"\nTXT_SHOW_MORE_INFO = \"Daha Fazla &Bilgi Göster\"\nTXT_SHOW_TASKBAR_WINDOW = \"Görev Çubuğu &Penceresini Göster\"\nTXT_SHOW_MAIN_WINDOW = \"Ana &Pencereyi Göster\"\nTXT_WINDOW_OPACITY = \"Pencere Opaklığı\"\nTXT_OTHER_FUNCTIONS = \"Diğer &Fonksiyonlar\"\nTXT_CHANGE_SKIN = \"&Cildi Değiştir...\"\nTXT_CHANGE_NOTIFY_ICON = \"Bildirim &Simgesini Değiştir...\"\nTXT_ALLOW_OUT_OF_BOUNDARIES = \"Ekran &Sınırlarının Dışına Çıkmasına İzin Ver\"\nTXT_HISTORY_TRAFFIC_STATISTICS = \"&Geçmiş Trafik İstatistikleri\"\nTXT_PLUGIN_MANAGE = \"Eklenti Yönetimi...\"\nTXT_OPTIONS = \"&Ayarlar...\"\nTXT_HELP_MENU = \"&Yardım\"\nTXT_HELP = \"&Yardım\"\nTXT_FAQ = \"&Sıkça Sorulan Sorular\"\nTXT_UPDATE_LOG = \"Güncelleme &Günlüğü\"\nTXT_ABOUT = \"&Hakkında...\"\nTXT_CHECK_UPDATE = \"&Güncellemeyi Kontrol Et...\"\nTXT_EXIT = \"Çıkış\"\n\n; IDR_TASK_BAR_MENU\nTXT_DISPLAY_SETTINGS = \"Gösterim &Ayarları...\"\nTXT_CLOSE_TASKBAR_WINDOW = \"&Görev Çubuğu Penceresini Kapat\"\nTXT_TASK_MANAGER = \"&Görev Yöneticisi\"\n\n;IDR_PLUGIN_MANAGER_MENU\nTXT_PLUGIN_DETAIL = \"&Ayrıntılar...\"\nTXT_PLUGIN_OPTIONS = \"&Seçenekler...\"\nTXT_PLUGIN_DISABLE = \"D&isabled\"\n"
  },
  {
    "path": "TrafficMonitor/language.h",
    "content": "﻿#pragma once \n \n#define IDS_CHECK_UPDATE_FAILD L\"IDS_CHECK_UPDATE_FAILD\"\n#define IDS_CHECK_UPDATE_ERROR L\"IDS_CHECK_UPDATE_ERROR\"\n#define IDS_UPDATE_AVLIABLE L\"IDS_UPDATE_AVLIABLE\"\n#define IDS_UPDATE_AVLIABLE2 L\"IDS_UPDATE_AVLIABLE2\"\n#define IDS_ALREADY_UPDATED L\"IDS_ALREADY_UPDATED\"\n#define IDS_AUTORUN_FAILED_NO_KEY L\"IDS_AUTORUN_FAILED_NO_KEY\"\n#define IDS_AUTORUN_FAILED_NO_ACCESS L\"IDS_AUTORUN_FAILED_NO_ACCESS\"\n#define IDS_AUTORUN_DELETE_FAILED L\"IDS_AUTORUN_DELETE_FAILED\"\n#define IDS_AN_INSTANCE_RUNNING L\"IDS_AN_INSTANCE_RUNNING\"\n#define IDS_TRAFFIC_USED_TODAY L\"IDS_TRAFFIC_USED_TODAY\"\n#define IDS_MEMORY_USAGE L\"IDS_MEMORY_USAGE\"\n#define IDS_CPU_USAGE L\"IDS_CPU_USAGE\"\n#define IDS_SEND_EMAIL_TO_ATHOUR L\"IDS_SEND_EMAIL_TO_ATHOUR\"\n#define IDS_GOTO_GITHUB L\"IDS_GOTO_GITHUB\"\n#define IDS_DONATE_ATHOUR L\"IDS_DONATE_ATHOUR\"\n#define IDS_UPLOAD L\"IDS_UPLOAD\"\n#define IDS_DOWNLOAD L\"IDS_DOWNLOAD\"\n#define IDS_MEMORY L\"IDS_MEMORY\"\n#define IDS_UPLOAD_DISP L\"IDS_UPLOAD_DISP\"\n#define IDS_DOWNLOAD_DISP L\"IDS_DOWNLOAD_DISP\"\n#define IDS_MEMORY_DISP L\"IDS_MEMORY_DISP\"\n#define IDS_CONNOT_SAVE_CONFIG_WARNING L\"IDS_CONNOT_SAVE_CONFIG_WARNING\"\n#define IDS_TRAFFICMONITOR L\"IDS_TRAFFICMONITOR\"\n#define IDS_INSUFFICIENT_BUFFER L\"IDS_INSUFFICIENT_BUFFER\"\n#define IDS_CONNECTION_NUM_CHANGED L\"IDS_CONNECTION_NUM_CHANGED\"\n#define IDS_CONNECTION_NOT_MATCH L\"IDS_CONNECTION_NOT_MATCH\"\n#define IDS_CONNOT_INSERT_TO_TASKBAR L\"IDS_CONNOT_INSERT_TO_TASKBAR\"\n#define IDS_MEMORY_UDAGE_EXCEED L\"IDS_MEMORY_UDAGE_EXCEED\"\n#define IDS_NOTIFY L\"IDS_NOTIFY\"\n#define IDS_TODAY_TRAFFIC_EXCEED L\"IDS_TODAY_TRAFFIC_EXCEED\"\n#define IDS_DATE L\"IDS_DATE\"\n#define IDS_TRAFFIC_USED L\"IDS_TRAFFIC_USED\"\n#define IDS_FIGURE L\"IDS_FIGURE\"\n#define IDS_DEFAULT_ICON L\"IDS_DEFAULT_ICON\"\n#define IDS_ICON L\"IDS_ICON\"\n#define IDS_INTERFACE_NAME L\"IDS_INTERFACE_NAME\"\n#define IDS_INTERFACE_DESCRIPTION L\"IDS_INTERFACE_DESCRIPTION\"\n#define IDS_CONNECTION_TYPE L\"IDS_CONNECTION_TYPE\"\n#define IDS_IF_TYPE_OTHER L\"IDS_IF_TYPE_OTHER\"\n#define IDS_IF_TYPE_ETHERNET_CSMACD L\"IDS_IF_TYPE_ETHERNET_CSMACD\"\n#define IDS_IF_TYPE_ISO88025_TOKENRING L\"IDS_IF_TYPE_ISO88025_TOKENRING\"\n#define IDS_IF_TYPE_FDDI L\"IDS_IF_TYPE_FDDI\"\n#define IDS_IF_TYPE_PPP L\"IDS_IF_TYPE_PPP\"\n#define IDS_IF_TYPE_SOFTWARE_LOOPBACK L\"IDS_IF_TYPE_SOFTWARE_LOOPBACK\"\n#define IDS_IF_TYPE_ATM L\"IDS_IF_TYPE_ATM\"\n#define IDS_IF_TYPE_IEEE80211 L\"IDS_IF_TYPE_IEEE80211\"\n#define IDS_IF_TYPE_TUNNEL L\"IDS_IF_TYPE_TUNNEL\"\n#define IDS_IF_TYPE_IEEE1394 L\"IDS_IF_TYPE_IEEE1394\"\n#define IDS_IF_TYPE_IEEE80216_WMAN L\"IDS_IF_TYPE_IEEE80216_WMAN\"\n#define IDS_IF_TYPE_WWANPP L\"IDS_IF_TYPE_WWANPP\"\n#define IDS_IF_TYPE_WWANPP2 L\"IDS_IF_TYPE_WWANPP2\"\n#define IDS_UNKNOW_CONNECTION L\"IDS_UNKNOW_CONNECTION\"\n#define IDS_SPEED L\"IDS_SPEED\"\n#define IDS_ADAPTER_PHYSICAL_ADDRESS L\"IDS_ADAPTER_PHYSICAL_ADDRESS\"\n#define IDS_IP_ADDRESS L\"IDS_IP_ADDRESS\"\n#define IDS_SUBNET_MASK L\"IDS_SUBNET_MASK\"\n#define IDS_DEFAULT_GATEWAY L\"IDS_DEFAULT_GATEWAY\"\n#define IDS_OPERATIONAL_STATUS L\"IDS_OPERATIONAL_STATUS\"\n#define IDS_IF_OPER_STATUS_NON_OPERATIONAL L\"IDS_IF_OPER_STATUS_NON_OPERATIONAL\"\n#define IDS_IF_OPER_STATUS_UNREACHABLE L\"IDS_IF_OPER_STATUS_UNREACHABLE\"\n#define IDS_IF_OPER_STATUS_DISCONNECTED L\"IDS_IF_OPER_STATUS_DISCONNECTED\"\n#define IDS_IF_OPER_STATUS_CONNECTING L\"IDS_IF_OPER_STATUS_CONNECTING\"\n#define IDS_IF_OPER_STATUS_CONNECTED L\"IDS_IF_OPER_STATUS_CONNECTED\"\n#define IDS_IF_OPER_STATUS_OPERATIONAL L\"IDS_IF_OPER_STATUS_OPERATIONAL\"\n#define IDS_UNKNOW_STATUS L\"IDS_UNKNOW_STATUS\"\n#define IDS_BYTES_RECEIVED L\"IDS_BYTES_RECEIVED\"\n#define IDS_BYTES_SENT L\"IDS_BYTES_SENT\"\n#define IDS_BYTES_RECEIVED_SINCE_START L\"IDS_BYTES_RECEIVED_SINCE_START\"\n#define IDS_BYTES_SENT_SINCE_START L\"IDS_BYTES_SENT_SINCE_START\"\n#define IDS_PROGRAM_ELAPSED_TIME L\"IDS_PROGRAM_ELAPSED_TIME\"\n#define IDS_HOUR_MINUTE_SECOND L\"IDS_HOUR_MINUTE_SECOND\"\n#define IDS_INTERNET_IP_ADDRESS L\"IDS_INTERNET_IP_ADDRESS\"\n#define IDS_GET_FAILED L\"IDS_GET_FAILED\"\n#define IDS_ITEM L\"IDS_ITEM\"\n#define IDS_VALUE L\"IDS_VALUE\"\n#define IDS_COPY_TO_CLIPBOARD_FAILED L\"IDS_COPY_TO_CLIPBOARD_FAILED\"\n#define IDS_SKIN_AUTHOUR L\"IDS_SKIN_AUTHOUR\"\n#define IDS_OVERWRITE_FONT_TEXT_WARNING L\"IDS_OVERWRITE_FONT_TEXT_WARNING\"\n#define IDS_OVERWRITE_FONT_WARNING L\"IDS_OVERWRITE_FONT_WARNING\"\n#define IDS_OVERWRITE_TEXT_WARNING L\"IDS_OVERWRITE_TEXT_WARNING\"\n#define IDS_SPEED_SHORT_MODE_TIP L\"IDS_SPEED_SHORT_MODE_TIP\"\n#define IDS_AUTO L\"IDS_AUTO\"\n#define IDS_FIXED_AS L\"IDS_FIXED_AS\"\n#define IDS_OPEN_CONNECTION_DETIAL L\"IDS_OPEN_CONNECTION_DETIAL\"\n#define IDS_OPEN_HISTORICAL_TRAFFIC L\"IDS_OPEN_HISTORICAL_TRAFFIC\"\n#define IDS_SHOW_HIDE_MORE_INFO L\"IDS_SHOW_HIDE_MORE_INFO\"\n#define IDS_SHOW_HIDE_CPU_MEMORY L\"IDS_SHOW_HIDE_CPU_MEMORY\"\n#define IDS_OPEN_OPTION_SETTINGS L\"IDS_OPEN_OPTION_SETTINGS\"\n#define IDS_OPEN_TASK_MANAGER L\"IDS_OPEN_TASK_MANAGER\"\n#define IDS_CHANGE_SKIN L\"IDS_CHANGE_SKIN\"\n#define IDS_NONE L\"IDS_NONE\"\n#define IDS_FONT_SIZE_WARNING L\"IDS_FONT_SIZE_WARNING\"\n#define IDS_SAME_TEXT_BACK_COLOR_WARNING L\"IDS_SAME_TEXT_BACK_COLOR_WARNING\"\n#define IDS_SAME_BACK_TEXT_COLOR_WARNING L\"IDS_SAME_BACK_TEXT_COLOR_WARNING\"\n#define IDS_FOLLOWING_SYSTEM L\"IDS_FOLLOWING_SYSTEM\"\n#define IDS_LANGUAGE_CHANGE_INFO L\"IDS_LANGUAGE_CHANGE_INFO\"\n#define IDS_MAIN_WINDOW_SETTINGS L\"IDS_MAIN_WINDOW_SETTINGS\"\n#define IDS_TASKBAR_WINDOW_SETTINGS L\"IDS_TASKBAR_WINDOW_SETTINGS\"\n#define IDS_GENERAL_SETTINGS L\"IDS_GENERAL_SETTINGS\"\n#define IDS_ACQUIRING L\"IDS_ACQUIRING\"\n#define IDS_LIST_VIEW L\"IDS_LIST_VIEW\"\n#define IDS_CALENDAR_VIEW L\"IDS_CALENDAR_VIEW\"\n#define IDS_MONDAY L\"IDS_MONDAY\"\n#define IDS_TUESDAY L\"IDS_TUESDAY\"\n#define IDS_WEDNESDAY L\"IDS_WEDNESDAY\"\n#define IDS_THURSDAY L\"IDS_THURSDAY\"\n#define IDS_FRIDAY L\"IDS_FRIDAY\"\n#define IDS_SATURDAY L\"IDS_SATURDAY\"\n#define IDS_SUNDAY L\"IDS_SUNDAY\"\n#define IDS_CURRENT_MONTH_TOTAL_TRAFFIC L\"IDS_CURRENT_MONTH_TOTAL_TRAFFIC\"\n#define IDS_TRAFFIC_USED1 L\"IDS_TRAFFIC_USED1\"\n#define IDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG L\"IDS_CONNOT_INSERT_TO_TASKBAR_ERROR_LOG\"\n#define IDS_NO_CONNECTION L\"IDS_NO_CONNECTION\"\n#define IDS_CONTACT_TRANSLATOR L\"IDS_CONTACT_TRANSLATOR\"\n#define IDS_THANKS_DONORS L\"IDS_THANKS_DONORS\"\n#define IDS_GET_URL_ERROR_LOG_INFO L\"IDS_GET_URL_ERROR_LOG_INFO\"\n#define IDS_SHOW_ALL_INFO_TIP L\"IDS_SHOW_ALL_INFO_TIP\"\n#define IDS_CFG_DIR_CHANGED_INFO L\"IDS_CFG_DIR_CHANGED_INFO\"\n#define IDS_DOUBLE_CLICK_TO_ACQUIRE L\"IDS_DOUBLE_CLICK_TO_ACQUIRE\"\n#define IDS_ERROR1 L\"IDS_ERROR1\"\n#define IDS_ERROR_MESSAGE L\"IDS_ERROR_MESSAGE\"\n#define IDS_CRASH_INFO L\"IDS_CRASH_INFO\"\n#define IDS_TITLE_ACKNOWLEDGEMENT L\"IDS_TITLE_ACKNOWLEDGEMENT\"\n#define IDS_SAVE_DEFAULT_STYLE_INQUIRY L\"IDS_SAVE_DEFAULT_STYLE_INQUIRY\"\n#define IDS_SPECIFIC_APP L\"IDS_SPECIFIC_APP\"\n#define IDS_EXE_FILTER L\"IDS_EXE_FILTER\"\n#define IDS_PRESET L\"IDS_PRESET\"\n#define IDS_LIGHT_MODE L\"IDS_LIGHT_MODE\"\n#define IDS_AUTO_ADAPT_TIP_INFO L\"IDS_AUTO_ADAPT_TIP_INFO\"\n#define IDS_WITHOUT_TEMPERATURE L\"IDS_WITHOUT_TEMPERATURE\"\n#define IDS_MOUSE_PENETRATE_TIP_INFO L\"IDS_MOUSE_PENETRATE_TIP_INFO\"\n#define IDS_HISTORY_TRAFFIC_LOST_ERROR_LOG L\"IDS_HISTORY_TRAFFIC_LOST_ERROR_LOG\"\n#define IDS_LEGEND L\"IDS_LEGEND\"\n#define IDS_LICENSE_EXPLAIN L\"IDS_LICENSE_EXPLAIN\"\n#define IDS_LICENSE L\"IDS_LICENSE\"\n#define IDS_DAY_VIEW L\"IDS_DAY_VIEW\"\n#define IDS_MONTH_VIEW L\"IDS_MONTH_VIEW\"\n#define IDS_QUARTER_VIEW L\"IDS_QUARTER_VIEW\"\n#define IDS_YEAR_VIEW L\"IDS_YEAR_VIEW\"\n#define IDS_LINEAR_SCALE L\"IDS_LINEAR_SCALE\"\n#define IDS_LOG_SCALE L\"IDS_LOG_SCALE\"\n#define IDS_CPU_TEMPERATURE L\"IDS_CPU_TEMPERATURE\"\n#define IDS_GPU_TEMPERATURE L\"IDS_GPU_TEMPERATURE\"\n#define IDS_CPU_FREQ L\"IDS_CPU_FREQ\"\n#define IDS_HDD_TEMPERATURE L\"IDS_HDD_TEMPERATURE\"\n#define IDS_MAINBOARD_TEMPERATURE L\"IDS_MAINBOARD_TEMPERATURE\"\n#define IDS_GPU_DISP L\"IDS_GPU_DISP\"\n#define IDS_HDD_DISP L\"IDS_HDD_DISP\"\n#define IDS_MAINBOARD_DISP L\"IDS_MAINBOARD_DISP\"\n#define IDS_CPU_TEMPERATURE_EXCEED L\"IDS_CPU_TEMPERATURE_EXCEED\"\n#define IDS_GPU_TEMPERATURE_EXCEED L\"IDS_GPU_TEMPERATURE_EXCEED\"\n#define IDS_HDD_TEMPERATURE_EXCEED L\"IDS_HDD_TEMPERATURE_EXCEED\"\n#define IDS_MBD_TEMPERATURE_EXCEED L\"IDS_MBD_TEMPERATURE_EXCEED\"\n#define IDS_MUSICPLAYER2_DESCRIPTION L\"IDS_MUSICPLAYER2_DESCRIPTION\"\n#define IDS_SIMPLENOTEPAD_DESCRIPTION L\"IDS_SIMPLENOTEPAD_DESCRIPTION\"\n#define IDS_COLOR L\"IDS_COLOR\"\n#define IDS_COLOR_LABEL L\"IDS_COLOR_LABEL\"\n#define IDS_COLOR_VALUE L\"IDS_COLOR_VALUE\"\n#define IDS_GPU_USAGE L\"IDS_GPU_USAGE\"\n#define IDS_IF_OPER_STATUS_UP L\"IDS_IF_OPER_STATUS_UP\"\n#define IDS_IF_OPER_STATUS_DOWN L\"IDS_IF_OPER_STATUS_DOWN\"\n#define IDS_IF_OPER_STATUS_DORMANT L\"IDS_IF_OPER_STATUS_DORMANT\"\n#define IDS_GOTO_GITEE L\"IDS_GOTO_GITEE\"\n#define IDS_USAGE_PERCENTAGE L\"IDS_USAGE_PERCENTAGE\"\n#define IDS_MEMORY_USED L\"IDS_MEMORY_USED\"\n#define IDS_MEMORY_AVAILABLE L\"IDS_MEMORY_AVAILABLE\"\n#define IDS_DOTNET_NOT_INSTALLED_TIP L\"IDS_DOTNET_NOT_INSTALLED_TIP\"\n#define IDS_VERSION_UPDATE L\"IDS_VERSION_UPDATE\"\n#define IDS_AVREAGE_TEMPERATURE L\"IDS_AVREAGE_TEMPERATURE\"\n#define IDS_HARDWARE_MONITOR_WARNING L\"IDS_HARDWARE_MONITOR_WARNING\"\n#define IDS_HDD_USAGE L\"IDS_HDD_USAGE\"\n#define IDS_FILE_NAME L\"IDS_FILE_NAME\"\n#define IDS_STATUS L\"IDS_STATUS\"\n#define IDS_PLUGIN_LOAD_SUCCEED L\"IDS_PLUGIN_LOAD_SUCCEED\"\n#define IDS_PLUGIN_MODULE_LOAD_FAILED L\"IDS_PLUGIN_MODULE_LOAD_FAILED\"\n#define IDS_PLUGIN_FUNCTION_GET_FAILED L\"IDS_PLUGIN_FUNCTION_GET_FAILED\"\n#define IDS_PLUGIN_INFO L\"IDS_PLUGIN_INFO\"\n#define IDS_NAME L\"IDS_NAME\"\n#define IDS_DESCRIPTION L\"IDS_DESCRIPTION\"\n#define IDS_FILE_PATH L\"IDS_FILE_PATH\"\n#define IDS_ITEM_NUM L\"IDS_ITEM_NUM\"\n#define IDS_ITEM_NAMES L\"IDS_ITEM_NAMES\"\n#define IDS_AUTHOR L\"IDS_AUTHOR\"\n#define IDS_COPYRIGHT L\"IDS_COPYRIGHT\"\n#define IDS_PLUGIN_NO_OPTIONS_INFO L\"IDS_PLUGIN_NO_OPTIONS_INFO\"\n#define IDS_PLUGIN_NAME L\"IDS_PLUGIN_NAME\"\n#define IDS_DISABLED L\"IDS_DISABLED\"\n#define IDS_RESTART_TO_APPLY_CHANGE_INFO L\"IDS_RESTART_TO_APPLY_CHANGE_INFO\"\n#define IDS_VERSION L\"IDS_VERSION\"\n#define IDS_DISP_ITEM_ID L\"IDS_DISP_ITEM_ID\"\n#define IDS_PLUGIN_API_VERSION L\"IDS_PLUGIN_API_VERSION\"\n#define IDS_WEEK_VIEW L\"IDS_WEEK_VIEW\"\n#define IDS_WEEK_NUM L\"IDS_WEEK_NUM\"\n#define IDS_URL L\"IDS_URL\"\n#define IDS_PLUGIN_VERSION_NOT_SUPPORT L\"IDS_PLUGIN_VERSION_NOT_SUPPORT\"\n#define IDS_MODIFY_PRESET L\"IDS_MODIFY_PRESET\"\n#define IDS_SELECT_AT_LEASE_ONE_WARNING L\"IDS_SELECT_AT_LEASE_ONE_WARNING\"\n#define IDS_AUTO_SAVE_TO_PRESET_TIP L\"IDS_AUTO_SAVE_TO_PRESET_TIP\"\n#define IDS_TOTAL_NET_SPEED L\"IDS_TOTAL_NET_SPEED\"\n#define IDS_SHOW_RESOURCE_USAGE_GRAPH_TIP L\"IDS_SHOW_RESOURCE_USAGE_GRAPH_TIP\"\n#define IDS_SHOW_NET_SPEED_GRAPH_TIP L\"IDS_SHOW_NET_SPEED_GRAPH_TIP\"\n#define IDS_REFRESH_CONNECTION_LIST L\"IDS_REFRESH_CONNECTION_LIST\"\n#define IDS_HARDWARE_MONITOR_INIT_FAILED L\"IDS_HARDWARE_MONITOR_INIT_FAILED\"\n#define IDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR L\"IDS_HARDWARE_INFO_ACQUIRE_FAILED_ERROR\"\n#define IDS_AUTO_RUN_METHOD_REGESTRY L\"IDS_AUTO_RUN_METHOD_REGESTRY\"\n#define IDS_AUTO_RUN_METHOD_TASK_SCHEDULE L\"IDS_AUTO_RUN_METHOD_TASK_SCHEDULE\"\n#define IDS_PATH L\"IDS_PATH\"\n#define IDS_SET_AUTO_RUN_FAILED_WARNING L\"IDS_SET_AUTO_RUN_FAILED_WARNING\"\n#define IDS_UPDATE_TASKBARDLG_FAILED_TIP L\"IDS_UPDATE_TASKBARDLG_FAILED_TIP\"\n#define IDS_D2DDRAWCOMMON_ERROR_TIP L\"IDS_D2DDRAWCOMMON_ERROR_TIP\"\n#define IDS_PLUGIN_OPTIONS L\"IDS_PLUGIN_OPTIONS\"\n#define IDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG L\"IDS_GET_CPU_USAGE_BY_PDH_FAILED_LOG\"\n#define IDS_PRIMARY_DISPLAY L\"IDS_PRIMARY_DISPLAY\"\n#define IDS_SECONDARY_DISPLAY L\"IDS_SECONDARY_DISPLAY\"\n#define IDS_RESTORE_FROM_SLEEP_LOG L\"IDS_RESTORE_FROM_SLEEP_LOG\"\n#define IDS_PLUGIN_NEW_VERSION_INFO L\"IDS_PLUGIN_NEW_VERSION_INFO\"\n#define IDS_TRAFFICMONITOR_PLUGIN_NITIFICATION L\"IDS_TRAFFICMONITOR_PLUGIN_NITIFICATION\"\n#define IDS_SKIN_FILE_ERROR_INFO L\"IDS_SKIN_FILE_ERROR_INFO\"\n\n#define TXT_OK L\"TXT_OK\"\n#define TXT_CANCEL L\"TXT_CANCEL\"\n#define TXT_CLOSE L\"TXT_CLOSE\""
  },
  {
    "path": "TrafficMonitor/print_compile_time.bat",
    "content": "REM ǰںʱ䣬浽compile_time.txtļ\ndel /F /Q compile_time.txt\necho %date:~0,10% >> compile_time.txt\necho %time:~0,8% >> compile_time.txt"
  },
  {
    "path": "TrafficMonitor/resource.h",
    "content": "﻿//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ 生成的包含文件。\n// 供 TrafficMonitor.rc 使用\n//\n#define IDD_TRAFFICMONITOR_DIALOG       102\n#define IDR_MAINFRAME                   128\n#define IDR_MENU1                       130\n#define IDD_NETWORK_INFO_DIALOG         131\n#define IDD_ABOUTBOX                    133\n#define IDD_TASK_BAR_DIALOG             135\n#define IDR_TASK_BAR_MENU               137\n#define IDD_SKIN_DIALOG                 138\n#define IDB_BITMAP1                     140\n#define IDD_HISTORY_TRAFFIC_DIALOG      141\n#define IDB_BITMAP2                     145\n#define IDB_DONATE_BITMAP               145\n#define IDI_NOFITY_ICON                 146\n#define IDD_OPTIONS_DIALOG              147\n#define IDD_MAIN_WND_SETTINGS_DIALOG    149\n#define IDD_TASKBAR_SETTINGS_DIALOG     150\n#define IDR_INFO_MENU                   153\n#define IDR_MENU2                       154\n#define IDR_HISTORY_TRAFFIC_MENU        154\n#define IDD_GENERAL_SETTINGS_DIALOG     155\n#define IDB_ABOUT_BACKGROUND_HD         157\n#define IDI_NOFITY_ICON2                158\n#define IDI_NOFITY_ICON3                159\n#define IDD_ICON_SELECT_DIALOG          160\n#define IDB_NOTIFY_ICON_PREVIEW         162\n#define IDD_MAIN_COLOR_DIALOG           163\n#define IDD_TASKBAR_COLOR_DIALOG        165\n#define IDD_HISTORY_TRAFFIC_LIST_DIALOG 168\n#define IDD_HISTORY_TRAFFIC_CALENDAR_DIALOG 170\n#define IDS_SEND_EMAIL_TO_TRANSLATOR    290\n#define IDR_TEXT2                       290\n#define IDR_TEXT                        290\n#define IDD_DIALOG1                     293\n#define IDD_MESSAGE_DIALOG              293\n#define IDR_ACKNOWLEDGEMENT_TEXT        294\n#define IDI_NOFITY_ICON4                299\n#define IDB_NOTIFY_ICON_PREVIEW_LIGHT   302\n#define IDB_BITMAP3                     305\n#define IDB_DONATE_WECHAT               305\n#define IDD_ATUO_ADAPT_SETTING_DIALOG   306\n#define IDR_LICENSE                     310\n#define IDI_EXIT                        311\n#define IDI_HELP                        312\n#define IDI_INFO                        313\n#define IDI_LOCK                        314\n#define IDI_SETTINGS                    315\n#define IDI_STATISTICS                  316\n#define IDI_CLOSE                       317\n#define IDI_PIN                         318\n#define IDI_SKIN                        319\n#define IDI_CONNECTION                  320\n#define IDI_MOUSE                       321\n#define IDI_MAIN_WINDOW                 322\n#define IDI_TASKBAR_WINDOW              323\n#define IDI_NOTIFY                      324\n#define IDI_MORE                        325\n#define IDI_ITEM                        326\n#define IDI_FUNCTION                    327\n#define IDI_NOTIFY_ICON5                328\n#define IDD_DISPLAY_TEXT_SETTINGS_DIALOG 329\n#define IDR_COMPILE_TIME                329\n#define IDD_SELECT_ORDER_DIALOG         330\n#define IDD_PLUGIN_MANAGER_DIALOG       332\n#define IDI_PLUGINS                     334\n#define IDR_MENU3                       335\n#define IDR_PLUGIN_MANAGER_MENU         335\n#define IDI_TASK_MANAGER                336\n#define IDD_APP_ALREAD_RUNING_DIALOG    337\n#define IDD_SELECT_CONNECTIONS_DIALOG   339\n#define IDD_TASK_BAR_DIALOG_NOREDIRECTIONBITMAP 340\n#define IDD_SKIN_AUTO_ADAPT_DLG         341\n#define IDI_ICON1                       343\n#define IDI_PLUGIN_DISABLED             343\n#define IDD_WIN11_TASKBAR_SETTING_DLG   344\n#define IDR_LANGUAGE                    346\n#define IDR_LANGUAGE_DEFAULT            347\n#define IDR_DISPLAY_ITEM_CONTEXT_MENU   348\n#define IDS_PLUGIN_DETAILS              388\n#define IDC_STATIC_INFO                 1001\n#define IDC_STATIC1                     1002\n#define IDC_STATIC_DOWN                 1002\n#define IDC_PIXELS_STATIC1              1002\n#define IDC_STATIC_UP                   1003\n#define IDC_STATIC2                     1003\n#define IDC_STATIC_DOWN1                1003\n#define IDC_STATIC_MEMORY               1004\n#define IDC_STATIC3                     1004\n#define IDC_STATIC_CPU                  1005\n#define IDC_STATIC4                     1005\n#define IDC_STATIC_UP1                  1006\n#define IDC_STATIC_VERSION              1007\n#define IDC_COMBO1                      1008\n#define IDC_STATIC_SKIN_S               1009\n#define IDC_STATIC_SKIN_L               1010\n#define IDC_STATIC_TEXT2                1012\n#define IDC_SKIN_INFO                   1013\n#define IDC_STATIC_ABOUT                1015\n#define IDC_STATIC_MAIL                 1016\n#define IDC_LIST1                       1017\n#define IDC_INFO_LIST                   1017\n#define IDC_INFO_LIST1                  1017\n#define IDC_HISTORY_INFO_LIST           1017\n#define IDC_STATIC_LICENSE              1017\n#define IDC_DONATE_PIC                  1018\n#define IDC_FONT_NAME_EDIT              1019\n#define IDC_FONT_SIZE_EDIT              1020\n#define IDC_STATIC_CHECK_UPDATE         1021\n#define IDC_SET_FONT_BUTTON             1021\n#define IDC_STATIC_DONATE               1022\n#define IDC_TEXT_COLOR_STATIC           1022\n#define IDC_UPLOAD_EDIT                 1023\n#define IDC_RESOTRE_SKIN_DEFAULT_BUTTON 1023\n#define IDC_DOWNLOAD_EDIT               1024\n#define IDC_CPU_EDIT                    1025\n#define IDC_MEMORY_EDIT                 1026\n#define IDC_FONT_NAME_EDIT1             1027\n#define IDC_FONT_SIZE_EDIT1             1028\n#define IDC_SET_FONT_BUTTON1            1029\n#define IDC_TEXT_COLOR_STATIC1          1030\n#define IDC_UPLOAD_EDIT1                1031\n#define IDC_DOWNLOAD_EDIT1              1032\n#define IDC_CPU_EDIT1                   1033\n#define IDC_MEMORY_EDIT1                1034\n#define IDC_TEXT_COLOR_STATIC2          1035\n#define IDC_TAB1                        1035\n#define IDC_SET_DEFAULT_BUTTON          1036\n#define IDC_TEXT_COLOR_STATIC3          1036\n#define IDC_SET_COLOR_BUTTON2           1037\n#define IDC_TRANSPARENT_COLOR_STATIC    1037\n#define IDC_SET_COLOR_BUTTON1           1038\n#define IDC_SET_COLOR_BUTTON3           1038\n#define IDC_SWITCH_UP_DOWN_CHECK        1039\n#define IDC_SWITCH_UP_DOWN_CHECK1       1040\n#define IDC_SET_DEFAULT_BUTTON1         1041\n#define IDC_FULLSCREEN_HIDE_CHECK       1042\n#define IDC_SWITCH_UP_DOWN_CHECK2       1042\n#define IDC_SPEED_SHORT_MODE_CHECK      1042\n#define IDC_STATIC_GITHUB               1043\n#define IDC_SPEED_SHORT_MODE_CHECK2     1043\n#define IDC_SET_LIGHT_MODE_BUTTON       1043\n#define IDC_CHECK_UPDATE_CHECK          1044\n#define IDC_STATIC_GITEE                1044\n#define IDC_CHECK_NOW_BUTTON            1045\n#define IDC_AUTO_RUN_CHECK              1046\n#define IDC_TASKBAR_WND_ON_LEFT_CHECK   1047\n#define IDC_HIDE_UNIT_CHECK             1049\n#define IDC_UNIT_COMBO                  1050\n#define IDC_ICON_PREVIEW                1051\n#define IDC_HIDE_PERCENTAGE_CHECK       1051\n#define IDC_SKIN_COURSE_STATIC          1052\n#define IDC_SKIN_COURSE_STATIC2         1053\n#define IDC_SKIN_DOWNLOAD_STATIC        1053\n#define IDC_PREVIEW_GROUP_STATIC        1054\n#define IDC_NOTIFY_STATIC               1056\n#define IDC_ALLOW_SKIN_FONT_CHECK       1057\n#define IDC_CHECK2                      1058\n#define IDC_ALLOW_SKIN_DISP_STR_CHECK   1058\n#define IDC_VALUE_RIGHT_ALIGN_CHECK     1058\n#define IDC_ALWAYS_ON_TOP_CHECK         1058\n#define IDC_UP_STATIC                   1059\n#define IDC_DOWN_STATIC                 1060\n#define IDC_UP_VALUE_STATIC             1060\n#define IDC_CPU_STATIC                  1061\n#define IDC_DWON_LABLE_STATIC           1061\n#define IDC_MEMORY_STATIC               1062\n#define IDC_DWON_VALUE_STATIC           1062\n#define IDC_SPECIFY_EACH_ITEM_COLOR_CHECK 1063\n#define IDC_CPU_LABLE_STATIC            1063\n#define IDC_CPU_TEMP_STATIC             1063\n#define IDC_CPU_VALUE_STATIC            1064\n#define IDC_GPU_TEMP_STATIC             1064\n#define IDC_MEMORY_LABLE_STATIC         1065\n#define IDC_HDD_TEMP_STATIC             1065\n#define IDC_UP_STATIC8                  1066\n#define IDC_MEMORY_VALUE_STATIC         1066\n#define IDC_MEMORY_STATIC2              1066\n#define IDC_MBD_TEMP_STATIC             1066\n#define IDC_UP_LABLE_STATIC             1067\n#define IDC_DOUBLE_CLICK_COMBO          1068\n#define IDC_TODAY_TRAFFIC_TIP_CHECK     1069\n#define IDC_TODAY_TRAFFIC_TIP_EDIT      1070\n#define IDC_MEMORY_USAGE_TIP_CHECK      1071\n#define IDC_MEMORY_USAGE_TIP_EDIT       1072\n#define IDC_TODAY_TRAFFIC_TIP_COMBO     1073\n#define IDC_STATIC_COPYRIGHT            1074\n#define IDC_LANGUAGE_COMBO              1075\n#define IDC_CPU_TEMP_LABLE_STATIC       1076\n#define IDC_YEAR_COMBO                  1077\n#define IDC_CPU_TEMP_VALUE_STATIC       1077\n#define IDC_GPU_TEMP_TIP_CHECK          1077\n#define IDC_MONTH_COMBO                 1078\n#define IDC_GPU_TEMP_LABLE_STATIC       1078\n#define IDC_PREVIOUS_BUTTON             1079\n#define IDC_GPU_TEMP_VALUE_STATIC       1079\n#define IDC_NEXT_BUTTON                 1080\n#define IDC_OPEN_CONFIG_PATH_BUTTON     1080\n#define IDC_HDD_TEMP_LABLE_STATIC       1080\n#define IDC_DIGIT_NUMBER_COMBO          1081\n#define IDC_HDD_TEMP_VALUE_STATIC       1081\n#define IDC_HORIZONTAL_ARRANGE_CHECK    1082\n#define IDC_MAIN_BOARD_TEMP_LABLE_STATIC 1082\n#define IDC_MBD_TEMP_TIP_CHECK          1082\n#define IDC_PREVIEW_BUTTON              1083\n#define IDC_MAIN_BOARD_TEMP_VALUE_STATIC 1083\n#define IDC_INDEX_STATIC                1084\n#define IDC_STATIC_ACKNOWLEDGEMENT      1085\n#define IDC_TRADITIONAL_CHINESE_TRANSLATOR_STATIC 1086\n#define IDC_TRANSLATOR_STATIC           1087\n#define IDC_SEPARATE_VALUE_UNIT_CHECK   1089\n#define IDC_SHOW_STATUS_BAR_CHECK       1090\n#define IDC_UNIT_BYTE_RADIO             1091\n#define IDC_UNIT_BIT_RADIO              1092\n#define IDC_SHOW_ALL_CONNECTION_CHECK   1092\n#define IDC_SAVE_TO_APPDATA_RADIO       1093\n#define IDC_SAVE_TO_PROGRAM_DIR_RADIO   1094\n#define IDC_HELP_EDIT                   1095\n#define IDC_INFO_STATIC                 1096\n#define IDC_SHOW_TOOL_TIP_CHK           1097\n#define IDC_DEFAULT_STYLE_BUTTON        1098\n#define IDC_BROWSE_BUTTON               1100\n#define IDC_EXE_PATH_EDIT               1101\n#define IDC_EXE_PATH_STATIC             1102\n#define IDC_CM_GRAPH_BAR_RADIO          1104\n#define IDC_CM_GRAPH_PLOT_RADIO         1105\n#define IDC_USE_CPU_TIME_RADIO          1106\n#define IDC_USE_PDH_RADIO               1107\n#define IDC_BACKGROUND_TRANSPARENT_CHECK 1108\n#define IDC_USE_HARDWARE_MONITOR_RADIO  1108\n#define IDC_AUTO_ADAPT_LIGHT_THEME_CHECK 1109\n#define IDC_AUTO_ADAPT_SETTINGS_BUTTON  1110\n#define IDC_DARK_MODE_DEFAULT_STYLE_COMBO 1111\n#define IDC_LIGHT_MODE_DEFAULT_STYLE_COMBO 1112\n#define IDC_MENU_BUTTON                 1112\n#define IDC_AUTO_ADAPT_CHECK            1113\n#define IDC_MONITOR_SPAN_EDIT           1114\n#define IDC_VIEW_TYPE_COMBO             1115\n#define IDC_VIEW_SCALE_COMBO            1116\n#define IDC_HDD_TEMP_TIP_CHECK          1117\n#define IDC_AUTO_SET_BACK_COLOR_CHECK   1117\n#define IDC_RESTORE_DEFAULT_BUTTON      1118\n#define IDC_DISPLAY_TEXT_SETTING_BUTTON 1119\n#define IDC_CPU_TEMP_TIP_CHECK          1120\n#define IDC_OPENHARDWAREMONITOR_LINK    1122\n#define IDC_TINYXML2_LINK               1123\n#define IDC_MUSICPLAYER2_LINK           1124\n#define IDC_SIMPLENOTEPAD_LINK          1125\n#define IDC_GITHUB_RADIO                1126\n#define IDC_GITEE_RADIO                 1127\n#define IDC_MEMORY_DISPLAY_COMBO        1127\n#define IDC_RESTORE_DEFAULT_TIME_SPAN_BUTTON 1128\n#define IDC_SELECT_HARD_DISK_COMBO      1129\n#define IDC_CPU_CHECK                   1130\n#define IDC_GPU_CHECK                   1131\n#define IDC_SHOW_DASHED_BOX             1131\n#define IDC_HDD_CHECK                   1132\n#define IDC_MBD_CHECK                   1133\n#define IDC_MOUSE_PENETRATE_CHECK       1133\n#define IDC_SELECT_CPU_COMBO            1134\n#define IDC_LOCK_WINDOW_POS_CHECK       1134\n#define IDC_ALOW_OUT_OF_BORDER_CHECK    1135\n#define IDC_MOVE_UP_BUTTON              1136\n#define IDC_MOVE_DOWN_BUTTON            1137\n#define IDC_SET_ORDER_BUTTON            1137\n#define IDC_OPTINS_BUTTON               1139\n#define IDC_PLUGIN_MANAGE_BUTTON        1140\n#define IDC_PLUGIN_INFO_BUTTON          1141\n#define IDC_SHOW_NOTIFY_ICON_CHECK      1142\n#define IDC_HDD_STATIC                  1143\n#define IDC_HARDWARE_MONITOR_STATIC     1144\n#define IDC_SELECT_HDD_STATIC           1145\n#define IDC_SELECT_CPU_STATIC           1146\n#define IDC_APPLY_BUTTON                1147\n#define IDC_TASKBAR_WND_SNAP_CHECK      1148\n#define IDC_ITEM_SPACE_EDIT             1149\n#define IDC_EXIT_INST_BUTTON            1150\n#define IDC_OPEN_SETTINGS_BUTTON        1151\n#define IDC_SHOW_HIDE_MAIN_WINDOW_BUTTON 1152\n#define IDC_SHOW_HIDE_TASKBAR_WINDOW_BUTTON 1153\n#define IDC_PLUGIN_DEV_GUID_STATIC      1153\n#define IDC_PLUGIN_DOWNLOAD_STATIC      1154\n#define IDC_SELECT_CONNECTIONS_BUTTON   1155\n#define IDC_AUTO_SAVE_TO_PRESET_CHECK   1156\n#define IDC_SHOW_NET_SPEED_FIGURE_CHECK 1157\n#define IDC_NET_SPEED_FIGURE_MAX_VALUE_EDIT 1158\n#define IDC_NET_SPEED_FIGURE_MAX_VALUE_UNIT_COMBO 1159\n#define IDC_OPEN_PLUGIN_DIR_STATIC      1160\n#define IDC_OPEN_SKIN_DIR_STATIC        1161\n#define IDC_RESET_AUTO_RUN_BUTTON       1162\n#define IDC_WINDOW_OFFSET_TOP_NEGATIVE_CHECK 1166\n#define IDC_WINDOW_OFFSET_TOP_EDIT      1167\n#define IDC_VERTICAL_MARGIN_EDIT        1168\n#define IDC_WIDTET_WIDTH_EDIT           1168\n#define IDC_VERTICAL_MARGIN_NEGATIVE_CHECK 1169\n#define IDC_WINDOW_OFFSET_TOP_EDIT2     1169\n#define IDC_WINDOW_OFFSET_LEFT_EDIT     1169\n#define IDC_DISABLE_D2D                 1170\n#define IDC_GDI_RADIO                   1171\n#define IDC_D2D_RADIO                   1172\n#define IDC_SKIN_AUTO_ADAPT_CHECK       1173\n#define IDC_SKIN_AUTO_ADAPT_BUTTON      1174\n#define IDC_DARK_MODE_SKIN_COMBO        1175\n#define IDC_LIGHT_MODE_SKIN_COMBO       1176\n#define IDC_ENABLE_COLOR_EMOJI_CHECK    1177\n#define IDC_WIN11_SETTINGS_BUTTON       1178\n#define IDC_AVOID_OVERLAP_RIGHT_WIDGETS_CHECK 1179\n#define IDC_CHECK1                      1181\n#define IDC_TASKBAR_WND_IN_SECONDARY_DISPLAY_CHECK 1181\n#define IDC_MEMORY_USAGE_BACK_STATIC    1182\n#define IDC_TODAY_TRAFFIC_BACK_STATIC   1183\n#define IDC_UPDATE_SORUCE_STATIC        1184\n#define IDC_LANGUAGE_STATIC             1185\n#define IDC_DOUBLE_CLICK_ACTION_STATIC  1186\n#define IDC_MEMORY_DISPLAY_MODE_STATIC  1187\n#define IDC_TXT_COLOR_STATIC            1188\n#define IDC_BACK_COLOR_STATIC           1189\n#define IDC_MONITOR_INTERVAL_STATIC     1190\n#define IDC_MILLISECONDS_STATIC         1191\n#define IDC_NET_SPEED_WIDTH_STATIC      1192\n#define IDC_CHARACTOR_STATIC            1193\n#define IDC_ITEM_SPACING_STATIC         1194\n#define IDC_PIXELS_STATIC               1195\n#define IDC_VERTICAL_MARGIN_STATIC      1196\n#define TXT_MEMORY_DISPLAY_MODE         1197\n#define IDC_TXT_COLOR_LABEL_STATIC      1198\n#define IDC_NET_SPEED_MAX_VALUE_STATIC  1199\n#define IDC_USAGE_GRAPH_COLOR_STATIC    1200\n#define IDC_GRAPH_DISPLAY_MODE_STATIC   1201\n#define IDC_DARK_MODE_STATIC            1202\n#define IDC_LIGHT_MODE_STATIC           1203\n#define IDC_FONT_STATIC                 1204\n#define IDC_FONT_SIZE_STATIC            1205\n#define IDC_SELECT_ICON_STATIC          1206\n#define IDC_VERTICAL_OFFSET_STATIC      1207\n#define IDC_HORIZONTAL_OFFSET_STATIC    1208\n#define IDC_PIXEL_STATIC                1209\n#define IDC_PIXEL_STATIC1               1210\n#define IDC_WIDGET_WIDTH_STATIC         1211\n#define IDC_PIXEL_STATIC2               1212\n#define IDC_DISPLAY_TO_SHOW_TASKBAR_WND_COMBO 1213\n#define IDC_DISPLAY_TO_SHOW_TASKBAR_WND_STATIC 1214\n#define IDC_USAGE_GRAPH_FOLLOW_SYSTEM_CHECK 1215\n#define IDC_CPU_TEMP_TIP_EDIT           1216\n#define IDC_GPU_TEMP_TIP_EDIT           1217\n#define IDC_HDD_TIP_EDIT                1218\n#define IDC_MBD_TEMP_TIP_EDIT           1219\n#define ID_32771                        32771\n#define ID_NETWORK_INFO                 32772\n#define ID_32773                        32773\n#define ID_ALWAYS_ON_TOP                32774\n#define ID_32775                        32775\n#define ID_32776                        32776\n#define ID_32777                        32777\n#define ID_32778                        32778\n#define ID_32779                        32779\n#define ID_TRANS_100                    32780\n#define ID_TRANSPARENCY_100             32781\n#define ID_TRANSPARENCY_80              32782\n#define ID_TRANSPARENCY_60              32783\n#define ID_TRANSPARENCY_40              32784\n#define ID_32785                        32785\n#define ID_32786                        32786\n#define ID_32789                        32789\n#define ID_LOCK_WINDOW_POS              32790\n#define ID_32791                        32791\n#define ID_SHOW_NOTIFY_ICON             32792\n#define ID_32793                        32793\n#define ID_SHOW_CPU_MEMORY              32794\n#define ID_32795                        32795\n#define ID_MOUSE_PENETRATE              32796\n#define ID_32797                        32797\n#define ID_32798                        32798\n#define ID_TEXT_COLOR                   32799\n#define ID_32800                        32800\n#define ID_SHOW_TASK_BAR_WND            32801\n#define ID_32802                        32802\n#define ID_32803                        32803\n#define ID_32804                        32804\n#define ID_32805                        32805\n#define ID_32806                        32806\n#define ID_SET_BACK_COLOR               32807\n#define ID_32808                        32808\n#define ID_SET_TEXT_COLOR               32809\n#define ID_32810                        32810\n#define ID_SHOW_CPU_MEMORY2             32811\n#define ID_32812                        32812\n#define ID_MINMIZE                      32813\n#define ID_32814                        32814\n#define ID_AUTO_RUN_WHEN_START          32815\n#define ID_HIDE_MAIN_WND                32816\n#define ID_32817                        32817\n#define ID_32818                        32818\n#define ID_CHANGE_SKIN                  32819\n#define ID_32820                        32820\n#define ID_SET_FONT                     32821\n#define ID_32822                        32822\n#define ID_SET_                         32823\n#define ID_SET_FONT2                    32824\n#define ID_32825                        32825\n#define ID_TRAFFIC_HISTORY              32826\n#define ID_32827                        32827\n#define ID_32828                        32828\n#define ID_OPTIONS                      32829\n#define ID_32830                        32830\n#define ID_OPTIONS2                     32831\n#define ID_32832                        32832\n#define ID_COPY_TEXT                    32833\n#define ID_32834                        32834\n#define ID_32835                        32835\n#define ID_USE_LINEAR_SCALE             32836\n#define ID_USE_LOG_SCALE                32837\n#define ID_32838                        32838\n#define ID_CHANGE_NOTIFY_ICON           32839\n#define ID_32840                        32840\n#define ID_ALOW_OUT_OF_BORDER           32841\n#define ID_32842                        32842\n#define ID_32843                        32843\n#define ID_32844                        32844\n#define ID_32845                        32845\n#define ID_CHECK_UPDATE                 32846\n#define ID_SHOW_MAIN_WND                32847\n#define ID_DEFAULT_STYLE1               32848\n#define ID_DEFAULT_STYLE_MAX            32857\n#define ID_MODIFY_DEFAULT_STYLE1        32858\n#define ID_MODIFY_DEFAULT_STYLE_MAX     32867\n#define ID_LIGHT_MODE_STYLE             32868\n#define ID_SHOW_NET_SPEED               32869\n#define ID_FIRST_DAY_OF_WEEK_SUNDAY     32870\n#define ID_FIRST_DAY_OF_WEEK_MONDAY     32871\n#define ID_CALENDAR_JUMP_TO_TODAY       32872\n#define ID_FREQUENTY_ASKED_QUESTIONS    32873\n#define ID_CMD_TEST                     32874\n#define ID_SHOW_UP_SPEED                32875\n#define ID_SHOW_DOWN_SPEED              32876\n#define ID_SHOW_CPU_USAGE               32877\n#define ID_SHOW_MEMORY_USAGE            32878\n#define ID_SHOW_CPU_TEMPERATURE         32879\n#define ID_SHOW_GPU_TEMPERATURE         32880\n#define ID_SHOW_HDD_TEMPERATURE         32881\n#define ID_SHOW_MAIN_BOARD_TEMPERATURE  32882\n#define ID_SHOW_GPU                     32883\n#define ID_SHOW_HDD                     32884\n#define ID_UPDATE_LOG                   32885\n#define ID_PLUGIN_MANAGE                32886\n#define ID_SHOW_PLUGIN_ITEM_START       32887\n#define ID_SHOW_PLUGIN_ITEM_MAX         33140\n#define ID_SELETE_CONNECTION            33141\n#define ID_SELECT_ALL_CONNECTION        33142\n#define ID_SELETE_CONNECTION_MAX        33398\n#define ID_PLUGIN_DETAIL                33399\n#define ID_PLUGIN_OPTIONS               33400\n#define ID_PLUGIN_DISABLE               33401\n#define ID_SHOW_TOTAL_SPEED             33402\n#define ID_OPEN_TASK_MANAGER            33403\n#define ID_REFRESH_CONNECTION_LIST      33404\n#define ID_DISPLAY_SETTINGS             33405\n#define ID_PLUGIN_DETAIL_TASKBAR        33406\n#define ID_PLUGIN_OPTIONS_TASKBAR       33407\n#define ID_PLUGIN_COMMAND_START         33408\n#define ID_PLUGIN_COMMAND_MAX           33664\n#define ID_RESTORE_DEFAULT              33665\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        349\n#define _APS_NEXT_COMMAND_VALUE         33666\n#define _APS_NEXT_CONTROL_VALUE         1220\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "TrafficMonitor/skins/0默认皮肤/skin.ini",
    "content": "[skin]\ntext_color=16384\nspecify_each_item_color=0\nskin_author=\"zy\"\n[layout]\ntext_height=20\nno_text=0\npreview_width=250\npreview_height=128\nwidth_l=232\nheight_l=55\nup_x_l=12\nup_y_l=8\nup_width_l=108\nup_align_l=0\ndown_x_l=120\ndown_y_l=8\ndown_width_l=110\ndown_align_l=0\ncpu_x_l=12\ncpu_y_l=28\ncpu_width_l=108\ncpu_align_l=0\nmemory_x_l=120\nmemory_y_l=28\nmemory_width_l=110\nmemory_align_l=0\nshow_up_l=1\nshow_down_l=1\nshow_cpu_l=1\nshow_memory_l=1\npreview_x_l=0\npreview_y_l=59\nwidth_s=232\nheight_s=40\nup_x_s=12\nup_y_s=10\nup_width_s=108\nup_align_s=0\ndown_x_s=120\ndown_y_s=10\ndown_width_s=110\ndown_align_s=0\ncpu_x_s=0\ncpu_y_s=0\ncpu_width_s=0\ncpu_align_s=0\nmemory_x_s=0\nmemory_y_s=0\nmemory_width_s=0\nmemory_align_s=0\nshow_up_s=1\nshow_down_s=1\nshow_cpu_s=0\nshow_memory_s=0\npreview_x_s=0\npreview_y_s=0\n"
  },
  {
    "path": "TrafficMonitor/skins/xml_test/skin.xml",
    "content": "﻿<root>\n\t<skin>\n\t\t<text_color>16768959,10022341,16777215,16777215,16777215,16770992,16770992,16770992,16770992</text_color>\n\t\t<specify_each_item_color>1</specify_each_item_color>\n\t\t<skin_author>zy</skin_author>\n\t\t<font name=\"Microsoft YaHei\" size=\"9\" style=\"0\"/>\n\t\t<display_text>\n\t\t\t<up>上传: </up>\n\t\t\t<down>下载: </down>\n\t\t\t<cpu>CPU: </cpu>\n\t\t\t<memory>内存: </memory>\n\t\t\t<gpu>显卡: </gpu>\n\t\t\t<cpu_temperature>CPU温度: </cpu_temperature>\n\t\t\t<gpu_temperature>显卡温度: </gpu_temperature>\n\t\t\t<total_speed>↑↓: </total_speed>\n\t\t</display_text>\n\t</skin>\n\t<plugin_map>\n\t\t<time>ra1YX2g1</time>\n\t\t<cosutom_item>b4zc373y</cosutom_item>\n\t\t<battery>b5R30ITQ</battery>\n\t\t<weather>NdKZEf39</weather>\n\t\t<text_reader>W5XuBvH0</text_reader>\n\t</plugin_map>\n\t<layout text_height=\"20\" no_label=\"0\">\n\t\t<layout_l width=\"232\" height=\"107\">\n\t\t\t<cpu x=\"14\" y=\"3\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<memory x=\"88\" y=\"3\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<battery x=\"162\" y=\"3\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<up x=\"14\" y=\"27\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<down x=\"122\" y=\"27\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<total_speed x=\"32\" y=\"57\" width=\"94\" align=\"0\" show=\"1\"/>\n      <weather x=\"32\" y=\"83\" width=\"94\" align=\"0\" show=\"1\"/>\n\t\t\t<time x=\"142\" y=\"57\" width=\"94\" align=\"0\" show=\"1\"/>\n      <text_reader x=\"142\" y=\"83\" width=\"94\" align=\"0\" show=\"1\"/>\n\t\t</layout_l>\n\t\t<layout_s width=\"232\" height=\"50\">\n\t\t\t<cpu x=\"14\" y=\"3\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<memory x=\"88\" y=\"3\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<battery x=\"162\" y=\"3\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<up x=\"14\" y=\"27\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t\t<down x=\"122\" y=\"27\" width=\"106\" align=\"0\" show=\"1\"/>\n\t\t</layout_s>\n\n\t</layout>\n\t<preview width=\"250\" height=\"170\">\n\t\t<l x=\"0\" y=\"0\"/>\n\t\t<s x=\"0\" y=\"112\"/>\n\t</preview>\n</root>\n"
  },
  {
    "path": "TrafficMonitor/skins/皮肤01/skin.ini",
    "content": "[skin]\ntext_color=3803808\nspecify_each_item_color=0\nskin_author=\"zy\"\n[layout]\ntext_height=20\nno_text=0\npreview_width=250\npreview_height=128\nwidth_l=232\nheight_l=55\nup_x_l=12\nup_y_l=8\nup_width_l=108\nup_align_l=0\ndown_x_l=120\ndown_y_l=8\ndown_width_l=110\ndown_align_l=0\ncpu_x_l=12\ncpu_y_l=28\ncpu_width_l=108\ncpu_align_l=0\nmemory_x_l=120\nmemory_y_l=28\nmemory_width_l=110\nmemory_align_l=0\nshow_up_l=1\nshow_down_l=1\nshow_cpu_l=1\nshow_memory_l=1\npreview_x_l=0\npreview_y_l=59\nwidth_s=232\nheight_s=40\nup_x_s=12\nup_y_s=10\nup_width_s=108\nup_align_s=0\ndown_x_s=120\ndown_y_s=10\ndown_width_s=110\ndown_align_s=0\ncpu_x_s=0\ncpu_y_s=0\ncpu_width_s=0\ncpu_align_s=0\nmemory_x_s=0\nmemory_y_s=0\nmemory_width_s=0\nmemory_align_s=0\nshow_up_s=1\nshow_down_s=1\nshow_cpu_s=0\nshow_memory_s=0\npreview_x_s=0\npreview_y_s=0\n"
  },
  {
    "path": "TrafficMonitor/skins/皮肤02/skin.ini",
    "content": "[skin]\ntext_color=9844741\nspecify_each_item_color=0\nskin_author=\"zy\"\n[layout]\ntext_height=20\nno_text=0\npreview_width=250\npreview_height=128\nwidth_l=232\nheight_l=55\nup_x_l=12\nup_y_l=8\nup_width_l=108\nup_align_l=0\ndown_x_l=120\ndown_y_l=8\ndown_width_l=110\ndown_align_l=0\ncpu_x_l=12\ncpu_y_l=28\ncpu_width_l=108\ncpu_align_l=0\nmemory_x_l=120\nmemory_y_l=28\nmemory_width_l=110\nmemory_align_l=0\nshow_up_l=1\nshow_down_l=1\nshow_cpu_l=1\nshow_memory_l=1\npreview_x_l=0\npreview_y_l=59\nwidth_s=232\nheight_s=40\nup_x_s=12\nup_y_s=10\nup_width_s=108\nup_align_s=0\ndown_x_s=120\ndown_y_s=10\ndown_width_s=110\ndown_align_s=0\ncpu_x_s=0\ncpu_y_s=0\ncpu_width_s=0\ncpu_align_s=0\nmemory_x_s=0\nmemory_y_s=0\nmemory_width_s=0\nmemory_align_s=0\nshow_up_s=1\nshow_down_s=1\nshow_cpu_s=0\nshow_memory_s=0\npreview_x_s=0\npreview_y_s=0\n"
  },
  {
    "path": "TrafficMonitor/skins/皮肤03/skin.ini",
    "content": "[skin]\ntext_color=16777215\nskin_author=zy"
  },
  {
    "path": "TrafficMonitor/skins/皮肤04/skin.ini",
    "content": "[skin]\ntext_color=16777215\nskin_author=zy"
  },
  {
    "path": "TrafficMonitor/skins/皮肤05/skin.ini",
    "content": "[skin]\ntext_color=335674\nskin_author=zy"
  },
  {
    "path": "TrafficMonitor/skins/皮肤06/skin.ini",
    "content": "[skin]\ntext_color=16773870\nskin_author=zy"
  },
  {
    "path": "TrafficMonitor/skins/皮肤07/skin.ini",
    "content": "[skin]\ntext_color=14547455\nskin_author=zy"
  },
  {
    "path": "TrafficMonitor/skins/皮肤08/skin.ini",
    "content": "[skin]\ntext_color=16763528\nskin_author=zy"
  },
  {
    "path": "TrafficMonitor/skins/皮肤09/skin.ini",
    "content": "[skin]\ntext_color=16384\nskin_author=zy"
  },
  {
    "path": "TrafficMonitor/skins/皮肤10/skin.ini",
    "content": "[skin]\ntext_color=9586944\nskin_author=\"zy\"\n[layout]\ntext_height=20\nno_text=1\npreview_width=238\npreview_height=110\nwidth_l=189\nheight_l=43\nup_x_l=24\nup_y_l=2\nup_width_l=73\nup_align_l=0\ndown_x_l=116\ndown_y_l=2\ndown_width_l=73\ndown_align_l=0\ncpu_x_l=24\ncpu_y_l=21\ncpu_width_l=73\ncpu_align_l=0\nmemory_x_l=116\nmemory_y_l=21\nmemory_width_l=73\nmemory_align_l=0\nshow_up_l=1\nshow_down_l=1\nshow_cpu_l=1\nshow_memory_l=1\npreview_x_l=0\npreview_y_l=47\nwidth_s=189\nheight_s=28\nup_x_s=24\nup_y_s=4\nup_width_s=73\nup_align_s=0\ndown_x_s=116\ndown_y_s=4\ndown_width_s=73\ndown_align_s=0\ncpu_x_s=0\ncpu_y_s=0\ncpu_width_s=0\ncpu_align_s=0\nmemory_x_s=0\nmemory_y_s=0\nmemory_width_s=0\nmemory_align_s=0\nshow_up_s=1\nshow_down_s=1\nshow_cpu_s=0\nshow_memory_s=0\npreview_x_s=0\npreview_y_s=0\n"
  },
  {
    "path": "TrafficMonitor/skins/皮肤10（竖排）/skin.ini",
    "content": "[skin]\ntext_color=9586944\nskin_author=\"zy\"\n[layout]\ntext_height=20\nno_text=1\npreview_width=238\npreview_height=79\nwidth_l=110\nheight_l=63\nup_x_l=24\nup_y_l=2\nup_width_l=85\ndown_x_l=24\ndown_y_l=21\ndown_width_l=85\ncpu_x_l=24\ncpu_y_l=40\ncpu_width_l=34\nmemory_x_l=76\nmemory_y_l=40\nmemory_width_l=33\nshow_up_l=1\nshow_down_l=1\nshow_cpu_l=1\nshow_memory_l=1\npreview_x_l=115\npreview_y_l=0\nwidth_s=100\nheight_s=43\nup_x_s=24\nup_y_s=2\nup_width_s=76\ndown_x_s=24\ndown_y_s=20\ndown_width_s=76\ncpu_x_s=0\ncpu_y_s=0\ncpu_width_s=0\nmemory_x_s=0\nmemory_y_s=0\nmemory_width_s=0\nshow_up_s=1\nshow_down_s=1\nshow_cpu_s=0\nshow_memory_s=0\npreview_x_s=0\npreview_y_s=0\n"
  },
  {
    "path": "TrafficMonitor/skins/皮肤11/skin.ini",
    "content": "[skin]\ntext_color=16777215,0,0,0,\nspecify_each_item_color=0\nskin_author=\"zy\"\nfont_name=\"Segoe UI Semibold\"\nfont_size=10\nfont_style=0\n[layout]\ntext_height=20\nno_text=1\npreview_width=171\npreview_height=108\nwidth_l=174\nheight_l=41\nup_x_l=16\nup_y_l=1\nup_width_l=69\nup_align_l=1\ndown_x_l=16\ndown_y_l=20\ndown_width_l=69\ndown_align_l=1\ncpu_x_l=90\ncpu_y_l=20\ncpu_width_l=42\ncpu_align_l=2\nmemory_x_l=132\nmemory_y_l=20\nmemory_width_l=42\nmemory_align_l=2\nshow_up_l=1\nshow_down_l=1\nshow_cpu_l=1\nshow_memory_l=1\npreview_x_l=0\npreview_y_l=55\nwidth_s=90\nheight_s=41\nup_x_s=16\nup_y_s=1\nup_width_s=69\nup_align_s=1\ndown_x_s=16\ndown_y_s=20\ndown_width_s=69\ndown_align_s=1\ncpu_x_s=0\ncpu_y_s=0\ncpu_width_s=0\ncpu_align_s=0\nmemory_x_s=0\nmemory_y_s=0\nmemory_width_s=0\nmemory_align_s=0\nshow_up_s=1\nshow_down_s=1\nshow_cpu_s=0\nshow_memory_s=0\npreview_x_s=0\npreview_y_s=0\n"
  },
  {
    "path": "TrafficMonitor/skins/默认皮肤2/skin.ini",
    "content": "[skin]\ntext_color=16384,0,0,0,\nspecify_each_item_color=0\nskin_author=\"zy\"\n[layout]\ntext_height=20\nno_text=0\npreview_width=250\npreview_height=128\nwidth_l=232\nheight_l=55\nup_x_l=12\nup_y_l=8\nup_width_l=108\nup_align_l=0\ndown_x_l=120\ndown_y_l=8\ndown_width_l=110\ndown_align_l=0\ncpu_x_l=12\ncpu_y_l=28\ncpu_width_l=108\ncpu_align_l=0\nmemory_x_l=120\nmemory_y_l=28\nmemory_width_l=110\nmemory_align_l=0\nshow_up_l=1\nshow_down_l=1\nshow_cpu_l=1\nshow_memory_l=1\npreview_x_l=0\npreview_y_l=59\nwidth_s=165\nheight_s=40\nup_x_s=12\nup_y_s=10\nup_width_s=70\nup_align_s=0\ndown_x_s=83\ndown_y_s=10\ndown_width_s=77\ndown_align_s=0\ncpu_x_s=12\ncpu_y_s=10\ncpu_width_s=70\ncpu_align_s=0\nmemory_x_s=83\nmemory_y_s=10\nmemory_width_s=77\nmemory_align_s=0\nshow_up_s=0\nshow_down_s=0\nshow_cpu_s=1\nshow_memory_s=1\npreview_x_s=0\npreview_y_s=0\n"
  },
  {
    "path": "TrafficMonitor/stdafx.cpp",
    "content": "\n// stdafx.cpp : ֻ׼ļԴļ\n// TrafficMonitor.pch ΪԤͷ\n// stdafx.obj ԤϢ\n\n#include \"stdafx.h\"\n\n\n"
  },
  {
    "path": "TrafficMonitor/stdafx.h",
    "content": "﻿\n// stdafx.h : 标准系统包含文件的包含文件，\n// 或是经常使用但不常更改的\n// 特定于项目的包含文件\n\n#pragma once\n\n#ifndef VC_EXTRALEAN\n#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料\n#endif\n\n#include \"targetver.h\"\n\n#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的\n\n// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏\n#define _AFX_ALL_WARNINGS\n\n#include <afxwin.h>         // MFC 核心组件和标准组件\n#include <afxext.h>         // MFC 扩展\n\n\n#include <afxdisp.h>        // MFC 自动化类\n\n\n\n#ifndef _AFX_NO_OLE_SUPPORT\n#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持\n#endif\n#ifndef _AFX_NO_AFXCMN_SUPPORT\n#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持\n#endif // _AFX_NO_AFXCMN_SUPPORT\n\n#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持\n\n#include \"resource.h\"\n#include <string>\nusing std::string;\nusing std::wstring;\n#include <vector>\nusing std::vector;\n#include <deque>\nusing std::deque;\n#include<iostream>\n#include<fstream>\nusing std::ifstream;\nusing std::ofstream;\n#include <map>\n#include <set>\n#include<io.h>\n#include<algorithm>\n#include <cmath>\n#include <afxinet.h>    //用于支持使用网络相关的类\n#include <afxwin.h>\n\n#include \"language.h\"\n\n#ifdef _UNICODE\n#if defined _M_IX86\n#pragma comment(linker,\"/manifestdependency:\\\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\\\"\")\n#elif defined _M_X64\n#pragma comment(linker,\"/manifestdependency:\\\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\\\"\")\n#else\n#pragma comment(linker,\"/manifestdependency:\\\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\\\"\")\n#endif\n#endif\n\n\n#define MY_WM_NOTIFYICON (WM_USER+1005)\n#define WM_TASKBAR_WND_CLOSED (WM_USER+1006)        //任务栏窗口关闭时发送此消息\n#define WM_MONITOR_INFO_UPDATED (WM_USER+1007)        //监控信息已更新\n#define WM_REOPEN_TASKBAR_WND (WM_USER+1008)        //重新打开任务栏窗口\n#define WM_SETTINGS_APPLIED (WM_USER+1009)          //在选项设置中点击了“应用”按钮\n\n#define WM_NEXT_USER_MSG (WM_USER+1011)\n\n//#define CONFIG_PATH _T(\".\\\\config.ini\")\n//#define CONFIG_PATHA \".\\\\config.ini\"\n//#define LOG_PATH _T(\".\\\\error.log\")\n//#define HISTORY_TRAFFIC_PATH _T(\".\\\\history_traffic.dat\")\n#define MAX_RESTART_CNT 10      //最大重新初始化次数\n\n#define MAIN_TIMER 1234         //主定时器的ID\n#define DELAY_TIMER 1235        //延时定时器ID\n#define TASKBAR_TIMER 1236\n#define CONNECTION_DETAIL_TIMER 1237\n#define MONITOR_TIMER 1238\n#define DELETE_NOTIFY_ICON_TIMER 1239   //删除通知区图标的定时器\n#define RESTART_TASKBAR_TIMER 1240\n#define INIT_CONNECT_TIMER 1241\n#define DPI_CHANGE_TIMER 1242\n\n#define MAX_INSERT_TO_TASKBAR_CNT 200     //尝试嵌入任务栏的最大次数\n#define WARN_INSERT_TO_TASKBAR_CNT 20     //尝试嵌入任务栏的警告次数\n\n#define APP_NAME _T(\"TrafficMonitor\")\n#define TASKBAR_WINDOW_NAME _T(\"TrafficMonitorTaskbarWindow\")\n#define APP_CLASS_NAME _T(\"TrafficMonitor_r7XZaS4p\") //程序主窗口的类名\n#define VERSION L\"1.85.1\"\n\n#define MAX_NOTIFY_ICON 6       //可选的通知区图标数量\n\n//背景图片的文件名\n#define BACKGROUND_IMAGE_S L\"\\\\background.bmp\"\n#define BACKGROUND_IMAGE_L L\"\\\\background_l.bmp\"\n#define BACKGROUND_IMAGE_S_PNG L\"background.png\"\n#define BACKGROUND_IMAGE_L_PNG L\"background_l.png\"\n#define BACKGROUND_MASK_S L\"\\\\background_mask.bmp\"\n#define BACKGROUND_MASK_L L\"\\\\background_mask_l.bmp\"\n\n#define MIN_FONT_SIZE 5\n#define MAX_FONT_SIZE 72\n\n#define SAFE_DELETE(p) do \\\n{\\\n    if(p != nullptr) \\\n    { \\\n        delete p; \\\n        p = nullptr; \\\n    } \\\n} while (false)\n\n//定义两个用于作为任务栏透明色的颜色（当需要设置任务栏窗口不透明时使用）\n#define TASKBAR_TRANSPARENT_COLOR1 RGB(52, 28, 41)\n#define TASKBAR_TRANSPARENT_COLOR2 RGB(38, 67, 55)\n\n//如果需要为Windows XP系统编译，请去掉下面一行代码的注释\n//#define COMPILE_FOR_WINXP\n\n//是否禁用WebExperience检测功能，用于检测Windows11下是否存在“小组件”\n//如果这部分功能导致编译出错，请去掉下面一行代码的注释\n//#define DISABLE_WINDOWS_WEB_EXPERIENCE_DETECTOR\n"
  },
  {
    "path": "TrafficMonitor/targetver.h",
    "content": "#pragma once\n\n//  SDKDDKVer.h õ߰汾 Windows ƽ̨\n\n// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h\n//  _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h\n\n#include <SDKDDKVer.h>\n"
  },
  {
    "path": "TrafficMonitor/tinyxml2/tinyxml2.cpp",
    "content": "﻿/*\nOriginal code by Lee Thomason (www.grinninglizard.com)\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any\ndamages arising from the use of this software.\n\nPermission is granted to anyone to use this software for any\npurpose, including commercial applications, and to alter it and\nredistribute it freely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must\nnot claim that you wrote the original software. If you use this\nsoftware in a product, an acknowledgment in the product documentation\nwould be appreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and\nmust not be misrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source\ndistribution.\n*/\n\n#include \"tinyxml2.h\"\n\n#include <new>\t\t// yes, this one new style header, is in the Android SDK.\n#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)\n#   include <stddef.h>\n#   include <stdarg.h>\n#else\n#   include <cstddef>\n#   include <cstdarg>\n#endif\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)\n\t// Microsoft Visual Studio, version 2005 and higher. Not WinCE.\n\t/*int _snprintf_s(\n\t   char *buffer,\n\t   size_t sizeOfBuffer,\n\t   size_t count,\n\t   const char *format [,\n\t\t  argument] ...\n\t);*/\n\tstatic inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )\n\t{\n\t\tva_list va;\n\t\tva_start( va, format );\n\t\tconst int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );\n\t\tva_end( va );\n\t\treturn result;\n\t}\n\n\tstatic inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va )\n\t{\n\t\tconst int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );\n\t\treturn result;\n\t}\n\n\t#define TIXML_VSCPRINTF\t_vscprintf\n\t#define TIXML_SSCANF\tsscanf_s\n#elif defined _MSC_VER\n\t// Microsoft Visual Studio 2003 and earlier or WinCE\n\t#define TIXML_SNPRINTF\t_snprintf\n\t#define TIXML_VSNPRINTF _vsnprintf\n\t#define TIXML_SSCANF\tsscanf\n\t#if (_MSC_VER < 1400 ) && (!defined WINCE)\n\t\t// Microsoft Visual Studio 2003 and not WinCE.\n\t\t#define TIXML_VSCPRINTF   _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have.\n\t#else\n\t\t// Microsoft Visual Studio 2003 and earlier or WinCE.\n\t\tstatic inline int TIXML_VSCPRINTF( const char* format, va_list va )\n\t\t{\n\t\t\tint len = 512;\n\t\t\tfor (;;) {\n\t\t\t\tlen = len*2;\n\t\t\t\tchar* str = new char[len]();\n\t\t\t\tconst int required = _vsnprintf(str, len, format, va);\n\t\t\t\tdelete[] str;\n\t\t\t\tif ( required != -1 ) {\n\t\t\t\t\tTIXMLASSERT( required >= 0 );\n\t\t\t\t\tlen = required;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tTIXMLASSERT( len >= 0 );\n\t\t\treturn len;\n\t\t}\n\t#endif\n#else\n\t// GCC version 3 and higher\n\t//#warning( \"Using sn* functions.\" )\n\t#define TIXML_SNPRINTF\tsnprintf\n\t#define TIXML_VSNPRINTF\tvsnprintf\n\tstatic inline int TIXML_VSCPRINTF( const char* format, va_list va )\n\t{\n\t\tint len = vsnprintf( 0, 0, format, va );\n\t\tTIXMLASSERT( len >= 0 );\n\t\treturn len;\n\t}\n\t#define TIXML_SSCANF   sscanf\n#endif\n\n#if defined(_WIN64)\n\t#define TIXML_FSEEK _fseeki64\n\t#define TIXML_FTELL _ftelli64\n#elif defined(__APPLE__) || (__FreeBSD__)\n\t#define TIXML_FSEEK fseeko\n\t#define TIXML_FTELL ftello\n#elif defined(__unix__) && defined(__x86_64__)\n\t#define TIXML_FSEEK fseeko64\n\t#define TIXML_FTELL ftello64\n#else\n\t#define TIXML_FSEEK fseek\n\t#define TIXML_FTELL ftell\n#endif\n\n\nstatic const char LINE_FEED\t\t\t\t= static_cast<char>(0x0a);\t\t\t// all line endings are normalized to LF\nstatic const char LF = LINE_FEED;\nstatic const char CARRIAGE_RETURN\t\t= static_cast<char>(0x0d);\t\t\t// CR gets filtered out\nstatic const char CR = CARRIAGE_RETURN;\nstatic const char SINGLE_QUOTE\t\t\t= '\\'';\nstatic const char DOUBLE_QUOTE\t\t\t= '\\\"';\n\n// Bunch of unicode info at:\n//\t\thttp://www.unicode.org/faq/utf_bom.html\n//\tef bb bf (Microsoft \"lead bytes\") - designates UTF-8\n\nstatic const unsigned char TIXML_UTF_LEAD_0 = 0xefU;\nstatic const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;\nstatic const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;\n\nnamespace tinyxml2\n{\n\nstruct Entity {\n    const char* pattern;\n    int length;\n    char value;\n};\n\nstatic const int NUM_ENTITIES = 5;\nstatic const Entity entities[NUM_ENTITIES] = {\n    { \"quot\", 4,\tDOUBLE_QUOTE },\n    { \"amp\", 3,\t\t'&'  },\n    { \"apos\", 4,\tSINGLE_QUOTE },\n    { \"lt\",\t2, \t\t'<'\t },\n    { \"gt\",\t2,\t\t'>'\t }\n};\n\n\nStrPair::~StrPair()\n{\n    Reset();\n}\n\n\nvoid StrPair::TransferTo( StrPair* other )\n{\n    if ( this == other ) {\n        return;\n    }\n    // This in effect implements the assignment operator by \"moving\"\n    // ownership (as in auto_ptr).\n\n    TIXMLASSERT( other != 0 );\n    TIXMLASSERT( other->_flags == 0 );\n    TIXMLASSERT( other->_start == 0 );\n    TIXMLASSERT( other->_end == 0 );\n\n    other->Reset();\n\n    other->_flags = _flags;\n    other->_start = _start;\n    other->_end = _end;\n\n    _flags = 0;\n    _start = 0;\n    _end = 0;\n}\n\n\nvoid StrPair::Reset()\n{\n    if ( _flags & NEEDS_DELETE ) {\n        delete [] _start;\n    }\n    _flags = 0;\n    _start = 0;\n    _end = 0;\n}\n\n\nvoid StrPair::SetStr( const char* str, int flags )\n{\n    TIXMLASSERT( str );\n    Reset();\n    size_t len = strlen( str );\n    TIXMLASSERT( _start == 0 );\n    _start = new char[ len+1 ];\n    memcpy( _start, str, len+1 );\n    _end = _start + len;\n    _flags = flags | NEEDS_DELETE;\n}\n\n\nchar* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr )\n{\n    TIXMLASSERT( p );\n    TIXMLASSERT( endTag && *endTag );\n\tTIXMLASSERT(curLineNumPtr);\n\n    char* start = p;\n    const char  endChar = *endTag;\n    size_t length = strlen( endTag );\n\n    // Inner loop of text parsing.\n    while ( *p ) {\n        if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {\n            Set( start, p, strFlags );\n            return p + length;\n        } else if (*p == '\\n') {\n            ++(*curLineNumPtr);\n        }\n        ++p;\n        TIXMLASSERT( p );\n    }\n    return 0;\n}\n\n\nchar* StrPair::ParseName( char* p )\n{\n    if ( !p || !(*p) ) {\n        return 0;\n    }\n    if ( !XMLUtil::IsNameStartChar( (unsigned char) *p ) ) {\n        return 0;\n    }\n\n    char* const start = p;\n    ++p;\n    while ( *p && XMLUtil::IsNameChar( (unsigned char) *p ) ) {\n        ++p;\n    }\n\n    Set( start, p, 0 );\n    return p;\n}\n\n\nvoid StrPair::CollapseWhitespace()\n{\n    // Adjusting _start would cause undefined behavior on delete[]\n    TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 );\n    // Trim leading space.\n    _start = XMLUtil::SkipWhiteSpace( _start, 0 );\n\n    if ( *_start ) {\n        const char* p = _start;\t// the read pointer\n        char* q = _start;\t// the write pointer\n\n        while( *p ) {\n            if ( XMLUtil::IsWhiteSpace( *p )) {\n                p = XMLUtil::SkipWhiteSpace( p, 0 );\n                if ( *p == 0 ) {\n                    break;    // don't write to q; this trims the trailing space.\n                }\n                *q = ' ';\n                ++q;\n            }\n            *q = *p;\n            ++q;\n            ++p;\n        }\n        *q = 0;\n    }\n}\n\n\nconst char* StrPair::GetStr()\n{\n    TIXMLASSERT( _start );\n    TIXMLASSERT( _end );\n    if ( _flags & NEEDS_FLUSH ) {\n        *_end = 0;\n        _flags ^= NEEDS_FLUSH;\n\n        if ( _flags ) {\n            const char* p = _start;\t// the read pointer\n            char* q = _start;\t// the write pointer\n\n            while( p < _end ) {\n                if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {\n                    // CR-LF pair becomes LF\n                    // CR alone becomes LF\n                    // LF-CR becomes LF\n                    if ( *(p+1) == LF ) {\n                        p += 2;\n                    }\n                    else {\n                        ++p;\n                    }\n                    *q = LF;\n                    ++q;\n                }\n                else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {\n                    if ( *(p+1) == CR ) {\n                        p += 2;\n                    }\n                    else {\n                        ++p;\n                    }\n                    *q = LF;\n                    ++q;\n                }\n                else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {\n                    // Entities handled by tinyXML2:\n                    // - special entities in the entity table [in/out]\n                    // - numeric character reference [in]\n                    //   &#20013; or &#x4e2d;\n\n                    if ( *(p+1) == '#' ) {\n                        const int buflen = 10;\n                        char buf[buflen] = { 0 };\n                        int len = 0;\n                        const char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );\n                        if ( adjusted == 0 ) {\n                            *q = *p;\n                            ++p;\n                            ++q;\n                        }\n                        else {\n                            TIXMLASSERT( 0 <= len && len <= buflen );\n                            TIXMLASSERT( q + len <= adjusted );\n                            p = adjusted;\n                            memcpy( q, buf, len );\n                            q += len;\n                        }\n                    }\n                    else {\n                        bool entityFound = false;\n                        for( int i = 0; i < NUM_ENTITIES; ++i ) {\n                            const Entity& entity = entities[i];\n                            if ( strncmp( p + 1, entity.pattern, entity.length ) == 0\n                                    && *( p + entity.length + 1 ) == ';' ) {\n                                // Found an entity - convert.\n                                *q = entity.value;\n                                ++q;\n                                p += entity.length + 2;\n                                entityFound = true;\n                                break;\n                            }\n                        }\n                        if ( !entityFound ) {\n                            // fixme: treat as error?\n                            ++p;\n                            ++q;\n                        }\n                    }\n                }\n                else {\n                    *q = *p;\n                    ++p;\n                    ++q;\n                }\n            }\n            *q = 0;\n        }\n        // The loop below has plenty going on, and this\n        // is a less useful mode. Break it out.\n        if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) {\n            CollapseWhitespace();\n        }\n        _flags = (_flags & NEEDS_DELETE);\n    }\n    TIXMLASSERT( _start );\n    return _start;\n}\n\n\n\n\n// --------- XMLUtil ----------- //\n\nconst char* XMLUtil::writeBoolTrue  = \"true\";\nconst char* XMLUtil::writeBoolFalse = \"false\";\n\nvoid XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse)\n{\n\tstatic const char* defTrue  = \"true\";\n\tstatic const char* defFalse = \"false\";\n\n\twriteBoolTrue = (writeTrue) ? writeTrue : defTrue;\n\twriteBoolFalse = (writeFalse) ? writeFalse : defFalse;\n}\n\n\nconst char* XMLUtil::ReadBOM( const char* p, bool* bom )\n{\n    TIXMLASSERT( p );\n    TIXMLASSERT( bom );\n    *bom = false;\n    const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);\n    // Check for BOM:\n    if (    *(pu+0) == TIXML_UTF_LEAD_0\n            && *(pu+1) == TIXML_UTF_LEAD_1\n            && *(pu+2) == TIXML_UTF_LEAD_2 ) {\n        *bom = true;\n        p += 3;\n    }\n    TIXMLASSERT( p );\n    return p;\n}\n\n\nvoid XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )\n{\n    const unsigned long BYTE_MASK = 0xBF;\n    const unsigned long BYTE_MARK = 0x80;\n    const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };\n\n    if (input < 0x80) {\n        *length = 1;\n    }\n    else if ( input < 0x800 ) {\n        *length = 2;\n    }\n    else if ( input < 0x10000 ) {\n        *length = 3;\n    }\n    else if ( input < 0x200000 ) {\n        *length = 4;\n    }\n    else {\n        *length = 0;    // This code won't convert this correctly anyway.\n        return;\n    }\n\n    output += *length;\n\n    // Scary scary fall throughs are annotated with carefully designed comments\n    // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc\n    switch (*length) {\n        case 4:\n            --output;\n            *output = static_cast<char>((input | BYTE_MARK) & BYTE_MASK);\n            input >>= 6;\n            //fall through\n        case 3:\n            --output;\n            *output = static_cast<char>((input | BYTE_MARK) & BYTE_MASK);\n            input >>= 6;\n            //fall through\n        case 2:\n            --output;\n            *output = static_cast<char>((input | BYTE_MARK) & BYTE_MASK);\n            input >>= 6;\n            //fall through\n        case 1:\n            --output;\n            *output = static_cast<char>(input | FIRST_BYTE_MARK[*length]);\n            break;\n        default:\n            TIXMLASSERT( false );\n    }\n}\n\n\nconst char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )\n{\n    // Presume an entity, and pull it out.\n    *length = 0;\n\n    if ( *(p+1) == '#' && *(p+2) ) {\n        unsigned long ucs = 0;\n        TIXMLASSERT( sizeof( ucs ) >= 4 );\n        ptrdiff_t delta = 0;\n        unsigned mult = 1;\n        static const char SEMICOLON = ';';\n\n        if ( *(p+2) == 'x' ) {\n            // Hexadecimal.\n            const char* q = p+3;\n            if ( !(*q) ) {\n                return 0;\n            }\n\n            q = strchr( q, SEMICOLON );\n\n            if ( !q ) {\n                return 0;\n            }\n            TIXMLASSERT( *q == SEMICOLON );\n\n            delta = q-p;\n            --q;\n\n            while ( *q != 'x' ) {\n                unsigned int digit = 0;\n\n                if ( *q >= '0' && *q <= '9' ) {\n                    digit = *q - '0';\n                }\n                else if ( *q >= 'a' && *q <= 'f' ) {\n                    digit = *q - 'a' + 10;\n                }\n                else if ( *q >= 'A' && *q <= 'F' ) {\n                    digit = *q - 'A' + 10;\n                }\n                else {\n                    return 0;\n                }\n                TIXMLASSERT( digit < 16 );\n                TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );\n                const unsigned int digitScaled = mult * digit;\n                TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );\n                ucs += digitScaled;\n                TIXMLASSERT( mult <= UINT_MAX / 16 );\n                mult *= 16;\n                --q;\n            }\n        }\n        else {\n            // Decimal.\n            const char* q = p+2;\n            if ( !(*q) ) {\n                return 0;\n            }\n\n            q = strchr( q, SEMICOLON );\n\n            if ( !q ) {\n                return 0;\n            }\n            TIXMLASSERT( *q == SEMICOLON );\n\n            delta = q-p;\n            --q;\n\n            while ( *q != '#' ) {\n                if ( *q >= '0' && *q <= '9' ) {\n                    const unsigned int digit = *q - '0';\n                    TIXMLASSERT( digit < 10 );\n                    TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );\n                    const unsigned int digitScaled = mult * digit;\n                    TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );\n                    ucs += digitScaled;\n                }\n                else {\n                    return 0;\n                }\n                TIXMLASSERT( mult <= UINT_MAX / 10 );\n                mult *= 10;\n                --q;\n            }\n        }\n        // convert the UCS to UTF-8\n        ConvertUTF32ToUTF8( ucs, value, length );\n        return p + delta + 1;\n    }\n    return p+1;\n}\n\n\nvoid XMLUtil::ToStr( int v, char* buffer, int bufferSize )\n{\n    TIXML_SNPRINTF( buffer, bufferSize, \"%d\", v );\n}\n\n\nvoid XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )\n{\n    TIXML_SNPRINTF( buffer, bufferSize, \"%u\", v );\n}\n\n\nvoid XMLUtil::ToStr( bool v, char* buffer, int bufferSize )\n{\n    TIXML_SNPRINTF( buffer, bufferSize, \"%s\", v ? writeBoolTrue : writeBoolFalse);\n}\n\n/*\n\tToStr() of a number is a very tricky topic.\n\thttps://github.com/leethomason/tinyxml2/issues/106\n*/\nvoid XMLUtil::ToStr( float v, char* buffer, int bufferSize )\n{\n    TIXML_SNPRINTF( buffer, bufferSize, \"%.8g\", v );\n}\n\n\nvoid XMLUtil::ToStr( double v, char* buffer, int bufferSize )\n{\n    TIXML_SNPRINTF( buffer, bufferSize, \"%.17g\", v );\n}\n\n\nvoid XMLUtil::ToStr( int64_t v, char* buffer, int bufferSize )\n{\n\t// horrible syntax trick to make the compiler happy about %lld\n\tTIXML_SNPRINTF(buffer, bufferSize, \"%lld\", static_cast<long long>(v));\n}\n\nvoid XMLUtil::ToStr( uint64_t v, char* buffer, int bufferSize )\n{\n    // horrible syntax trick to make the compiler happy about %llu\n    TIXML_SNPRINTF(buffer, bufferSize, \"%llu\", (long long)v);\n}\n\nbool XMLUtil::ToInt(const char* str, int* value)\n{\n    if (TIXML_SSCANF(str, IsPrefixHex(str) ? \"%x\" : \"%d\", value) == 1) {\n        return true;\n    }\n    return false;\n}\n\nbool XMLUtil::ToUnsigned(const char* str, unsigned* value)\n{\n    if (TIXML_SSCANF(str, IsPrefixHex(str) ? \"%x\" : \"%u\", value) == 1) {\n        return true;\n    }\n    return false;\n}\n\nbool XMLUtil::ToBool( const char* str, bool* value )\n{\n    int ival = 0;\n    if ( ToInt( str, &ival )) {\n        *value = (ival==0) ? false : true;\n        return true;\n    }\n    static const char* TRUE_VALS[] = { \"true\", \"True\", \"TRUE\", 0 };\n    static const char* FALSE_VALS[] = { \"false\", \"False\", \"FALSE\", 0 };\n\n    for (int i = 0; TRUE_VALS[i]; ++i) {\n        if (StringEqual(str, TRUE_VALS[i])) {\n            *value = true;\n            return true;\n        }\n    }\n    for (int i = 0; FALSE_VALS[i]; ++i) {\n        if (StringEqual(str, FALSE_VALS[i])) {\n            *value = false;\n            return true;\n        }\n    }\n    return false;\n}\n\n\nbool XMLUtil::ToFloat( const char* str, float* value )\n{\n    if ( TIXML_SSCANF( str, \"%f\", value ) == 1 ) {\n        return true;\n    }\n    return false;\n}\n\n\nbool XMLUtil::ToDouble( const char* str, double* value )\n{\n    if ( TIXML_SSCANF( str, \"%lf\", value ) == 1 ) {\n        return true;\n    }\n    return false;\n}\n\n\nbool XMLUtil::ToInt64(const char* str, int64_t* value)\n{\n\tlong long v = 0;\t// horrible syntax trick to make the compiler happy about %lld\n\tif (TIXML_SSCANF(str, IsPrefixHex(str) ? \"%llx\" : \"%lld\", &v) == 1) {\n\t\t*value = static_cast<int64_t>(v);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n\nbool XMLUtil::ToUnsigned64(const char* str, uint64_t* value) {\n    unsigned long long v = 0;\t// horrible syntax trick to make the compiler happy about %llu\n    if(TIXML_SSCANF(str, IsPrefixHex(str) ? \"%llx\" : \"%llu\", &v) == 1) {\n        *value = (uint64_t)v;\n        return true;\n    }\n    return false;\n}\n\n\nchar* XMLDocument::Identify( char* p, XMLNode** node )\n{\n    TIXMLASSERT( node );\n    TIXMLASSERT( p );\n    char* const start = p;\n    int const startLine = _parseCurLineNum;\n    p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );\n    if( !*p ) {\n        *node = 0;\n        TIXMLASSERT( p );\n        return p;\n    }\n\n    // These strings define the matching patterns:\n    static const char* xmlHeader\t\t= { \"<?\" };\n    static const char* commentHeader\t= { \"<!--\" };\n    static const char* cdataHeader\t\t= { \"<![CDATA[\" };\n    static const char* dtdHeader\t\t= { \"<!\" };\n    static const char* elementHeader\t= { \"<\" };\t// and a header for everything else; check last.\n\n    static const int xmlHeaderLen\t\t= 2;\n    static const int commentHeaderLen\t= 4;\n    static const int cdataHeaderLen\t\t= 9;\n    static const int dtdHeaderLen\t\t= 2;\n    static const int elementHeaderLen\t= 1;\n\n    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );\t\t// use same memory pool\n    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );\t// use same memory pool\n    XMLNode* returnNode = 0;\n    if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {\n        returnNode = CreateUnlinkedNode<XMLDeclaration>( _commentPool );\n        returnNode->_parseLineNum = _parseCurLineNum;\n        p += xmlHeaderLen;\n    }\n    else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {\n        returnNode = CreateUnlinkedNode<XMLComment>( _commentPool );\n        returnNode->_parseLineNum = _parseCurLineNum;\n        p += commentHeaderLen;\n    }\n    else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {\n        XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );\n        returnNode = text;\n        returnNode->_parseLineNum = _parseCurLineNum;\n        p += cdataHeaderLen;\n        text->SetCData( true );\n    }\n    else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {\n        returnNode = CreateUnlinkedNode<XMLUnknown>( _commentPool );\n        returnNode->_parseLineNum = _parseCurLineNum;\n        p += dtdHeaderLen;\n    }\n    else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {\n        returnNode =  CreateUnlinkedNode<XMLElement>( _elementPool );\n        returnNode->_parseLineNum = _parseCurLineNum;\n        p += elementHeaderLen;\n    }\n    else {\n        returnNode = CreateUnlinkedNode<XMLText>( _textPool );\n        returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character\n        p = start;\t// Back it up, all the text counts.\n        _parseCurLineNum = startLine;\n    }\n\n    TIXMLASSERT( returnNode );\n    TIXMLASSERT( p );\n    *node = returnNode;\n    return p;\n}\n\n\nbool XMLDocument::Accept( XMLVisitor* visitor ) const\n{\n    TIXMLASSERT( visitor );\n    if ( visitor->VisitEnter( *this ) ) {\n        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {\n            if ( !node->Accept( visitor ) ) {\n                break;\n            }\n        }\n    }\n    return visitor->VisitExit( *this );\n}\n\n\n// --------- XMLNode ----------- //\n\nXMLNode::XMLNode( XMLDocument* doc ) :\n    _document( doc ),\n    _parent( 0 ),\n    _value(),\n    _parseLineNum( 0 ),\n    _firstChild( 0 ), _lastChild( 0 ),\n    _prev( 0 ), _next( 0 ),\n\t_userData( 0 ),\n    _memPool( 0 )\n{\n}\n\n\nXMLNode::~XMLNode()\n{\n    DeleteChildren();\n    if ( _parent ) {\n        _parent->Unlink( this );\n    }\n}\n\nconst char* XMLNode::Value() const\n{\n    // Edge case: XMLDocuments don't have a Value. Return null.\n    if ( this->ToDocument() )\n        return 0;\n    return _value.GetStr();\n}\n\nvoid XMLNode::SetValue( const char* str, bool staticMem )\n{\n    if ( staticMem ) {\n        _value.SetInternedStr( str );\n    }\n    else {\n        _value.SetStr( str );\n    }\n}\n\nXMLNode* XMLNode::DeepClone(XMLDocument* target) const\n{\n\tXMLNode* clone = this->ShallowClone(target);\n\tif (!clone) return 0;\n\n\tfor (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) {\n\t\tXMLNode* childClone = child->DeepClone(target);\n\t\tTIXMLASSERT(childClone);\n\t\tclone->InsertEndChild(childClone);\n\t}\n\treturn clone;\n}\n\nvoid XMLNode::DeleteChildren()\n{\n    while( _firstChild ) {\n        TIXMLASSERT( _lastChild );\n        DeleteChild( _firstChild );\n    }\n    _firstChild = _lastChild = 0;\n}\n\n\nvoid XMLNode::Unlink( XMLNode* child )\n{\n    TIXMLASSERT( child );\n    TIXMLASSERT( child->_document == _document );\n    TIXMLASSERT( child->_parent == this );\n    if ( child == _firstChild ) {\n        _firstChild = _firstChild->_next;\n    }\n    if ( child == _lastChild ) {\n        _lastChild = _lastChild->_prev;\n    }\n\n    if ( child->_prev ) {\n        child->_prev->_next = child->_next;\n    }\n    if ( child->_next ) {\n        child->_next->_prev = child->_prev;\n    }\n\tchild->_next = 0;\n\tchild->_prev = 0;\n\tchild->_parent = 0;\n}\n\n\nvoid XMLNode::DeleteChild( XMLNode* node )\n{\n    TIXMLASSERT( node );\n    TIXMLASSERT( node->_document == _document );\n    TIXMLASSERT( node->_parent == this );\n    Unlink( node );\n\tTIXMLASSERT(node->_prev == 0);\n\tTIXMLASSERT(node->_next == 0);\n\tTIXMLASSERT(node->_parent == 0);\n    DeleteNode( node );\n}\n\n\nXMLNode* XMLNode::InsertEndChild( XMLNode* addThis )\n{\n    TIXMLASSERT( addThis );\n    if ( addThis->_document != _document ) {\n        TIXMLASSERT( false );\n        return 0;\n    }\n    InsertChildPreamble( addThis );\n\n    if ( _lastChild ) {\n        TIXMLASSERT( _firstChild );\n        TIXMLASSERT( _lastChild->_next == 0 );\n        _lastChild->_next = addThis;\n        addThis->_prev = _lastChild;\n        _lastChild = addThis;\n\n        addThis->_next = 0;\n    }\n    else {\n        TIXMLASSERT( _firstChild == 0 );\n        _firstChild = _lastChild = addThis;\n\n        addThis->_prev = 0;\n        addThis->_next = 0;\n    }\n    addThis->_parent = this;\n    return addThis;\n}\n\n\nXMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )\n{\n    TIXMLASSERT( addThis );\n    if ( addThis->_document != _document ) {\n        TIXMLASSERT( false );\n        return 0;\n    }\n    InsertChildPreamble( addThis );\n\n    if ( _firstChild ) {\n        TIXMLASSERT( _lastChild );\n        TIXMLASSERT( _firstChild->_prev == 0 );\n\n        _firstChild->_prev = addThis;\n        addThis->_next = _firstChild;\n        _firstChild = addThis;\n\n        addThis->_prev = 0;\n    }\n    else {\n        TIXMLASSERT( _lastChild == 0 );\n        _firstChild = _lastChild = addThis;\n\n        addThis->_prev = 0;\n        addThis->_next = 0;\n    }\n    addThis->_parent = this;\n    return addThis;\n}\n\n\nXMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )\n{\n    TIXMLASSERT( addThis );\n    if ( addThis->_document != _document ) {\n        TIXMLASSERT( false );\n        return 0;\n    }\n\n    TIXMLASSERT( afterThis );\n\n    if ( afterThis->_parent != this ) {\n        TIXMLASSERT( false );\n        return 0;\n    }\n    if ( afterThis == addThis ) {\n        // Current state: BeforeThis -> AddThis -> OneAfterAddThis\n        // Now AddThis must disappear from it's location and then\n        // reappear between BeforeThis and OneAfterAddThis.\n        // So just leave it where it is.\n        return addThis;\n    }\n\n    if ( afterThis->_next == 0 ) {\n        // The last node or the only node.\n        return InsertEndChild( addThis );\n    }\n    InsertChildPreamble( addThis );\n    addThis->_prev = afterThis;\n    addThis->_next = afterThis->_next;\n    afterThis->_next->_prev = addThis;\n    afterThis->_next = addThis;\n    addThis->_parent = this;\n    return addThis;\n}\n\n\n\n\nconst XMLElement* XMLNode::FirstChildElement( const char* name ) const\n{\n    for( const XMLNode* node = _firstChild; node; node = node->_next ) {\n        const XMLElement* element = node->ToElementWithName( name );\n        if ( element ) {\n            return element;\n        }\n    }\n    return 0;\n}\n\n\nconst XMLElement* XMLNode::LastChildElement( const char* name ) const\n{\n    for( const XMLNode* node = _lastChild; node; node = node->_prev ) {\n        const XMLElement* element = node->ToElementWithName( name );\n        if ( element ) {\n            return element;\n        }\n    }\n    return 0;\n}\n\n\nconst XMLElement* XMLNode::NextSiblingElement( const char* name ) const\n{\n    for( const XMLNode* node = _next; node; node = node->_next ) {\n        const XMLElement* element = node->ToElementWithName( name );\n        if ( element ) {\n            return element;\n        }\n    }\n    return 0;\n}\n\n\nconst XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const\n{\n    for( const XMLNode* node = _prev; node; node = node->_prev ) {\n        const XMLElement* element = node->ToElementWithName( name );\n        if ( element ) {\n            return element;\n        }\n    }\n    return 0;\n}\n\n\nchar* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )\n{\n    // This is a recursive method, but thinking about it \"at the current level\"\n    // it is a pretty simple flat list:\n    //\t\t<foo/>\n    //\t\t<!-- comment -->\n    //\n    // With a special case:\n    //\t\t<foo>\n    //\t\t</foo>\n    //\t\t<!-- comment -->\n    //\n    // Where the closing element (/foo) *must* be the next thing after the opening\n    // element, and the names must match. BUT the tricky bit is that the closing\n    // element will be read by the child.\n    //\n    // 'endTag' is the end tag for this node, it is returned by a call to a child.\n    // 'parentEnd' is the end tag for the parent, which is filled in and returned.\n\n\tXMLDocument::DepthTracker tracker(_document);\n\tif (_document->Error())\n\t\treturn 0;\n\n\twhile( p && *p ) {\n        XMLNode* node = 0;\n\n        p = _document->Identify( p, &node );\n        TIXMLASSERT( p );\n        if ( node == 0 ) {\n            break;\n        }\n\n       const int initialLineNum = node->_parseLineNum;\n\n        StrPair endTag;\n        p = node->ParseDeep( p, &endTag, curLineNumPtr );\n        if ( !p ) {\n            DeleteNode( node );\n            if ( !_document->Error() ) {\n                _document->SetError( XML_ERROR_PARSING, initialLineNum, 0);\n            }\n            break;\n        }\n\n        const XMLDeclaration* const decl = node->ToDeclaration();\n        if ( decl ) {\n            // Declarations are only allowed at document level\n            //\n            // Multiple declarations are allowed but all declarations\n            // must occur before anything else.\n            //\n            // Optimized due to a security test case. If the first node is\n            // a declaration, and the last node is a declaration, then only\n            // declarations have so far been added.\n            bool wellLocated = false;\n\n            if (ToDocument()) {\n                if (FirstChild()) {\n                    wellLocated =\n                        FirstChild() &&\n                        FirstChild()->ToDeclaration() &&\n                        LastChild() &&\n                        LastChild()->ToDeclaration();\n                }\n                else {\n                    wellLocated = true;\n                }\n            }\n            if ( !wellLocated ) {\n                _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, \"XMLDeclaration value=%s\", decl->Value());\n                DeleteNode( node );\n                break;\n            }\n        }\n\n        XMLElement* ele = node->ToElement();\n        if ( ele ) {\n            // We read the end tag. Return it to the parent.\n            if ( ele->ClosingType() == XMLElement::CLOSING ) {\n                if ( parentEndTag ) {\n                    ele->_value.TransferTo( parentEndTag );\n                }\n                node->_memPool->SetTracked();   // created and then immediately deleted.\n                DeleteNode( node );\n                return p;\n            }\n\n            // Handle an end tag returned to this level.\n            // And handle a bunch of annoying errors.\n            bool mismatch = false;\n            if ( endTag.Empty() ) {\n                if ( ele->ClosingType() == XMLElement::OPEN ) {\n                    mismatch = true;\n                }\n            }\n            else {\n                if ( ele->ClosingType() != XMLElement::OPEN ) {\n                    mismatch = true;\n                }\n                else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {\n                    mismatch = true;\n                }\n            }\n            if ( mismatch ) {\n                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, \"XMLElement name=%s\", ele->Name());\n                DeleteNode( node );\n                break;\n            }\n        }\n        InsertEndChild( node );\n    }\n    return 0;\n}\n\n/*static*/ void XMLNode::DeleteNode( XMLNode* node )\n{\n    if ( node == 0 ) {\n        return;\n    }\n\tTIXMLASSERT(node->_document);\n\tif (!node->ToDocument()) {\n\t\tnode->_document->MarkInUse(node);\n\t}\n\n    MemPool* pool = node->_memPool;\n    node->~XMLNode();\n    pool->Free( node );\n}\n\nvoid XMLNode::InsertChildPreamble( XMLNode* insertThis ) const\n{\n    TIXMLASSERT( insertThis );\n    TIXMLASSERT( insertThis->_document == _document );\n\n\tif (insertThis->_parent) {\n        insertThis->_parent->Unlink( insertThis );\n\t}\n\telse {\n\t\tinsertThis->_document->MarkInUse(insertThis);\n        insertThis->_memPool->SetTracked();\n\t}\n}\n\nconst XMLElement* XMLNode::ToElementWithName( const char* name ) const\n{\n    const XMLElement* element = this->ToElement();\n    if ( element == 0 ) {\n        return 0;\n    }\n    if ( name == 0 ) {\n        return element;\n    }\n    if ( XMLUtil::StringEqual( element->Name(), name ) ) {\n       return element;\n    }\n    return 0;\n}\n\n// --------- XMLText ---------- //\nchar* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr )\n{\n    if ( this->CData() ) {\n        p = _value.ParseText( p, \"]]>\", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );\n        if ( !p ) {\n            _document->SetError( XML_ERROR_PARSING_CDATA, _parseLineNum, 0 );\n        }\n        return p;\n    }\n    else {\n        int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;\n        if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {\n            flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING;\n        }\n\n        p = _value.ParseText( p, \"<\", flags, curLineNumPtr );\n        if ( p && *p ) {\n            return p-1;\n        }\n        if ( !p ) {\n            _document->SetError( XML_ERROR_PARSING_TEXT, _parseLineNum, 0 );\n        }\n    }\n    return 0;\n}\n\n\nXMLNode* XMLText::ShallowClone( XMLDocument* doc ) const\n{\n    if ( !doc ) {\n        doc = _document;\n    }\n    XMLText* text = doc->NewText( Value() );\t// fixme: this will always allocate memory. Intern?\n    text->SetCData( this->CData() );\n    return text;\n}\n\n\nbool XMLText::ShallowEqual( const XMLNode* compare ) const\n{\n    TIXMLASSERT( compare );\n    const XMLText* text = compare->ToText();\n    return ( text && XMLUtil::StringEqual( text->Value(), Value() ) );\n}\n\n\nbool XMLText::Accept( XMLVisitor* visitor ) const\n{\n    TIXMLASSERT( visitor );\n    return visitor->Visit( *this );\n}\n\n\n// --------- XMLComment ---------- //\n\nXMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )\n{\n}\n\n\nXMLComment::~XMLComment()\n{\n}\n\n\nchar* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr )\n{\n    // Comment parses as text.\n    p = _value.ParseText( p, \"-->\", StrPair::COMMENT, curLineNumPtr );\n    if ( p == 0 ) {\n        _document->SetError( XML_ERROR_PARSING_COMMENT, _parseLineNum, 0 );\n    }\n    return p;\n}\n\n\nXMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const\n{\n    if ( !doc ) {\n        doc = _document;\n    }\n    XMLComment* comment = doc->NewComment( Value() );\t// fixme: this will always allocate memory. Intern?\n    return comment;\n}\n\n\nbool XMLComment::ShallowEqual( const XMLNode* compare ) const\n{\n    TIXMLASSERT( compare );\n    const XMLComment* comment = compare->ToComment();\n    return ( comment && XMLUtil::StringEqual( comment->Value(), Value() ));\n}\n\n\nbool XMLComment::Accept( XMLVisitor* visitor ) const\n{\n    TIXMLASSERT( visitor );\n    return visitor->Visit( *this );\n}\n\n\n// --------- XMLDeclaration ---------- //\n\nXMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )\n{\n}\n\n\nXMLDeclaration::~XMLDeclaration()\n{\n    //printf( \"~XMLDeclaration\\n\" );\n}\n\n\nchar* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr )\n{\n    // Declaration parses as text.\n    p = _value.ParseText( p, \"?>\", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );\n    if ( p == 0 ) {\n        _document->SetError( XML_ERROR_PARSING_DECLARATION, _parseLineNum, 0 );\n    }\n    return p;\n}\n\n\nXMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const\n{\n    if ( !doc ) {\n        doc = _document;\n    }\n    XMLDeclaration* dec = doc->NewDeclaration( Value() );\t// fixme: this will always allocate memory. Intern?\n    return dec;\n}\n\n\nbool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const\n{\n    TIXMLASSERT( compare );\n    const XMLDeclaration* declaration = compare->ToDeclaration();\n    return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() ));\n}\n\n\n\nbool XMLDeclaration::Accept( XMLVisitor* visitor ) const\n{\n    TIXMLASSERT( visitor );\n    return visitor->Visit( *this );\n}\n\n// --------- XMLUnknown ---------- //\n\nXMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )\n{\n}\n\n\nXMLUnknown::~XMLUnknown()\n{\n}\n\n\nchar* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr )\n{\n    // Unknown parses as text.\n    p = _value.ParseText( p, \">\", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );\n    if ( !p ) {\n        _document->SetError( XML_ERROR_PARSING_UNKNOWN, _parseLineNum, 0 );\n    }\n    return p;\n}\n\n\nXMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const\n{\n    if ( !doc ) {\n        doc = _document;\n    }\n    XMLUnknown* text = doc->NewUnknown( Value() );\t// fixme: this will always allocate memory. Intern?\n    return text;\n}\n\n\nbool XMLUnknown::ShallowEqual( const XMLNode* compare ) const\n{\n    TIXMLASSERT( compare );\n    const XMLUnknown* unknown = compare->ToUnknown();\n    return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() ));\n}\n\n\nbool XMLUnknown::Accept( XMLVisitor* visitor ) const\n{\n    TIXMLASSERT( visitor );\n    return visitor->Visit( *this );\n}\n\n// --------- XMLAttribute ---------- //\n\nconst char* XMLAttribute::Name() const\n{\n    return _name.GetStr();\n}\n\nconst char* XMLAttribute::Value() const\n{\n    return _value.GetStr();\n}\n\nchar* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr )\n{\n    // Parse using the name rules: bug fix, was using ParseText before\n    p = _name.ParseName( p );\n    if ( !p || !*p ) {\n        return 0;\n    }\n\n    // Skip white space before =\n    p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );\n    if ( *p != '=' ) {\n        return 0;\n    }\n\n    ++p;\t// move up to opening quote\n    p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );\n    if ( *p != '\\\"' && *p != '\\'' ) {\n        return 0;\n    }\n\n    const char endTag[2] = { *p, 0 };\n    ++p;\t// move past opening quote\n\n    p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr );\n    return p;\n}\n\n\nvoid XMLAttribute::SetName( const char* n )\n{\n    _name.SetStr( n );\n}\n\n\nXMLError XMLAttribute::QueryIntValue( int* value ) const\n{\n    if ( XMLUtil::ToInt( Value(), value )) {\n        return XML_SUCCESS;\n    }\n    return XML_WRONG_ATTRIBUTE_TYPE;\n}\n\n\nXMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const\n{\n    if ( XMLUtil::ToUnsigned( Value(), value )) {\n        return XML_SUCCESS;\n    }\n    return XML_WRONG_ATTRIBUTE_TYPE;\n}\n\n\nXMLError XMLAttribute::QueryInt64Value(int64_t* value) const\n{\n\tif (XMLUtil::ToInt64(Value(), value)) {\n\t\treturn XML_SUCCESS;\n\t}\n\treturn XML_WRONG_ATTRIBUTE_TYPE;\n}\n\n\nXMLError XMLAttribute::QueryUnsigned64Value(uint64_t* value) const\n{\n    if(XMLUtil::ToUnsigned64(Value(), value)) {\n        return XML_SUCCESS;\n    }\n    return XML_WRONG_ATTRIBUTE_TYPE;\n}\n\n\nXMLError XMLAttribute::QueryBoolValue( bool* value ) const\n{\n    if ( XMLUtil::ToBool( Value(), value )) {\n        return XML_SUCCESS;\n    }\n    return XML_WRONG_ATTRIBUTE_TYPE;\n}\n\n\nXMLError XMLAttribute::QueryFloatValue( float* value ) const\n{\n    if ( XMLUtil::ToFloat( Value(), value )) {\n        return XML_SUCCESS;\n    }\n    return XML_WRONG_ATTRIBUTE_TYPE;\n}\n\n\nXMLError XMLAttribute::QueryDoubleValue( double* value ) const\n{\n    if ( XMLUtil::ToDouble( Value(), value )) {\n        return XML_SUCCESS;\n    }\n    return XML_WRONG_ATTRIBUTE_TYPE;\n}\n\n\nvoid XMLAttribute::SetAttribute( const char* v )\n{\n    _value.SetStr( v );\n}\n\n\nvoid XMLAttribute::SetAttribute( int v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    _value.SetStr( buf );\n}\n\n\nvoid XMLAttribute::SetAttribute( unsigned v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    _value.SetStr( buf );\n}\n\n\nvoid XMLAttribute::SetAttribute(int64_t v)\n{\n\tchar buf[BUF_SIZE];\n\tXMLUtil::ToStr(v, buf, BUF_SIZE);\n\t_value.SetStr(buf);\n}\n\nvoid XMLAttribute::SetAttribute(uint64_t v)\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr(v, buf, BUF_SIZE);\n    _value.SetStr(buf);\n}\n\n\nvoid XMLAttribute::SetAttribute( bool v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    _value.SetStr( buf );\n}\n\nvoid XMLAttribute::SetAttribute( double v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    _value.SetStr( buf );\n}\n\nvoid XMLAttribute::SetAttribute( float v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    _value.SetStr( buf );\n}\n\n\n// --------- XMLElement ---------- //\nXMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),\n    _closingType( OPEN ),\n    _rootAttribute( 0 )\n{\n}\n\n\nXMLElement::~XMLElement()\n{\n    while( _rootAttribute ) {\n        XMLAttribute* next = _rootAttribute->_next;\n        DeleteAttribute( _rootAttribute );\n        _rootAttribute = next;\n    }\n}\n\n\nconst XMLAttribute* XMLElement::FindAttribute( const char* name ) const\n{\n    for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) {\n        if ( XMLUtil::StringEqual( a->Name(), name ) ) {\n            return a;\n        }\n    }\n    return 0;\n}\n\n\nconst char* XMLElement::Attribute( const char* name, const char* value ) const\n{\n    const XMLAttribute* a = FindAttribute( name );\n    if ( !a ) {\n        return 0;\n    }\n    if ( !value || XMLUtil::StringEqual( a->Value(), value )) {\n        return a->Value();\n    }\n    return 0;\n}\n\nint XMLElement::IntAttribute(const char* name, int defaultValue) const\n{\n\tint i = defaultValue;\n\tQueryIntAttribute(name, &i);\n\treturn i;\n}\n\nunsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const\n{\n\tunsigned i = defaultValue;\n\tQueryUnsignedAttribute(name, &i);\n\treturn i;\n}\n\nint64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const\n{\n\tint64_t i = defaultValue;\n\tQueryInt64Attribute(name, &i);\n\treturn i;\n}\n\nuint64_t XMLElement::Unsigned64Attribute(const char* name, uint64_t defaultValue) const\n{\n\tuint64_t i = defaultValue;\n\tQueryUnsigned64Attribute(name, &i);\n\treturn i;\n}\n\nbool XMLElement::BoolAttribute(const char* name, bool defaultValue) const\n{\n\tbool b = defaultValue;\n\tQueryBoolAttribute(name, &b);\n\treturn b;\n}\n\ndouble XMLElement::DoubleAttribute(const char* name, double defaultValue) const\n{\n\tdouble d = defaultValue;\n\tQueryDoubleAttribute(name, &d);\n\treturn d;\n}\n\nfloat XMLElement::FloatAttribute(const char* name, float defaultValue) const\n{\n\tfloat f = defaultValue;\n\tQueryFloatAttribute(name, &f);\n\treturn f;\n}\n\nconst char* XMLElement::GetText() const\n{\n    if ( FirstChild() && FirstChild()->ToText() ) {\n        return FirstChild()->Value();\n    }\n    return 0;\n}\n\n\nvoid\tXMLElement::SetText( const char* inText )\n{\n\tif ( FirstChild() && FirstChild()->ToText() )\n\t\tFirstChild()->SetValue( inText );\n\telse {\n\t\tXMLText*\ttheText = GetDocument()->NewText( inText );\n\t\tInsertFirstChild( theText );\n\t}\n}\n\n\nvoid XMLElement::SetText( int v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    SetText( buf );\n}\n\n\nvoid XMLElement::SetText( unsigned v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    SetText( buf );\n}\n\n\nvoid XMLElement::SetText(int64_t v)\n{\n\tchar buf[BUF_SIZE];\n\tXMLUtil::ToStr(v, buf, BUF_SIZE);\n\tSetText(buf);\n}\n\nvoid XMLElement::SetText(uint64_t v) {\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr(v, buf, BUF_SIZE);\n    SetText(buf);\n}\n\n\nvoid XMLElement::SetText( bool v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    SetText( buf );\n}\n\n\nvoid XMLElement::SetText( float v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    SetText( buf );\n}\n\n\nvoid XMLElement::SetText( double v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    SetText( buf );\n}\n\n\nXMLError XMLElement::QueryIntText( int* ival ) const\n{\n    if ( FirstChild() && FirstChild()->ToText() ) {\n        const char* t = FirstChild()->Value();\n        if ( XMLUtil::ToInt( t, ival ) ) {\n            return XML_SUCCESS;\n        }\n        return XML_CAN_NOT_CONVERT_TEXT;\n    }\n    return XML_NO_TEXT_NODE;\n}\n\n\nXMLError XMLElement::QueryUnsignedText( unsigned* uval ) const\n{\n    if ( FirstChild() && FirstChild()->ToText() ) {\n        const char* t = FirstChild()->Value();\n        if ( XMLUtil::ToUnsigned( t, uval ) ) {\n            return XML_SUCCESS;\n        }\n        return XML_CAN_NOT_CONVERT_TEXT;\n    }\n    return XML_NO_TEXT_NODE;\n}\n\n\nXMLError XMLElement::QueryInt64Text(int64_t* ival) const\n{\n\tif (FirstChild() && FirstChild()->ToText()) {\n\t\tconst char* t = FirstChild()->Value();\n\t\tif (XMLUtil::ToInt64(t, ival)) {\n\t\t\treturn XML_SUCCESS;\n\t\t}\n\t\treturn XML_CAN_NOT_CONVERT_TEXT;\n\t}\n\treturn XML_NO_TEXT_NODE;\n}\n\n\nXMLError XMLElement::QueryUnsigned64Text(uint64_t* ival) const\n{\n    if(FirstChild() && FirstChild()->ToText()) {\n        const char* t = FirstChild()->Value();\n        if(XMLUtil::ToUnsigned64(t, ival)) {\n            return XML_SUCCESS;\n        }\n        return XML_CAN_NOT_CONVERT_TEXT;\n    }\n    return XML_NO_TEXT_NODE;\n}\n\n\nXMLError XMLElement::QueryBoolText( bool* bval ) const\n{\n    if ( FirstChild() && FirstChild()->ToText() ) {\n        const char* t = FirstChild()->Value();\n        if ( XMLUtil::ToBool( t, bval ) ) {\n            return XML_SUCCESS;\n        }\n        return XML_CAN_NOT_CONVERT_TEXT;\n    }\n    return XML_NO_TEXT_NODE;\n}\n\n\nXMLError XMLElement::QueryDoubleText( double* dval ) const\n{\n    if ( FirstChild() && FirstChild()->ToText() ) {\n        const char* t = FirstChild()->Value();\n        if ( XMLUtil::ToDouble( t, dval ) ) {\n            return XML_SUCCESS;\n        }\n        return XML_CAN_NOT_CONVERT_TEXT;\n    }\n    return XML_NO_TEXT_NODE;\n}\n\n\nXMLError XMLElement::QueryFloatText( float* fval ) const\n{\n    if ( FirstChild() && FirstChild()->ToText() ) {\n        const char* t = FirstChild()->Value();\n        if ( XMLUtil::ToFloat( t, fval ) ) {\n            return XML_SUCCESS;\n        }\n        return XML_CAN_NOT_CONVERT_TEXT;\n    }\n    return XML_NO_TEXT_NODE;\n}\n\nint XMLElement::IntText(int defaultValue) const\n{\n\tint i = defaultValue;\n\tQueryIntText(&i);\n\treturn i;\n}\n\nunsigned XMLElement::UnsignedText(unsigned defaultValue) const\n{\n\tunsigned i = defaultValue;\n\tQueryUnsignedText(&i);\n\treturn i;\n}\n\nint64_t XMLElement::Int64Text(int64_t defaultValue) const\n{\n\tint64_t i = defaultValue;\n\tQueryInt64Text(&i);\n\treturn i;\n}\n\nuint64_t XMLElement::Unsigned64Text(uint64_t defaultValue) const\n{\n\tuint64_t i = defaultValue;\n\tQueryUnsigned64Text(&i);\n\treturn i;\n}\n\nbool XMLElement::BoolText(bool defaultValue) const\n{\n\tbool b = defaultValue;\n\tQueryBoolText(&b);\n\treturn b;\n}\n\ndouble XMLElement::DoubleText(double defaultValue) const\n{\n\tdouble d = defaultValue;\n\tQueryDoubleText(&d);\n\treturn d;\n}\n\nfloat XMLElement::FloatText(float defaultValue) const\n{\n\tfloat f = defaultValue;\n\tQueryFloatText(&f);\n\treturn f;\n}\n\n\nXMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )\n{\n    XMLAttribute* last = 0;\n    XMLAttribute* attrib = 0;\n    for( attrib = _rootAttribute;\n            attrib;\n            last = attrib, attrib = attrib->_next ) {\n        if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {\n            break;\n        }\n    }\n    if ( !attrib ) {\n        attrib = CreateAttribute();\n        TIXMLASSERT( attrib );\n        if ( last ) {\n            TIXMLASSERT( last->_next == 0 );\n            last->_next = attrib;\n        }\n        else {\n            TIXMLASSERT( _rootAttribute == 0 );\n            _rootAttribute = attrib;\n        }\n        attrib->SetName( name );\n    }\n    return attrib;\n}\n\n\nvoid XMLElement::DeleteAttribute( const char* name )\n{\n    XMLAttribute* prev = 0;\n    for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {\n        if ( XMLUtil::StringEqual( name, a->Name() ) ) {\n            if ( prev ) {\n                prev->_next = a->_next;\n            }\n            else {\n                _rootAttribute = a->_next;\n            }\n            DeleteAttribute( a );\n            break;\n        }\n        prev = a;\n    }\n}\n\n\nchar* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )\n{\n    XMLAttribute* prevAttribute = 0;\n\n    // Read the attributes.\n    while( p ) {\n        p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );\n        if ( !(*p) ) {\n            _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, \"XMLElement name=%s\", Name() );\n            return 0;\n        }\n\n        // attribute.\n        if (XMLUtil::IsNameStartChar( (unsigned char) *p ) ) {\n            XMLAttribute* attrib = CreateAttribute();\n            TIXMLASSERT( attrib );\n            attrib->_parseLineNum = _document->_parseCurLineNum;\n\n            const int attrLineNum = attrib->_parseLineNum;\n\n            p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr );\n            if ( !p || Attribute( attrib->Name() ) ) {\n                DeleteAttribute( attrib );\n                _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, \"XMLElement name=%s\", Name() );\n                return 0;\n            }\n            // There is a minor bug here: if the attribute in the source xml\n            // document is duplicated, it will not be detected and the\n            // attribute will be doubly added. However, tracking the 'prevAttribute'\n            // avoids re-scanning the attribute list. Preferring performance for\n            // now, may reconsider in the future.\n            if ( prevAttribute ) {\n                TIXMLASSERT( prevAttribute->_next == 0 );\n                prevAttribute->_next = attrib;\n            }\n            else {\n                TIXMLASSERT( _rootAttribute == 0 );\n                _rootAttribute = attrib;\n            }\n            prevAttribute = attrib;\n        }\n        // end of the tag\n        else if ( *p == '>' ) {\n            ++p;\n            break;\n        }\n        // end of the tag\n        else if ( *p == '/' && *(p+1) == '>' ) {\n            _closingType = CLOSED;\n            return p+2;\t// done; sealed element.\n        }\n        else {\n            _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, 0 );\n            return 0;\n        }\n    }\n    return p;\n}\n\nvoid XMLElement::DeleteAttribute( XMLAttribute* attribute )\n{\n    if ( attribute == 0 ) {\n        return;\n    }\n    MemPool* pool = attribute->_memPool;\n    attribute->~XMLAttribute();\n    pool->Free( attribute );\n}\n\nXMLAttribute* XMLElement::CreateAttribute()\n{\n    TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );\n    XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();\n    TIXMLASSERT( attrib );\n    attrib->_memPool = &_document->_attributePool;\n    attrib->_memPool->SetTracked();\n    return attrib;\n}\n\n\nXMLElement* XMLElement::InsertNewChildElement(const char* name)\n{\n    XMLElement* node = _document->NewElement(name);\n    return InsertEndChild(node) ? node : 0;\n}\n\nXMLComment* XMLElement::InsertNewComment(const char* comment)\n{\n    XMLComment* node = _document->NewComment(comment);\n    return InsertEndChild(node) ? node : 0;\n}\n\nXMLText* XMLElement::InsertNewText(const char* text)\n{\n    XMLText* node = _document->NewText(text);\n    return InsertEndChild(node) ? node : 0;\n}\n\nXMLDeclaration* XMLElement::InsertNewDeclaration(const char* text)\n{\n    XMLDeclaration* node = _document->NewDeclaration(text);\n    return InsertEndChild(node) ? node : 0;\n}\n\nXMLUnknown* XMLElement::InsertNewUnknown(const char* text)\n{\n    XMLUnknown* node = _document->NewUnknown(text);\n    return InsertEndChild(node) ? node : 0;\n}\n\n\n\n//\n//\t<ele></ele>\n//\t<ele>foo<b>bar</b></ele>\n//\nchar* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )\n{\n    // Read the element name.\n    p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );\n\n    // The closing element is the </element> form. It is\n    // parsed just like a regular element then deleted from\n    // the DOM.\n    if ( *p == '/' ) {\n        _closingType = CLOSING;\n        ++p;\n    }\n\n    p = _value.ParseName( p );\n    if ( _value.Empty() ) {\n        return 0;\n    }\n\n    p = ParseAttributes( p, curLineNumPtr );\n    if ( !p || !*p || _closingType != OPEN ) {\n        return p;\n    }\n\n    p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr );\n    return p;\n}\n\n\n\nXMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const\n{\n    if ( !doc ) {\n        doc = _document;\n    }\n    XMLElement* element = doc->NewElement( Value() );\t\t\t\t\t// fixme: this will always allocate memory. Intern?\n    for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {\n        element->SetAttribute( a->Name(), a->Value() );\t\t\t\t\t// fixme: this will always allocate memory. Intern?\n    }\n    return element;\n}\n\n\nbool XMLElement::ShallowEqual( const XMLNode* compare ) const\n{\n    TIXMLASSERT( compare );\n    const XMLElement* other = compare->ToElement();\n    if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {\n\n        const XMLAttribute* a=FirstAttribute();\n        const XMLAttribute* b=other->FirstAttribute();\n\n        while ( a && b ) {\n            if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {\n                return false;\n            }\n            a = a->Next();\n            b = b->Next();\n        }\n        if ( a || b ) {\n            // different count\n            return false;\n        }\n        return true;\n    }\n    return false;\n}\n\n\nbool XMLElement::Accept( XMLVisitor* visitor ) const\n{\n    TIXMLASSERT( visitor );\n    if ( visitor->VisitEnter( *this, _rootAttribute ) ) {\n        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {\n            if ( !node->Accept( visitor ) ) {\n                break;\n            }\n        }\n    }\n    return visitor->VisitExit( *this );\n}\n\n\n// --------- XMLDocument ----------- //\n\n// Warning: List must match 'enum XMLError'\nconst char* XMLDocument::_errorNames[XML_ERROR_COUNT] = {\n    \"XML_SUCCESS\",\n    \"XML_NO_ATTRIBUTE\",\n    \"XML_WRONG_ATTRIBUTE_TYPE\",\n    \"XML_ERROR_FILE_NOT_FOUND\",\n    \"XML_ERROR_FILE_COULD_NOT_BE_OPENED\",\n    \"XML_ERROR_FILE_READ_ERROR\",\n    \"XML_ERROR_PARSING_ELEMENT\",\n    \"XML_ERROR_PARSING_ATTRIBUTE\",\n    \"XML_ERROR_PARSING_TEXT\",\n    \"XML_ERROR_PARSING_CDATA\",\n    \"XML_ERROR_PARSING_COMMENT\",\n    \"XML_ERROR_PARSING_DECLARATION\",\n    \"XML_ERROR_PARSING_UNKNOWN\",\n    \"XML_ERROR_EMPTY_DOCUMENT\",\n    \"XML_ERROR_MISMATCHED_ELEMENT\",\n    \"XML_ERROR_PARSING\",\n    \"XML_CAN_NOT_CONVERT_TEXT\",\n    \"XML_NO_TEXT_NODE\",\n\t\"XML_ELEMENT_DEPTH_EXCEEDED\"\n};\n\n\nXMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) :\n    XMLNode( 0 ),\n    _writeBOM( false ),\n    _processEntities( processEntities ),\n    _errorID(XML_SUCCESS),\n    _whitespaceMode( whitespaceMode ),\n    _errorStr(),\n    _errorLineNum( 0 ),\n    _charBuffer( 0 ),\n    _parseCurLineNum( 0 ),\n\t_parsingDepth(0),\n    _unlinked(),\n    _elementPool(),\n    _attributePool(),\n    _textPool(),\n    _commentPool()\n{\n    // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)\n    _document = this;\n}\n\n\nXMLDocument::~XMLDocument()\n{\n    Clear();\n}\n\n\nvoid XMLDocument::MarkInUse(const XMLNode* const node)\n{\n\tTIXMLASSERT(node);\n\tTIXMLASSERT(node->_parent == 0);\n\n\tfor (int i = 0; i < _unlinked.Size(); ++i) {\n\t\tif (node == _unlinked[i]) {\n\t\t\t_unlinked.SwapRemove(i);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid XMLDocument::Clear()\n{\n    DeleteChildren();\n\twhile( _unlinked.Size()) {\n\t\tDeleteNode(_unlinked[0]);\t// Will remove from _unlinked as part of delete.\n\t}\n\n#ifdef TINYXML2_DEBUG\n    const bool hadError = Error();\n#endif\n    ClearError();\n\n    delete [] _charBuffer;\n    _charBuffer = 0;\n\t_parsingDepth = 0;\n\n#if 0\n    _textPool.Trace( \"text\" );\n    _elementPool.Trace( \"element\" );\n    _commentPool.Trace( \"comment\" );\n    _attributePool.Trace( \"attribute\" );\n#endif\n\n#ifdef TINYXML2_DEBUG\n    if ( !hadError ) {\n        TIXMLASSERT( _elementPool.CurrentAllocs()   == _elementPool.Untracked() );\n        TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );\n        TIXMLASSERT( _textPool.CurrentAllocs()      == _textPool.Untracked() );\n        TIXMLASSERT( _commentPool.CurrentAllocs()   == _commentPool.Untracked() );\n    }\n#endif\n}\n\n\nvoid XMLDocument::DeepCopy(XMLDocument* target) const\n{\n\tTIXMLASSERT(target);\n    if (target == this) {\n        return; // technically success - a no-op.\n    }\n\n\ttarget->Clear();\n\tfor (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) {\n\t\ttarget->InsertEndChild(node->DeepClone(target));\n\t}\n}\n\nXMLElement* XMLDocument::NewElement( const char* name )\n{\n    XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );\n    ele->SetName( name );\n    return ele;\n}\n\n\nXMLComment* XMLDocument::NewComment( const char* str )\n{\n    XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool );\n    comment->SetValue( str );\n    return comment;\n}\n\n\nXMLText* XMLDocument::NewText( const char* str )\n{\n    XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );\n    text->SetValue( str );\n    return text;\n}\n\n\nXMLDeclaration* XMLDocument::NewDeclaration( const char* str )\n{\n    XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool );\n    dec->SetValue( str ? str : \"xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"\" );\n    return dec;\n}\n\n\nXMLUnknown* XMLDocument::NewUnknown( const char* str )\n{\n    XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool );\n    unk->SetValue( str );\n    return unk;\n}\n\nstatic FILE* callfopen( const char* filepath, const char* mode )\n{\n    TIXMLASSERT( filepath );\n    TIXMLASSERT( mode );\n#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)\n    FILE* fp = 0;\n    const errno_t err = fopen_s( &fp, filepath, mode );\n    if ( err ) {\n        return 0;\n    }\n#else\n    FILE* fp = fopen( filepath, mode );\n#endif\n    return fp;\n}\n\nvoid XMLDocument::DeleteNode( XMLNode* node )\t{\n    TIXMLASSERT( node );\n    TIXMLASSERT(node->_document == this );\n    if (node->_parent) {\n        node->_parent->DeleteChild( node );\n    }\n    else {\n        // Isn't in the tree.\n        // Use the parent delete.\n        // Also, we need to mark it tracked: we 'know'\n        // it was never used.\n        node->_memPool->SetTracked();\n        // Call the static XMLNode version:\n        XMLNode::DeleteNode(node);\n    }\n}\n\n\nXMLError XMLDocument::LoadFile( const char* filename )\n{\n    if ( !filename ) {\n        TIXMLASSERT( false );\n        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, \"filename=<null>\" );\n        return _errorID;\n    }\n\n    Clear();\n    FILE* fp = callfopen( filename, \"rb\" );\n    if ( !fp ) {\n        SetError( XML_ERROR_FILE_NOT_FOUND, 0, \"filename=%s\", filename );\n        return _errorID;\n    }\n    LoadFile( fp );\n    fclose( fp );\n    return _errorID;\n}\n\nXMLError XMLDocument::LoadFile( FILE* fp )\n{\n    Clear();\n\n    TIXML_FSEEK( fp, 0, SEEK_SET );\n    if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {\n        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\n        return _errorID;\n    }\n\n    TIXML_FSEEK( fp, 0, SEEK_END );\n\n    unsigned long long filelength;\n    {\n        const long long fileLengthSigned = TIXML_FTELL( fp );\n        TIXML_FSEEK( fp, 0, SEEK_SET );\n        if ( fileLengthSigned == -1L ) {\n            SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\n            return _errorID;\n        }\n        TIXMLASSERT( fileLengthSigned >= 0 );\n        filelength = static_cast<unsigned long long>(fileLengthSigned);\n    }\n\n    const size_t maxSizeT = static_cast<size_t>(-1);\n    // We'll do the comparison as an unsigned long long, because that's guaranteed to be at\n    // least 8 bytes, even on a 32-bit platform.\n    if ( filelength >= static_cast<unsigned long long>(maxSizeT) ) {\n        // Cannot handle files which won't fit in buffer together with null terminator\n        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\n        return _errorID;\n    }\n\n    if ( filelength == 0 ) {\n        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );\n        return _errorID;\n    }\n\n    const size_t size = static_cast<size_t>(filelength);\n    TIXMLASSERT( _charBuffer == 0 );\n    _charBuffer = new char[size+1];\n    const size_t read = fread( _charBuffer, 1, size, fp );\n    if ( read != size ) {\n        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\n        return _errorID;\n    }\n\n    _charBuffer[size] = 0;\n\n    Parse();\n    return _errorID;\n}\n\n\nXMLError XMLDocument::SaveFile( const char* filename, bool compact )\n{\n    if ( !filename ) {\n        TIXMLASSERT( false );\n        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, \"filename=<null>\" );\n        return _errorID;\n    }\n\n    FILE* fp = callfopen( filename, \"w\" );\n    if ( !fp ) {\n        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, \"filename=%s\", filename );\n        return _errorID;\n    }\n    SaveFile(fp, compact);\n    fclose( fp );\n    return _errorID;\n}\n\n\nXMLError XMLDocument::SaveFile( FILE* fp, bool compact )\n{\n    // Clear any error from the last save, otherwise it will get reported\n    // for *this* call.\n    ClearError();\n    XMLPrinter stream( fp, compact );\n    Print( &stream );\n    return _errorID;\n}\n\n\nXMLError XMLDocument::Parse( const char* p, size_t len )\n{\n    Clear();\n\n    if ( len == 0 || !p || !*p ) {\n        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );\n        return _errorID;\n    }\n    if ( len == static_cast<size_t>(-1) ) {\n        len = strlen( p );\n    }\n    TIXMLASSERT( _charBuffer == 0 );\n    _charBuffer = new char[ len+1 ];\n    memcpy( _charBuffer, p, len );\n    _charBuffer[len] = 0;\n\n    Parse();\n    if ( Error() ) {\n        // clean up now essentially dangling memory.\n        // and the parse fail can put objects in the\n        // pools that are dead and inaccessible.\n        DeleteChildren();\n        _elementPool.Clear();\n        _attributePool.Clear();\n        _textPool.Clear();\n        _commentPool.Clear();\n    }\n    return _errorID;\n}\n\n\nvoid XMLDocument::Print( XMLPrinter* streamer ) const\n{\n    if ( streamer ) {\n        Accept( streamer );\n    }\n    else {\n        XMLPrinter stdoutStreamer( stdout );\n        Accept( &stdoutStreamer );\n    }\n}\n\n\nvoid XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... )\n{\n    TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );\n    _errorID = error;\n    _errorLineNum = lineNum;\n\t_errorStr.Reset();\n\n    const size_t BUFFER_SIZE = 1000;\n    char* buffer = new char[BUFFER_SIZE];\n\n    TIXMLASSERT(sizeof(error) <= sizeof(int));\n    TIXML_SNPRINTF(buffer, BUFFER_SIZE, \"Error=%s ErrorID=%d (0x%x) Line number=%d\", ErrorIDToName(error), int(error), int(error), lineNum);\n\n\tif (format) {\n\t\tsize_t len = strlen(buffer);\n\t\tTIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, \": \");\n\t\tlen = strlen(buffer);\n\n\t\tva_list va;\n\t\tva_start(va, format);\n\t\tTIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va);\n\t\tva_end(va);\n\t}\n\t_errorStr.SetStr(buffer);\n\tdelete[] buffer;\n}\n\n\n/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID)\n{\n\tTIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT );\n    const char* errorName = _errorNames[errorID];\n    TIXMLASSERT( errorName && errorName[0] );\n    return errorName;\n}\n\nconst char* XMLDocument::ErrorStr() const\n{\n\treturn _errorStr.Empty() ? \"\" : _errorStr.GetStr();\n}\n\n\nvoid XMLDocument::PrintError() const\n{\n    printf(\"%s\\n\", ErrorStr());\n}\n\nconst char* XMLDocument::ErrorName() const\n{\n    return ErrorIDToName(_errorID);\n}\n\nvoid XMLDocument::Parse()\n{\n    TIXMLASSERT( NoChildren() ); // Clear() must have been called previously\n    TIXMLASSERT( _charBuffer );\n    _parseCurLineNum = 1;\n    _parseLineNum = 1;\n    char* p = _charBuffer;\n    p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );\n    p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );\n    if ( !*p ) {\n        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );\n        return;\n    }\n    ParseDeep(p, 0, &_parseCurLineNum );\n}\n\nvoid XMLDocument::PushDepth()\n{\n\t_parsingDepth++;\n\tif (_parsingDepth == TINYXML2_MAX_ELEMENT_DEPTH) {\n\t\tSetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, \"Element nesting is too deep.\" );\n\t}\n}\n\nvoid XMLDocument::PopDepth()\n{\n\tTIXMLASSERT(_parsingDepth > 0);\n\t--_parsingDepth;\n}\n\nXMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :\n    _elementJustOpened( false ),\n    _stack(),\n    _firstElement( true ),\n    _fp( file ),\n    _depth( depth ),\n    _textDepth( -1 ),\n    _processEntities( true ),\n    _compactMode( compact ),\n    _buffer()\n{\n    for( int i=0; i<ENTITY_RANGE; ++i ) {\n        _entityFlag[i] = false;\n        _restrictedEntityFlag[i] = false;\n    }\n    for( int i=0; i<NUM_ENTITIES; ++i ) {\n        const char entityValue = entities[i].value;\n        const unsigned char flagIndex = static_cast<unsigned char>(entityValue);\n        TIXMLASSERT( flagIndex < ENTITY_RANGE );\n        _entityFlag[flagIndex] = true;\n    }\n    _restrictedEntityFlag[static_cast<unsigned char>('&')] = true;\n    _restrictedEntityFlag[static_cast<unsigned char>('<')] = true;\n    _restrictedEntityFlag[static_cast<unsigned char>('>')] = true;\t// not required, but consistency is nice\n    _buffer.Push( 0 );\n}\n\n\nvoid XMLPrinter::Print( const char* format, ... )\n{\n    va_list     va;\n    va_start( va, format );\n\n    if ( _fp ) {\n        vfprintf( _fp, format, va );\n    }\n    else {\n        const int len = TIXML_VSCPRINTF( format, va );\n        // Close out and re-start the va-args\n        va_end( va );\n        TIXMLASSERT( len >= 0 );\n        va_start( va, format );\n        TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );\n        char* p = _buffer.PushArr( len ) - 1;\t// back up over the null terminator.\n\t\tTIXML_VSNPRINTF( p, len+1, format, va );\n    }\n    va_end( va );\n}\n\n\nvoid XMLPrinter::Write( const char* data, size_t size )\n{\n    if ( _fp ) {\n        fwrite ( data , sizeof(char), size, _fp);\n    }\n    else {\n        char* p = _buffer.PushArr( static_cast<int>(size) ) - 1;   // back up over the null terminator.\n        memcpy( p, data, size );\n        p[size] = 0;\n    }\n}\n\n\nvoid XMLPrinter::Putc( char ch )\n{\n    if ( _fp ) {\n        fputc ( ch, _fp);\n    }\n    else {\n        char* p = _buffer.PushArr( sizeof(char) ) - 1;   // back up over the null terminator.\n        p[0] = ch;\n        p[1] = 0;\n    }\n}\n\n\nvoid XMLPrinter::PrintSpace( int depth )\n{\n    for( int i=0; i<depth; ++i ) {\n        Write( \"    \" );\n    }\n}\n\n\nvoid XMLPrinter::PrintString( const char* p, bool restricted )\n{\n    // Look for runs of bytes between entities to print.\n    const char* q = p;\n\n    if ( _processEntities ) {\n        const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;\n        while ( *q ) {\n            TIXMLASSERT( p <= q );\n            // Remember, char is sometimes signed. (How many times has that bitten me?)\n            if ( *q > 0 && *q < ENTITY_RANGE ) {\n                // Check for entities. If one is found, flush\n                // the stream up until the entity, write the\n                // entity, and keep looking.\n                if ( flag[static_cast<unsigned char>(*q)] ) {\n                    while ( p < q ) {\n                        const size_t delta = q - p;\n                        const int toPrint = ( INT_MAX < delta ) ? INT_MAX : static_cast<int>(delta);\n                        Write( p, toPrint );\n                        p += toPrint;\n                    }\n                    bool entityPatternPrinted = false;\n                    for( int i=0; i<NUM_ENTITIES; ++i ) {\n                        if ( entities[i].value == *q ) {\n                            Putc( '&' );\n                            Write( entities[i].pattern, entities[i].length );\n                            Putc( ';' );\n                            entityPatternPrinted = true;\n                            break;\n                        }\n                    }\n                    if ( !entityPatternPrinted ) {\n                        // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release\n                        TIXMLASSERT( false );\n                    }\n                    ++p;\n                }\n            }\n            ++q;\n            TIXMLASSERT( p <= q );\n        }\n        // Flush the remaining string. This will be the entire\n        // string if an entity wasn't found.\n        if ( p < q ) {\n            const size_t delta = q - p;\n            const int toPrint = ( INT_MAX < delta ) ? INT_MAX : static_cast<int>(delta);\n            Write( p, toPrint );\n        }\n    }\n    else {\n        Write( p );\n    }\n}\n\n\nvoid XMLPrinter::PushHeader( bool writeBOM, bool writeDec )\n{\n    if ( writeBOM ) {\n        static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };\n        Write( reinterpret_cast< const char* >( bom ) );\n    }\n    if ( writeDec ) {\n        PushDeclaration( \"xml version=\\\"1.0\\\"\" );\n    }\n}\n\nvoid XMLPrinter::PrepareForNewNode( bool compactMode )\n{\n    SealElementIfJustOpened();\n\n    if ( compactMode ) {\n        return;\n    }\n\n    if ( _firstElement ) {\n        PrintSpace (_depth);\n    } else if ( _textDepth < 0) {\n        Putc( '\\n' );\n        PrintSpace( _depth );\n    }\n\n    _firstElement = false;\n}\n\nvoid XMLPrinter::OpenElement( const char* name, bool compactMode )\n{\n    PrepareForNewNode( compactMode );\n    _stack.Push( name );\n\n    Write ( \"<\" );\n    Write ( name );\n\n    _elementJustOpened = true;\n    ++_depth;\n}\n\n\nvoid XMLPrinter::PushAttribute( const char* name, const char* value )\n{\n    TIXMLASSERT( _elementJustOpened );\n    Putc ( ' ' );\n    Write( name );\n    Write( \"=\\\"\" );\n    PrintString( value, false );\n    Putc ( '\\\"' );\n}\n\n\nvoid XMLPrinter::PushAttribute( const char* name, int v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    PushAttribute( name, buf );\n}\n\n\nvoid XMLPrinter::PushAttribute( const char* name, unsigned v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    PushAttribute( name, buf );\n}\n\n\nvoid XMLPrinter::PushAttribute(const char* name, int64_t v)\n{\n\tchar buf[BUF_SIZE];\n\tXMLUtil::ToStr(v, buf, BUF_SIZE);\n\tPushAttribute(name, buf);\n}\n\n\nvoid XMLPrinter::PushAttribute(const char* name, uint64_t v)\n{\n\tchar buf[BUF_SIZE];\n\tXMLUtil::ToStr(v, buf, BUF_SIZE);\n\tPushAttribute(name, buf);\n}\n\n\nvoid XMLPrinter::PushAttribute( const char* name, bool v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    PushAttribute( name, buf );\n}\n\n\nvoid XMLPrinter::PushAttribute( const char* name, double v )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( v, buf, BUF_SIZE );\n    PushAttribute( name, buf );\n}\n\n\nvoid XMLPrinter::CloseElement( bool compactMode )\n{\n    --_depth;\n    const char* name = _stack.Pop();\n\n    if ( _elementJustOpened ) {\n        Write( \"/>\" );\n    }\n    else {\n        if ( _textDepth < 0 && !compactMode) {\n            Putc( '\\n' );\n            PrintSpace( _depth );\n        }\n        Write ( \"</\" );\n        Write ( name );\n        Write ( \">\" );\n    }\n\n    if ( _textDepth == _depth ) {\n        _textDepth = -1;\n    }\n    if ( _depth == 0 && !compactMode) {\n        Putc( '\\n' );\n    }\n    _elementJustOpened = false;\n}\n\n\nvoid XMLPrinter::SealElementIfJustOpened()\n{\n    if ( !_elementJustOpened ) {\n        return;\n    }\n    _elementJustOpened = false;\n    Putc( '>' );\n}\n\n\nvoid XMLPrinter::PushText( const char* text, bool cdata )\n{\n    _textDepth = _depth-1;\n\n    SealElementIfJustOpened();\n    if ( cdata ) {\n        Write( \"<![CDATA[\" );\n        Write( text );\n        Write( \"]]>\" );\n    }\n    else {\n        PrintString( text, true );\n    }\n}\n\n\nvoid XMLPrinter::PushText( int64_t value )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( value, buf, BUF_SIZE );\n    PushText( buf, false );\n}\n\n\nvoid XMLPrinter::PushText( uint64_t value )\n{\n\tchar buf[BUF_SIZE];\n\tXMLUtil::ToStr(value, buf, BUF_SIZE);\n\tPushText(buf, false);\n}\n\n\nvoid XMLPrinter::PushText( int value )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( value, buf, BUF_SIZE );\n    PushText( buf, false );\n}\n\n\nvoid XMLPrinter::PushText( unsigned value )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( value, buf, BUF_SIZE );\n    PushText( buf, false );\n}\n\n\nvoid XMLPrinter::PushText( bool value )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( value, buf, BUF_SIZE );\n    PushText( buf, false );\n}\n\n\nvoid XMLPrinter::PushText( float value )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( value, buf, BUF_SIZE );\n    PushText( buf, false );\n}\n\n\nvoid XMLPrinter::PushText( double value )\n{\n    char buf[BUF_SIZE];\n    XMLUtil::ToStr( value, buf, BUF_SIZE );\n    PushText( buf, false );\n}\n\n\nvoid XMLPrinter::PushComment( const char* comment )\n{\n    PrepareForNewNode( _compactMode );\n\n    Write( \"<!--\" );\n    Write( comment );\n    Write( \"-->\" );\n}\n\n\nvoid XMLPrinter::PushDeclaration( const char* value )\n{\n    PrepareForNewNode( _compactMode );\n\n    Write( \"<?\" );\n    Write( value );\n    Write( \"?>\" );\n}\n\n\nvoid XMLPrinter::PushUnknown( const char* value )\n{\n    PrepareForNewNode( _compactMode );\n\n    Write( \"<!\" );\n    Write( value );\n    Putc( '>' );\n}\n\n\nbool XMLPrinter::VisitEnter( const XMLDocument& doc )\n{\n    _processEntities = doc.ProcessEntities();\n    if ( doc.HasBOM() ) {\n        PushHeader( true, false );\n    }\n    return true;\n}\n\n\nbool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )\n{\n    const XMLElement* parentElem = 0;\n    if ( element.Parent() ) {\n        parentElem = element.Parent()->ToElement();\n    }\n    const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;\n    OpenElement( element.Name(), compactMode );\n    while ( attribute ) {\n        PushAttribute( attribute->Name(), attribute->Value() );\n        attribute = attribute->Next();\n    }\n    return true;\n}\n\n\nbool XMLPrinter::VisitExit( const XMLElement& element )\n{\n    CloseElement( CompactMode(element) );\n    return true;\n}\n\n\nbool XMLPrinter::Visit( const XMLText& text )\n{\n    PushText( text.Value(), text.CData() );\n    return true;\n}\n\n\nbool XMLPrinter::Visit( const XMLComment& comment )\n{\n    PushComment( comment.Value() );\n    return true;\n}\n\nbool XMLPrinter::Visit( const XMLDeclaration& declaration )\n{\n    PushDeclaration( declaration.Value() );\n    return true;\n}\n\n\nbool XMLPrinter::Visit( const XMLUnknown& unknown )\n{\n    PushUnknown( unknown.Value() );\n    return true;\n}\n\n}   // namespace tinyxml2\n"
  },
  {
    "path": "TrafficMonitor/tinyxml2/tinyxml2.h",
    "content": "/*\nOriginal code by Lee Thomason (www.grinninglizard.com)\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any\ndamages arising from the use of this software.\n\nPermission is granted to anyone to use this software for any\npurpose, including commercial applications, and to alter it and\nredistribute it freely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must\nnot claim that you wrote the original software. If you use this\nsoftware in a product, an acknowledgment in the product documentation\nwould be appreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and\nmust not be misrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source\ndistribution.\n*/\n\n#ifndef TINYXML2_INCLUDED\n#define TINYXML2_INCLUDED\n\n#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)\n#   include <ctype.h>\n#   include <limits.h>\n#   include <stdio.h>\n#   include <stdlib.h>\n#   include <string.h>\n#\tif defined(__PS3__)\n#\t\tinclude <stddef.h>\n#\tendif\n#else\n#   include <cctype>\n#   include <climits>\n#   include <cstdio>\n#   include <cstdlib>\n#   include <cstring>\n#endif\n#include <stdint.h>\n\n/*\n   TODO: intern strings instead of allocation.\n*/\n/*\n\tgcc:\n        g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe\n\n    Formatting, Artistic Style:\n        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h\n*/\n\n#if defined( _DEBUG ) || defined (__DEBUG__)\n#   ifndef TINYXML2_DEBUG\n#       define TINYXML2_DEBUG\n#   endif\n#endif\n\n#ifdef _MSC_VER\n#   pragma warning(push)\n#   pragma warning(disable: 4251)\n#endif\n\n#ifdef _WIN32\n#   ifdef TINYXML2_EXPORT\n#       define TINYXML2_LIB __declspec(dllexport)\n#   elif defined(TINYXML2_IMPORT)\n#       define TINYXML2_LIB __declspec(dllimport)\n#   else\n#       define TINYXML2_LIB\n#   endif\n#elif __GNUC__ >= 4\n#   define TINYXML2_LIB __attribute__((visibility(\"default\")))\n#else\n#   define TINYXML2_LIB\n#endif\n\n\n#if defined(TINYXML2_DEBUG)\n#   if defined(_MSC_VER)\n#       // \"(void)0,\" is for suppressing C4127 warning in \"assert(false)\", \"assert(true)\" and the like\n#       define TIXMLASSERT( x )           if ( !((void)0,(x))) { __debugbreak(); }\n#   elif defined (ANDROID_NDK)\n#       include <android/log.h>\n#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( \"assert\", \"grinliz\", \"ASSERT in '%s' at %d.\", __FILE__, __LINE__ ); }\n#   else\n#       include <assert.h>\n#       define TIXMLASSERT                assert\n#   endif\n#else\n#   define TIXMLASSERT( x )               {}\n#endif\n\n\n/* Versioning, past 1.0.14:\n\thttp://semver.org/\n*/\nstatic const int TIXML2_MAJOR_VERSION = 8;\nstatic const int TIXML2_MINOR_VERSION = 0;\nstatic const int TIXML2_PATCH_VERSION = 0;\n\n#define TINYXML2_MAJOR_VERSION 8\n#define TINYXML2_MINOR_VERSION 0\n#define TINYXML2_PATCH_VERSION 0\n\n// A fixed element depth limit is problematic. There needs to be a\n// limit to avoid a stack overflow. However, that limit varies per\n// system, and the capacity of the stack. On the other hand, it's a trivial\n// attack that can result from ill, malicious, or even correctly formed XML,\n// so there needs to be a limit in place.\nstatic const int TINYXML2_MAX_ELEMENT_DEPTH = 100;\n\nnamespace tinyxml2\n{\nclass XMLDocument;\nclass XMLElement;\nclass XMLAttribute;\nclass XMLComment;\nclass XMLText;\nclass XMLDeclaration;\nclass XMLUnknown;\nclass XMLPrinter;\n\n/*\n\tA class that wraps strings. Normally stores the start and end\n\tpointers into the XML file itself, and will apply normalization\n\tand entity translation if actually read. Can also store (and memory\n\tmanage) a traditional char[]\n\n    Isn't clear why TINYXML2_LIB is needed; but seems to fix #719\n*/\nclass TINYXML2_LIB StrPair\n{\npublic:\n    enum {\n        NEEDS_ENTITY_PROCESSING\t\t\t= 0x01,\n        NEEDS_NEWLINE_NORMALIZATION\t\t= 0x02,\n        NEEDS_WHITESPACE_COLLAPSING     = 0x04,\n\n        TEXT_ELEMENT\t\t            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,\n        TEXT_ELEMENT_LEAVE_ENTITIES\t\t= NEEDS_NEWLINE_NORMALIZATION,\n        ATTRIBUTE_NAME\t\t            = 0,\n        ATTRIBUTE_VALUE\t\t            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,\n        ATTRIBUTE_VALUE_LEAVE_ENTITIES  = NEEDS_NEWLINE_NORMALIZATION,\n        COMMENT\t\t\t\t\t\t\t= NEEDS_NEWLINE_NORMALIZATION\n    };\n\n    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}\n    ~StrPair();\n\n    void Set( char* start, char* end, int flags ) {\n        TIXMLASSERT( start );\n        TIXMLASSERT( end );\n        Reset();\n        _start  = start;\n        _end    = end;\n        _flags  = flags | NEEDS_FLUSH;\n    }\n\n    const char* GetStr();\n\n    bool Empty() const {\n        return _start == _end;\n    }\n\n    void SetInternedStr( const char* str ) {\n        Reset();\n        _start = const_cast<char*>(str);\n    }\n\n    void SetStr( const char* str, int flags=0 );\n\n    char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );\n    char* ParseName( char* in );\n\n    void TransferTo( StrPair* other );\n\tvoid Reset();\n\nprivate:\n    void CollapseWhitespace();\n\n    enum {\n        NEEDS_FLUSH = 0x100,\n        NEEDS_DELETE = 0x200\n    };\n\n    int     _flags;\n    char*   _start;\n    char*   _end;\n\n    StrPair( const StrPair& other );\t// not supported\n    void operator=( const StrPair& other );\t// not supported, use TransferTo()\n};\n\n\n/*\n\tA dynamic array of Plain Old Data. Doesn't support constructors, etc.\n\tHas a small initial memory pool, so that low or no usage will not\n\tcause a call to new/delete\n*/\ntemplate <class T, int INITIAL_SIZE>\nclass DynArray\n{\npublic:\n    DynArray() :\n        _mem( _pool ),\n        _allocated( INITIAL_SIZE ),\n        _size( 0 )\n    {\n    }\n\n    ~DynArray() {\n        if ( _mem != _pool ) {\n            delete [] _mem;\n        }\n    }\n\n    void Clear() {\n        _size = 0;\n    }\n\n    void Push( T t ) {\n        TIXMLASSERT( _size < INT_MAX );\n        EnsureCapacity( _size+1 );\n        _mem[_size] = t;\n        ++_size;\n    }\n\n    T* PushArr( int count ) {\n        TIXMLASSERT( count >= 0 );\n        TIXMLASSERT( _size <= INT_MAX - count );\n        EnsureCapacity( _size+count );\n        T* ret = &_mem[_size];\n        _size += count;\n        return ret;\n    }\n\n    T Pop() {\n        TIXMLASSERT( _size > 0 );\n        --_size;\n        return _mem[_size];\n    }\n\n    void PopArr( int count ) {\n        TIXMLASSERT( _size >= count );\n        _size -= count;\n    }\n\n    bool Empty() const\t\t\t\t\t{\n        return _size == 0;\n    }\n\n    T& operator[](int i)\t\t\t\t{\n        TIXMLASSERT( i>= 0 && i < _size );\n        return _mem[i];\n    }\n\n    const T& operator[](int i) const\t{\n        TIXMLASSERT( i>= 0 && i < _size );\n        return _mem[i];\n    }\n\n    const T& PeekTop() const            {\n        TIXMLASSERT( _size > 0 );\n        return _mem[ _size - 1];\n    }\n\n    int Size() const\t\t\t\t\t{\n        TIXMLASSERT( _size >= 0 );\n        return _size;\n    }\n\n    int Capacity() const\t\t\t\t{\n        TIXMLASSERT( _allocated >= INITIAL_SIZE );\n        return _allocated;\n    }\n\n\tvoid SwapRemove(int i) {\n\t\tTIXMLASSERT(i >= 0 && i < _size);\n\t\tTIXMLASSERT(_size > 0);\n\t\t_mem[i] = _mem[_size - 1];\n\t\t--_size;\n\t}\n\n    const T* Mem() const\t\t\t\t{\n        TIXMLASSERT( _mem );\n        return _mem;\n    }\n\n    T* Mem() {\n        TIXMLASSERT( _mem );\n        return _mem;\n    }\n\nprivate:\n    DynArray( const DynArray& ); // not supported\n    void operator=( const DynArray& ); // not supported\n\n    void EnsureCapacity( int cap ) {\n        TIXMLASSERT( cap > 0 );\n        if ( cap > _allocated ) {\n            TIXMLASSERT( cap <= INT_MAX / 2 );\n            const int newAllocated = cap * 2;\n            T* newMem = new T[newAllocated];\n            TIXMLASSERT( newAllocated >= _size );\n            memcpy( newMem, _mem, sizeof(T)*_size );\t// warning: not using constructors, only works for PODs\n            if ( _mem != _pool ) {\n                delete [] _mem;\n            }\n            _mem = newMem;\n            _allocated = newAllocated;\n        }\n    }\n\n    T*  _mem;\n    T   _pool[INITIAL_SIZE];\n    int _allocated;\t\t// objects allocated\n    int _size;\t\t\t// number objects in use\n};\n\n\n/*\n\tParent virtual class of a pool for fast allocation\n\tand deallocation of objects.\n*/\nclass MemPool\n{\npublic:\n    MemPool() {}\n    virtual ~MemPool() {}\n\n    virtual int ItemSize() const = 0;\n    virtual void* Alloc() = 0;\n    virtual void Free( void* ) = 0;\n    virtual void SetTracked() = 0;\n};\n\n\n/*\n\tTemplate child class to create pools of the correct type.\n*/\ntemplate< int ITEM_SIZE >\nclass MemPoolT : public MemPool\n{\npublic:\n    MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)\t{}\n    ~MemPoolT() {\n        MemPoolT< ITEM_SIZE >::Clear();\n    }\n\n    void Clear() {\n        // Delete the blocks.\n        while( !_blockPtrs.Empty()) {\n            Block* lastBlock = _blockPtrs.Pop();\n            delete lastBlock;\n        }\n        _root = 0;\n        _currentAllocs = 0;\n        _nAllocs = 0;\n        _maxAllocs = 0;\n        _nUntracked = 0;\n    }\n\n    virtual int ItemSize() const\t{\n        return ITEM_SIZE;\n    }\n    int CurrentAllocs() const\t\t{\n        return _currentAllocs;\n    }\n\n    virtual void* Alloc() {\n        if ( !_root ) {\n            // Need a new block.\n            Block* block = new Block();\n            _blockPtrs.Push( block );\n\n            Item* blockItems = block->items;\n            for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {\n                blockItems[i].next = &(blockItems[i + 1]);\n            }\n            blockItems[ITEMS_PER_BLOCK - 1].next = 0;\n            _root = blockItems;\n        }\n        Item* const result = _root;\n        TIXMLASSERT( result != 0 );\n        _root = _root->next;\n\n        ++_currentAllocs;\n        if ( _currentAllocs > _maxAllocs ) {\n            _maxAllocs = _currentAllocs;\n        }\n        ++_nAllocs;\n        ++_nUntracked;\n        return result;\n    }\n\n    virtual void Free( void* mem ) {\n        if ( !mem ) {\n            return;\n        }\n        --_currentAllocs;\n        Item* item = static_cast<Item*>( mem );\n#ifdef TINYXML2_DEBUG\n        memset( item, 0xfe, sizeof( *item ) );\n#endif\n        item->next = _root;\n        _root = item;\n    }\n    void Trace( const char* name ) {\n        printf( \"Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\\n\",\n                name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,\n                ITEM_SIZE, _nAllocs, _blockPtrs.Size() );\n    }\n\n    void SetTracked() {\n        --_nUntracked;\n    }\n\n    int Untracked() const {\n        return _nUntracked;\n    }\n\n\t// This number is perf sensitive. 4k seems like a good tradeoff on my machine.\n\t// The test file is large, 170k.\n\t// Release:\t\tVS2010 gcc(no opt)\n\t//\t\t1k:\t\t4000\n\t//\t\t2k:\t\t4000\n\t//\t\t4k:\t\t3900\t21000\n\t//\t\t16k:\t5200\n\t//\t\t32k:\t4300\n\t//\t\t64k:\t4000\t21000\n    // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK\n    // in private part if ITEMS_PER_BLOCK is private\n    enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };\n\nprivate:\n    MemPoolT( const MemPoolT& ); // not supported\n    void operator=( const MemPoolT& ); // not supported\n\n    union Item {\n        Item*   next;\n        char    itemData[ITEM_SIZE];\n    };\n    struct Block {\n        Item items[ITEMS_PER_BLOCK];\n    };\n    DynArray< Block*, 10 > _blockPtrs;\n    Item* _root;\n\n    int _currentAllocs;\n    int _nAllocs;\n    int _maxAllocs;\n    int _nUntracked;\n};\n\n\n\n/**\n\tImplements the interface to the \"Visitor pattern\" (see the Accept() method.)\n\tIf you call the Accept() method, it requires being passed a XMLVisitor\n\tclass to handle callbacks. For nodes that contain other nodes (Document, Element)\n\tyou will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs\n\tare simply called with Visit().\n\n\tIf you return 'true' from a Visit method, recursive parsing will continue. If you return\n\tfalse, <b>no children of this node or its siblings</b> will be visited.\n\n\tAll flavors of Visit methods have a default implementation that returns 'true' (continue\n\tvisiting). You need to only override methods that are interesting to you.\n\n\tGenerally Accept() is called on the XMLDocument, although all nodes support visiting.\n\n\tYou should never change the document from a callback.\n\n\t@sa XMLNode::Accept()\n*/\nclass TINYXML2_LIB XMLVisitor\n{\npublic:\n    virtual ~XMLVisitor() {}\n\n    /// Visit a document.\n    virtual bool VisitEnter( const XMLDocument& /*doc*/ )\t\t\t{\n        return true;\n    }\n    /// Visit a document.\n    virtual bool VisitExit( const XMLDocument& /*doc*/ )\t\t\t{\n        return true;\n    }\n\n    /// Visit an element.\n    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )\t{\n        return true;\n    }\n    /// Visit an element.\n    virtual bool VisitExit( const XMLElement& /*element*/ )\t\t\t{\n        return true;\n    }\n\n    /// Visit a declaration.\n    virtual bool Visit( const XMLDeclaration& /*declaration*/ )\t\t{\n        return true;\n    }\n    /// Visit a text node.\n    virtual bool Visit( const XMLText& /*text*/ )\t\t\t\t\t{\n        return true;\n    }\n    /// Visit a comment node.\n    virtual bool Visit( const XMLComment& /*comment*/ )\t\t\t\t{\n        return true;\n    }\n    /// Visit an unknown node.\n    virtual bool Visit( const XMLUnknown& /*unknown*/ )\t\t\t\t{\n        return true;\n    }\n};\n\n// WARNING: must match XMLDocument::_errorNames[]\nenum XMLError {\n    XML_SUCCESS = 0,\n    XML_NO_ATTRIBUTE,\n    XML_WRONG_ATTRIBUTE_TYPE,\n    XML_ERROR_FILE_NOT_FOUND,\n    XML_ERROR_FILE_COULD_NOT_BE_OPENED,\n    XML_ERROR_FILE_READ_ERROR,\n    XML_ERROR_PARSING_ELEMENT,\n    XML_ERROR_PARSING_ATTRIBUTE,\n    XML_ERROR_PARSING_TEXT,\n    XML_ERROR_PARSING_CDATA,\n    XML_ERROR_PARSING_COMMENT,\n    XML_ERROR_PARSING_DECLARATION,\n    XML_ERROR_PARSING_UNKNOWN,\n    XML_ERROR_EMPTY_DOCUMENT,\n    XML_ERROR_MISMATCHED_ELEMENT,\n    XML_ERROR_PARSING,\n    XML_CAN_NOT_CONVERT_TEXT,\n    XML_NO_TEXT_NODE,\n\tXML_ELEMENT_DEPTH_EXCEEDED,\n\n\tXML_ERROR_COUNT\n};\n\n\n/*\n\tUtility functionality.\n*/\nclass TINYXML2_LIB XMLUtil\n{\npublic:\n    static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr )\t{\n        TIXMLASSERT( p );\n\n        while( IsWhiteSpace(*p) ) {\n            if (curLineNumPtr && *p == '\\n') {\n                ++(*curLineNumPtr);\n            }\n            ++p;\n        }\n        TIXMLASSERT( p );\n        return p;\n    }\n    static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) {\n        return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );\n    }\n\n    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't\n    // correct, but simple, and usually works.\n    static bool IsWhiteSpace( char p )\t\t\t\t\t{\n        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );\n    }\n\n    inline static bool IsNameStartChar( unsigned char ch ) {\n        if ( ch >= 128 ) {\n            // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()\n            return true;\n        }\n        if ( isalpha( ch ) ) {\n            return true;\n        }\n        return ch == ':' || ch == '_';\n    }\n\n    inline static bool IsNameChar( unsigned char ch ) {\n        return IsNameStartChar( ch )\n               || isdigit( ch )\n               || ch == '.'\n               || ch == '-';\n    }\n\n    inline static bool IsPrefixHex( const char* p) {\n        p = SkipWhiteSpace(p, 0);\n        return p && *p == '0' && ( *(p + 1) == 'x' || *(p + 1) == 'X');\n    }\n\n    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {\n        if ( p == q ) {\n            return true;\n        }\n        TIXMLASSERT( p );\n        TIXMLASSERT( q );\n        TIXMLASSERT( nChar >= 0 );\n        return strncmp( p, q, nChar ) == 0;\n    }\n\n    inline static bool IsUTF8Continuation( const char p ) {\n        return ( p & 0x80 ) != 0;\n    }\n\n    static const char* ReadBOM( const char* p, bool* hasBOM );\n    // p is the starting location,\n    // the UTF-8 value of the entity will be placed in value, and length filled in.\n    static const char* GetCharacterRef( const char* p, char* value, int* length );\n    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );\n\n    // converts primitive types to strings\n    static void ToStr( int v, char* buffer, int bufferSize );\n    static void ToStr( unsigned v, char* buffer, int bufferSize );\n    static void ToStr( bool v, char* buffer, int bufferSize );\n    static void ToStr( float v, char* buffer, int bufferSize );\n    static void ToStr( double v, char* buffer, int bufferSize );\n\tstatic void ToStr(int64_t v, char* buffer, int bufferSize);\n    static void ToStr(uint64_t v, char* buffer, int bufferSize);\n\n    // converts strings to primitive types\n    static bool\tToInt( const char* str, int* value );\n    static bool ToUnsigned( const char* str, unsigned* value );\n    static bool\tToBool( const char* str, bool* value );\n    static bool\tToFloat( const char* str, float* value );\n    static bool ToDouble( const char* str, double* value );\n\tstatic bool ToInt64(const char* str, int64_t* value);\n    static bool ToUnsigned64(const char* str, uint64_t* value);\n\t// Changes what is serialized for a boolean value.\n\t// Default to \"true\" and \"false\". Shouldn't be changed\n\t// unless you have a special testing or compatibility need.\n\t// Be careful: static, global, & not thread safe.\n\t// Be sure to set static const memory as parameters.\n\tstatic void SetBoolSerialization(const char* writeTrue, const char* writeFalse);\n\nprivate:\n\tstatic const char* writeBoolTrue;\n\tstatic const char* writeBoolFalse;\n};\n\n\n/** XMLNode is a base class for every object that is in the\n\tXML Document Object Model (DOM), except XMLAttributes.\n\tNodes have siblings, a parent, and children which can\n\tbe navigated. A node is always in a XMLDocument.\n\tThe type of a XMLNode can be queried, and it can\n\tbe cast to its more defined type.\n\n\tA XMLDocument allocates memory for all its Nodes.\n\tWhen the XMLDocument gets deleted, all its Nodes\n\twill also be deleted.\n\n\t@verbatim\n\tA Document can contain:\tElement\t(container or leaf)\n\t\t\t\t\t\t\tComment (leaf)\n\t\t\t\t\t\t\tUnknown (leaf)\n\t\t\t\t\t\t\tDeclaration( leaf )\n\n\tAn Element can contain:\tElement (container or leaf)\n\t\t\t\t\t\t\tText\t(leaf)\n\t\t\t\t\t\t\tAttributes (not on tree)\n\t\t\t\t\t\t\tComment (leaf)\n\t\t\t\t\t\t\tUnknown (leaf)\n\n\t@endverbatim\n*/\nclass TINYXML2_LIB XMLNode\n{\n    friend class XMLDocument;\n    friend class XMLElement;\npublic:\n\n    /// Get the XMLDocument that owns this XMLNode.\n    const XMLDocument* GetDocument() const\t{\n        TIXMLASSERT( _document );\n        return _document;\n    }\n    /// Get the XMLDocument that owns this XMLNode.\n    XMLDocument* GetDocument()\t\t\t\t{\n        TIXMLASSERT( _document );\n        return _document;\n    }\n\n    /// Safely cast to an Element, or null.\n    virtual XMLElement*\t\tToElement()\t\t{\n        return 0;\n    }\n    /// Safely cast to Text, or null.\n    virtual XMLText*\t\tToText()\t\t{\n        return 0;\n    }\n    /// Safely cast to a Comment, or null.\n    virtual XMLComment*\t\tToComment()\t\t{\n        return 0;\n    }\n    /// Safely cast to a Document, or null.\n    virtual XMLDocument*\tToDocument()\t{\n        return 0;\n    }\n    /// Safely cast to a Declaration, or null.\n    virtual XMLDeclaration*\tToDeclaration()\t{\n        return 0;\n    }\n    /// Safely cast to an Unknown, or null.\n    virtual XMLUnknown*\t\tToUnknown()\t\t{\n        return 0;\n    }\n\n    virtual const XMLElement*\t\tToElement() const\t\t{\n        return 0;\n    }\n    virtual const XMLText*\t\t\tToText() const\t\t\t{\n        return 0;\n    }\n    virtual const XMLComment*\t\tToComment() const\t\t{\n        return 0;\n    }\n    virtual const XMLDocument*\t\tToDocument() const\t\t{\n        return 0;\n    }\n    virtual const XMLDeclaration*\tToDeclaration() const\t{\n        return 0;\n    }\n    virtual const XMLUnknown*\t\tToUnknown() const\t\t{\n        return 0;\n    }\n\n    /** The meaning of 'value' changes for the specific type.\n    \t@verbatim\n    \tDocument:\tempty (NULL is returned, not an empty string)\n    \tElement:\tname of the element\n    \tComment:\tthe comment text\n    \tUnknown:\tthe tag contents\n    \tText:\t\tthe text string\n    \t@endverbatim\n    */\n    const char* Value() const;\n\n    /** Set the Value of an XML node.\n    \t@sa Value()\n    */\n    void SetValue( const char* val, bool staticMem=false );\n\n    /// Gets the line number the node is in, if the document was parsed from a file.\n    int GetLineNum() const { return _parseLineNum; }\n\n    /// Get the parent of this node on the DOM.\n    const XMLNode*\tParent() const\t\t\t{\n        return _parent;\n    }\n\n    XMLNode* Parent()\t\t\t\t\t\t{\n        return _parent;\n    }\n\n    /// Returns true if this node has no children.\n    bool NoChildren() const\t\t\t\t\t{\n        return !_firstChild;\n    }\n\n    /// Get the first child node, or null if none exists.\n    const XMLNode*  FirstChild() const\t\t{\n        return _firstChild;\n    }\n\n    XMLNode*\t\tFirstChild()\t\t\t{\n        return _firstChild;\n    }\n\n    /** Get the first child element, or optionally the first child\n        element with the specified name.\n    */\n    const XMLElement* FirstChildElement( const char* name = 0 ) const;\n\n    XMLElement* FirstChildElement( const char* name = 0 )\t{\n        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));\n    }\n\n    /// Get the last child node, or null if none exists.\n    const XMLNode*\tLastChild() const\t\t\t\t\t\t{\n        return _lastChild;\n    }\n\n    XMLNode*\t\tLastChild()\t\t\t\t\t\t\t\t{\n        return _lastChild;\n    }\n\n    /** Get the last child element or optionally the last child\n        element with the specified name.\n    */\n    const XMLElement* LastChildElement( const char* name = 0 ) const;\n\n    XMLElement* LastChildElement( const char* name = 0 )\t{\n        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );\n    }\n\n    /// Get the previous (left) sibling node of this node.\n    const XMLNode*\tPreviousSibling() const\t\t\t\t\t{\n        return _prev;\n    }\n\n    XMLNode*\tPreviousSibling()\t\t\t\t\t\t\t{\n        return _prev;\n    }\n\n    /// Get the previous (left) sibling element of this node, with an optionally supplied name.\n    const XMLElement*\tPreviousSiblingElement( const char* name = 0 ) const ;\n\n    XMLElement*\tPreviousSiblingElement( const char* name = 0 ) {\n        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );\n    }\n\n    /// Get the next (right) sibling node of this node.\n    const XMLNode*\tNextSibling() const\t\t\t\t\t\t{\n        return _next;\n    }\n\n    XMLNode*\tNextSibling()\t\t\t\t\t\t\t\t{\n        return _next;\n    }\n\n    /// Get the next (right) sibling element of this node, with an optionally supplied name.\n    const XMLElement*\tNextSiblingElement( const char* name = 0 ) const;\n\n    XMLElement*\tNextSiblingElement( const char* name = 0 )\t{\n        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );\n    }\n\n    /**\n    \tAdd a child node as the last (right) child.\n\t\tIf the child node is already part of the document,\n\t\tit is moved from its old location to the new location.\n\t\tReturns the addThis argument or 0 if the node does not\n\t\tbelong to the same document.\n    */\n    XMLNode* InsertEndChild( XMLNode* addThis );\n\n    XMLNode* LinkEndChild( XMLNode* addThis )\t{\n        return InsertEndChild( addThis );\n    }\n    /**\n    \tAdd a child node as the first (left) child.\n\t\tIf the child node is already part of the document,\n\t\tit is moved from its old location to the new location.\n\t\tReturns the addThis argument or 0 if the node does not\n\t\tbelong to the same document.\n    */\n    XMLNode* InsertFirstChild( XMLNode* addThis );\n    /**\n    \tAdd a node after the specified child node.\n\t\tIf the child node is already part of the document,\n\t\tit is moved from its old location to the new location.\n\t\tReturns the addThis argument or 0 if the afterThis node\n\t\tis not a child of this node, or if the node does not\n\t\tbelong to the same document.\n    */\n    XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );\n\n    /**\n    \tDelete all the children of this node.\n    */\n    void DeleteChildren();\n\n    /**\n    \tDelete a child of this node.\n    */\n    void DeleteChild( XMLNode* node );\n\n    /**\n    \tMake a copy of this node, but not its children.\n    \tYou may pass in a Document pointer that will be\n    \tthe owner of the new Node. If the 'document' is\n    \tnull, then the node returned will be allocated\n    \tfrom the current Document. (this->GetDocument())\n\n    \tNote: if called on a XMLDocument, this will return null.\n    */\n    virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;\n\n\t/**\n\t\tMake a copy of this node and all its children.\n\n\t\tIf the 'target' is null, then the nodes will\n\t\tbe allocated in the current document. If 'target'\n        is specified, the memory will be allocated is the\n        specified XMLDocument.\n\n\t\tNOTE: This is probably not the correct tool to\n\t\tcopy a document, since XMLDocuments can have multiple\n\t\ttop level XMLNodes. You probably want to use\n        XMLDocument::DeepCopy()\n\t*/\n\tXMLNode* DeepClone( XMLDocument* target ) const;\n\n    /**\n    \tTest if 2 nodes are the same, but don't test children.\n    \tThe 2 nodes do not need to be in the same Document.\n\n    \tNote: if called on a XMLDocument, this will return false.\n    */\n    virtual bool ShallowEqual( const XMLNode* compare ) const = 0;\n\n    /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the\n    \tXML tree will be conditionally visited and the host will be called back\n    \tvia the XMLVisitor interface.\n\n    \tThis is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse\n    \tthe XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this\n    \tinterface versus any other.)\n\n    \tThe interface has been based on ideas from:\n\n    \t- http://www.saxproject.org/\n    \t- http://c2.com/cgi/wiki?HierarchicalVisitorPattern\n\n    \tWhich are both good references for \"visiting\".\n\n    \tAn example of using Accept():\n    \t@verbatim\n    \tXMLPrinter printer;\n    \ttinyxmlDoc.Accept( &printer );\n    \tconst char* xmlcstr = printer.CStr();\n    \t@endverbatim\n    */\n    virtual bool Accept( XMLVisitor* visitor ) const = 0;\n\n\t/**\n\t\tSet user data into the XMLNode. TinyXML-2 in\n\t\tno way processes or interprets user data.\n\t\tIt is initially 0.\n\t*/\n\tvoid SetUserData(void* userData)\t{ _userData = userData; }\n\n\t/**\n\t\tGet user data set into the XMLNode. TinyXML-2 in\n\t\tno way processes or interprets user data.\n\t\tIt is initially 0.\n\t*/\n\tvoid* GetUserData() const\t\t\t{ return _userData; }\n\nprotected:\n    explicit XMLNode( XMLDocument* );\n    virtual ~XMLNode();\n\n    virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);\n\n    XMLDocument*\t_document;\n    XMLNode*\t\t_parent;\n    mutable StrPair\t_value;\n    int             _parseLineNum;\n\n    XMLNode*\t\t_firstChild;\n    XMLNode*\t\t_lastChild;\n\n    XMLNode*\t\t_prev;\n    XMLNode*\t\t_next;\n\n\tvoid*\t\t\t_userData;\n\nprivate:\n    MemPool*\t\t_memPool;\n    void Unlink( XMLNode* child );\n    static void DeleteNode( XMLNode* node );\n    void InsertChildPreamble( XMLNode* insertThis ) const;\n    const XMLElement* ToElementWithName( const char* name ) const;\n\n    XMLNode( const XMLNode& );\t// not supported\n    XMLNode& operator=( const XMLNode& );\t// not supported\n};\n\n\n/** XML text.\n\n\tNote that a text node can have child element nodes, for example:\n\t@verbatim\n\t<root>This is <b>bold</b></root>\n\t@endverbatim\n\n\tA text node can have 2 ways to output the next. \"normal\" output\n\tand CDATA. It will default to the mode it was parsed from the XML file and\n\tyou generally want to leave it alone, but you can change the output mode with\n\tSetCData() and query it with CData().\n*/\nclass TINYXML2_LIB XMLText : public XMLNode\n{\n    friend class XMLDocument;\npublic:\n    virtual bool Accept( XMLVisitor* visitor ) const;\n\n    virtual XMLText* ToText()\t\t\t{\n        return this;\n    }\n    virtual const XMLText* ToText() const\t{\n        return this;\n    }\n\n    /// Declare whether this should be CDATA or standard text.\n    void SetCData( bool isCData )\t\t\t{\n        _isCData = isCData;\n    }\n    /// Returns true if this is a CDATA text element.\n    bool CData() const\t\t\t\t\t\t{\n        return _isCData;\n    }\n\n    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\n    virtual bool ShallowEqual( const XMLNode* compare ) const;\n\nprotected:\n    explicit XMLText( XMLDocument* doc )\t: XMLNode( doc ), _isCData( false )\t{}\n    virtual ~XMLText()\t\t\t\t\t\t\t\t\t\t\t\t{}\n\n    char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );\n\nprivate:\n    bool _isCData;\n\n    XMLText( const XMLText& );\t// not supported\n    XMLText& operator=( const XMLText& );\t// not supported\n};\n\n\n/** An XML Comment. */\nclass TINYXML2_LIB XMLComment : public XMLNode\n{\n    friend class XMLDocument;\npublic:\n    virtual XMLComment*\tToComment()\t\t\t\t\t{\n        return this;\n    }\n    virtual const XMLComment* ToComment() const\t\t{\n        return this;\n    }\n\n    virtual bool Accept( XMLVisitor* visitor ) const;\n\n    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\n    virtual bool ShallowEqual( const XMLNode* compare ) const;\n\nprotected:\n    explicit XMLComment( XMLDocument* doc );\n    virtual ~XMLComment();\n\n    char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);\n\nprivate:\n    XMLComment( const XMLComment& );\t// not supported\n    XMLComment& operator=( const XMLComment& );\t// not supported\n};\n\n\n/** In correct XML the declaration is the first entry in the file.\n\t@verbatim\n\t\t<?xml version=\"1.0\" standalone=\"yes\"?>\n\t@endverbatim\n\n\tTinyXML-2 will happily read or write files without a declaration,\n\thowever.\n\n\tThe text of the declaration isn't interpreted. It is parsed\n\tand written as a string.\n*/\nclass TINYXML2_LIB XMLDeclaration : public XMLNode\n{\n    friend class XMLDocument;\npublic:\n    virtual XMLDeclaration*\tToDeclaration()\t\t\t\t\t{\n        return this;\n    }\n    virtual const XMLDeclaration* ToDeclaration() const\t\t{\n        return this;\n    }\n\n    virtual bool Accept( XMLVisitor* visitor ) const;\n\n    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\n    virtual bool ShallowEqual( const XMLNode* compare ) const;\n\nprotected:\n    explicit XMLDeclaration( XMLDocument* doc );\n    virtual ~XMLDeclaration();\n\n    char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );\n\nprivate:\n    XMLDeclaration( const XMLDeclaration& );\t// not supported\n    XMLDeclaration& operator=( const XMLDeclaration& );\t// not supported\n};\n\n\n/** Any tag that TinyXML-2 doesn't recognize is saved as an\n\tunknown. It is a tag of text, but should not be modified.\n\tIt will be written back to the XML, unchanged, when the file\n\tis saved.\n\n\tDTD tags get thrown into XMLUnknowns.\n*/\nclass TINYXML2_LIB XMLUnknown : public XMLNode\n{\n    friend class XMLDocument;\npublic:\n    virtual XMLUnknown*\tToUnknown()\t\t\t\t\t{\n        return this;\n    }\n    virtual const XMLUnknown* ToUnknown() const\t\t{\n        return this;\n    }\n\n    virtual bool Accept( XMLVisitor* visitor ) const;\n\n    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\n    virtual bool ShallowEqual( const XMLNode* compare ) const;\n\nprotected:\n    explicit XMLUnknown( XMLDocument* doc );\n    virtual ~XMLUnknown();\n\n    char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );\n\nprivate:\n    XMLUnknown( const XMLUnknown& );\t// not supported\n    XMLUnknown& operator=( const XMLUnknown& );\t// not supported\n};\n\n\n\n/** An attribute is a name-value pair. Elements have an arbitrary\n\tnumber of attributes, each with a unique name.\n\n\t@note The attributes are not XMLNodes. You may only query the\n\tNext() attribute in a list.\n*/\nclass TINYXML2_LIB XMLAttribute\n{\n    friend class XMLElement;\npublic:\n    /// The name of the attribute.\n    const char* Name() const;\n\n    /// The value of the attribute.\n    const char* Value() const;\n\n    /// Gets the line number the attribute is in, if the document was parsed from a file.\n    int GetLineNum() const { return _parseLineNum; }\n\n    /// The next attribute in the list.\n    const XMLAttribute* Next() const {\n        return _next;\n    }\n\n    /** IntValue interprets the attribute as an integer, and returns the value.\n        If the value isn't an integer, 0 will be returned. There is no error checking;\n    \tuse QueryIntValue() if you need error checking.\n    */\n\tint\tIntValue() const {\n\t\tint i = 0;\n\t\tQueryIntValue(&i);\n\t\treturn i;\n\t}\n\n\tint64_t Int64Value() const {\n\t\tint64_t i = 0;\n\t\tQueryInt64Value(&i);\n\t\treturn i;\n\t}\n\n    uint64_t Unsigned64Value() const {\n        uint64_t i = 0;\n        QueryUnsigned64Value(&i);\n        return i;\n    }\n\n    /// Query as an unsigned integer. See IntValue()\n    unsigned UnsignedValue() const\t\t\t{\n        unsigned i=0;\n        QueryUnsignedValue( &i );\n        return i;\n    }\n    /// Query as a boolean. See IntValue()\n    bool\t BoolValue() const\t\t\t\t{\n        bool b=false;\n        QueryBoolValue( &b );\n        return b;\n    }\n    /// Query as a double. See IntValue()\n    double \t DoubleValue() const\t\t\t{\n        double d=0;\n        QueryDoubleValue( &d );\n        return d;\n    }\n    /// Query as a float. See IntValue()\n    float\t FloatValue() const\t\t\t\t{\n        float f=0;\n        QueryFloatValue( &f );\n        return f;\n    }\n\n    /** QueryIntValue interprets the attribute as an integer, and returns the value\n    \tin the provided parameter. The function will return XML_SUCCESS on success,\n    \tand XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.\n    */\n    XMLError QueryIntValue( int* value ) const;\n    /// See QueryIntValue\n    XMLError QueryUnsignedValue( unsigned int* value ) const;\n\t/// See QueryIntValue\n\tXMLError QueryInt64Value(int64_t* value) const;\n    /// See QueryIntValue\n    XMLError QueryUnsigned64Value(uint64_t* value) const;\n\t/// See QueryIntValue\n    XMLError QueryBoolValue( bool* value ) const;\n    /// See QueryIntValue\n    XMLError QueryDoubleValue( double* value ) const;\n    /// See QueryIntValue\n    XMLError QueryFloatValue( float* value ) const;\n\n    /// Set the attribute to a string value.\n    void SetAttribute( const char* value );\n    /// Set the attribute to value.\n    void SetAttribute( int value );\n    /// Set the attribute to value.\n    void SetAttribute( unsigned value );\n\t/// Set the attribute to value.\n\tvoid SetAttribute(int64_t value);\n    /// Set the attribute to value.\n    void SetAttribute(uint64_t value);\n    /// Set the attribute to value.\n    void SetAttribute( bool value );\n    /// Set the attribute to value.\n    void SetAttribute( double value );\n    /// Set the attribute to value.\n    void SetAttribute( float value );\n\nprivate:\n    enum { BUF_SIZE = 200 };\n\n    XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}\n    virtual ~XMLAttribute()\t{}\n\n    XMLAttribute( const XMLAttribute& );\t// not supported\n    void operator=( const XMLAttribute& );\t// not supported\n    void SetName( const char* name );\n\n    char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );\n\n    mutable StrPair _name;\n    mutable StrPair _value;\n    int             _parseLineNum;\n    XMLAttribute*   _next;\n    MemPool*        _memPool;\n};\n\n\n/** The element is a container class. It has a value, the element name,\n\tand can contain other elements, text, comments, and unknowns.\n\tElements also contain an arbitrary number of attributes.\n*/\nclass TINYXML2_LIB XMLElement : public XMLNode\n{\n    friend class XMLDocument;\npublic:\n    /// Get the name of an element (which is the Value() of the node.)\n    const char* Name() const\t\t{\n        return Value();\n    }\n    /// Set the name of the element.\n    void SetName( const char* str, bool staticMem=false )\t{\n        SetValue( str, staticMem );\n    }\n\n    virtual XMLElement* ToElement()\t\t\t\t{\n        return this;\n    }\n    virtual const XMLElement* ToElement() const {\n        return this;\n    }\n    virtual bool Accept( XMLVisitor* visitor ) const;\n\n    /** Given an attribute name, Attribute() returns the value\n    \tfor the attribute of that name, or null if none\n    \texists. For example:\n\n    \t@verbatim\n    \tconst char* value = ele->Attribute( \"foo\" );\n    \t@endverbatim\n\n    \tThe 'value' parameter is normally null. However, if specified,\n    \tthe attribute will only be returned if the 'name' and 'value'\n    \tmatch. This allow you to write code:\n\n    \t@verbatim\n    \tif ( ele->Attribute( \"foo\", \"bar\" ) ) callFooIsBar();\n    \t@endverbatim\n\n    \trather than:\n    \t@verbatim\n    \tif ( ele->Attribute( \"foo\" ) ) {\n    \t\tif ( strcmp( ele->Attribute( \"foo\" ), \"bar\" ) == 0 ) callFooIsBar();\n    \t}\n    \t@endverbatim\n    */\n    const char* Attribute( const char* name, const char* value=0 ) const;\n\n    /** Given an attribute name, IntAttribute() returns the value\n    \tof the attribute interpreted as an integer. The default\n        value will be returned if the attribute isn't present,\n        or if there is an error. (For a method with error\n    \tchecking, see QueryIntAttribute()).\n    */\n\tint IntAttribute(const char* name, int defaultValue = 0) const;\n    /// See IntAttribute()\n\tunsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;\n\t/// See IntAttribute()\n\tint64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;\n    /// See IntAttribute()\n    uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const;\n\t/// See IntAttribute()\n\tbool BoolAttribute(const char* name, bool defaultValue = false) const;\n    /// See IntAttribute()\n\tdouble DoubleAttribute(const char* name, double defaultValue = 0) const;\n    /// See IntAttribute()\n\tfloat FloatAttribute(const char* name, float defaultValue = 0) const;\n\n    /** Given an attribute name, QueryIntAttribute() returns\n    \tXML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion\n    \tcan't be performed, or XML_NO_ATTRIBUTE if the attribute\n    \tdoesn't exist. If successful, the result of the conversion\n    \twill be written to 'value'. If not successful, nothing will\n    \tbe written to 'value'. This allows you to provide default\n    \tvalue:\n\n    \t@verbatim\n    \tint value = 10;\n    \tQueryIntAttribute( \"foo\", &value );\t\t// if \"foo\" isn't found, value will still be 10\n    \t@endverbatim\n    */\n    XMLError QueryIntAttribute( const char* name, int* value ) const\t\t\t\t{\n        const XMLAttribute* a = FindAttribute( name );\n        if ( !a ) {\n            return XML_NO_ATTRIBUTE;\n        }\n        return a->QueryIntValue( value );\n    }\n\n\t/// See QueryIntAttribute()\n    XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const\t{\n        const XMLAttribute* a = FindAttribute( name );\n        if ( !a ) {\n            return XML_NO_ATTRIBUTE;\n        }\n        return a->QueryUnsignedValue( value );\n    }\n\n\t/// See QueryIntAttribute()\n\tXMLError QueryInt64Attribute(const char* name, int64_t* value) const {\n\t\tconst XMLAttribute* a = FindAttribute(name);\n\t\tif (!a) {\n\t\t\treturn XML_NO_ATTRIBUTE;\n\t\t}\n\t\treturn a->QueryInt64Value(value);\n\t}\n\n    /// See QueryIntAttribute()\n    XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const {\n        const XMLAttribute* a = FindAttribute(name);\n        if(!a) {\n            return XML_NO_ATTRIBUTE;\n        }\n        return a->QueryUnsigned64Value(value);\n    }\n\n\t/// See QueryIntAttribute()\n    XMLError QueryBoolAttribute( const char* name, bool* value ) const\t\t\t\t{\n        const XMLAttribute* a = FindAttribute( name );\n        if ( !a ) {\n            return XML_NO_ATTRIBUTE;\n        }\n        return a->QueryBoolValue( value );\n    }\n    /// See QueryIntAttribute()\n    XMLError QueryDoubleAttribute( const char* name, double* value ) const\t\t\t{\n        const XMLAttribute* a = FindAttribute( name );\n        if ( !a ) {\n            return XML_NO_ATTRIBUTE;\n        }\n        return a->QueryDoubleValue( value );\n    }\n    /// See QueryIntAttribute()\n    XMLError QueryFloatAttribute( const char* name, float* value ) const\t\t\t{\n        const XMLAttribute* a = FindAttribute( name );\n        if ( !a ) {\n            return XML_NO_ATTRIBUTE;\n        }\n        return a->QueryFloatValue( value );\n    }\n\n\t/// See QueryIntAttribute()\n\tXMLError QueryStringAttribute(const char* name, const char** value) const {\n\t\tconst XMLAttribute* a = FindAttribute(name);\n\t\tif (!a) {\n\t\t\treturn XML_NO_ATTRIBUTE;\n\t\t}\n\t\t*value = a->Value();\n\t\treturn XML_SUCCESS;\n\t}\n\n\n\n    /** Given an attribute name, QueryAttribute() returns\n    \tXML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion\n    \tcan't be performed, or XML_NO_ATTRIBUTE if the attribute\n    \tdoesn't exist. It is overloaded for the primitive types,\n\t\tand is a generally more convenient replacement of\n\t\tQueryIntAttribute() and related functions.\n\n\t\tIf successful, the result of the conversion\n    \twill be written to 'value'. If not successful, nothing will\n    \tbe written to 'value'. This allows you to provide default\n    \tvalue:\n\n    \t@verbatim\n    \tint value = 10;\n    \tQueryAttribute( \"foo\", &value );\t\t// if \"foo\" isn't found, value will still be 10\n    \t@endverbatim\n    */\n\tXMLError QueryAttribute( const char* name, int* value ) const {\n\t\treturn QueryIntAttribute( name, value );\n\t}\n\n\tXMLError QueryAttribute( const char* name, unsigned int* value ) const {\n\t\treturn QueryUnsignedAttribute( name, value );\n\t}\n\n\tXMLError QueryAttribute(const char* name, int64_t* value) const {\n\t\treturn QueryInt64Attribute(name, value);\n\t}\n\n    XMLError QueryAttribute(const char* name, uint64_t* value) const {\n        return QueryUnsigned64Attribute(name, value);\n    }\n\n    XMLError QueryAttribute( const char* name, bool* value ) const {\n\t\treturn QueryBoolAttribute( name, value );\n\t}\n\n\tXMLError QueryAttribute( const char* name, double* value ) const {\n\t\treturn QueryDoubleAttribute( name, value );\n\t}\n\n\tXMLError QueryAttribute( const char* name, float* value ) const {\n\t\treturn QueryFloatAttribute( name, value );\n\t}\n\n\tXMLError QueryAttribute(const char* name, const char** value) const {\n\t\treturn QueryStringAttribute(name, value);\n\t}\n\n\t/// Sets the named attribute to value.\n    void SetAttribute( const char* name, const char* value )\t{\n        XMLAttribute* a = FindOrCreateAttribute( name );\n        a->SetAttribute( value );\n    }\n    /// Sets the named attribute to value.\n    void SetAttribute( const char* name, int value )\t\t\t{\n        XMLAttribute* a = FindOrCreateAttribute( name );\n        a->SetAttribute( value );\n    }\n    /// Sets the named attribute to value.\n    void SetAttribute( const char* name, unsigned value )\t\t{\n        XMLAttribute* a = FindOrCreateAttribute( name );\n        a->SetAttribute( value );\n    }\n\n\t/// Sets the named attribute to value.\n\tvoid SetAttribute(const char* name, int64_t value) {\n\t\tXMLAttribute* a = FindOrCreateAttribute(name);\n\t\ta->SetAttribute(value);\n\t}\n\n    /// Sets the named attribute to value.\n    void SetAttribute(const char* name, uint64_t value) {\n        XMLAttribute* a = FindOrCreateAttribute(name);\n        a->SetAttribute(value);\n    }\n\n    /// Sets the named attribute to value.\n    void SetAttribute( const char* name, bool value )\t\t\t{\n        XMLAttribute* a = FindOrCreateAttribute( name );\n        a->SetAttribute( value );\n    }\n    /// Sets the named attribute to value.\n    void SetAttribute( const char* name, double value )\t\t{\n        XMLAttribute* a = FindOrCreateAttribute( name );\n        a->SetAttribute( value );\n    }\n    /// Sets the named attribute to value.\n    void SetAttribute( const char* name, float value )\t\t{\n        XMLAttribute* a = FindOrCreateAttribute( name );\n        a->SetAttribute( value );\n    }\n\n    /**\n    \tDelete an attribute.\n    */\n    void DeleteAttribute( const char* name );\n\n    /// Return the first attribute in the list.\n    const XMLAttribute* FirstAttribute() const {\n        return _rootAttribute;\n    }\n    /// Query a specific attribute in the list.\n    const XMLAttribute* FindAttribute( const char* name ) const;\n\n    /** Convenience function for easy access to the text inside an element. Although easy\n    \tand concise, GetText() is limited compared to getting the XMLText child\n    \tand accessing it directly.\n\n    \tIf the first child of 'this' is a XMLText, the GetText()\n    \treturns the character string of the Text node, else null is returned.\n\n    \tThis is a convenient method for getting the text of simple contained text:\n    \t@verbatim\n    \t<foo>This is text</foo>\n    \t\tconst char* str = fooElement->GetText();\n    \t@endverbatim\n\n    \t'str' will be a pointer to \"This is text\".\n\n    \tNote that this function can be misleading. If the element foo was created from\n    \tthis XML:\n    \t@verbatim\n    \t\t<foo><b>This is text</b></foo>\n    \t@endverbatim\n\n    \tthen the value of str would be null. The first child node isn't a text node, it is\n    \tanother element. From this XML:\n    \t@verbatim\n    \t\t<foo>This is <b>text</b></foo>\n    \t@endverbatim\n    \tGetText() will return \"This is \".\n    */\n    const char* GetText() const;\n\n    /** Convenience function for easy access to the text inside an element. Although easy\n    \tand concise, SetText() is limited compared to creating an XMLText child\n    \tand mutating it directly.\n\n    \tIf the first child of 'this' is a XMLText, SetText() sets its value to\n\t\tthe given string, otherwise it will create a first child that is an XMLText.\n\n    \tThis is a convenient method for setting the text of simple contained text:\n    \t@verbatim\n    \t<foo>This is text</foo>\n    \t\tfooElement->SetText( \"Hullaballoo!\" );\n     \t<foo>Hullaballoo!</foo>\n\t\t@endverbatim\n\n    \tNote that this function can be misleading. If the element foo was created from\n    \tthis XML:\n    \t@verbatim\n    \t\t<foo><b>This is text</b></foo>\n    \t@endverbatim\n\n    \tthen it will not change \"This is text\", but rather prefix it with a text element:\n    \t@verbatim\n    \t\t<foo>Hullaballoo!<b>This is text</b></foo>\n    \t@endverbatim\n\n\t\tFor this XML:\n    \t@verbatim\n    \t\t<foo />\n    \t@endverbatim\n    \tSetText() will generate\n    \t@verbatim\n    \t\t<foo>Hullaballoo!</foo>\n    \t@endverbatim\n    */\n\tvoid SetText( const char* inText );\n    /// Convenience method for setting text inside an element. See SetText() for important limitations.\n    void SetText( int value );\n    /// Convenience method for setting text inside an element. See SetText() for important limitations.\n    void SetText( unsigned value );\n\t/// Convenience method for setting text inside an element. See SetText() for important limitations.\n\tvoid SetText(int64_t value);\n    /// Convenience method for setting text inside an element. See SetText() for important limitations.\n    void SetText(uint64_t value);\n\t/// Convenience method for setting text inside an element. See SetText() for important limitations.\n    void SetText( bool value );\n    /// Convenience method for setting text inside an element. See SetText() for important limitations.\n    void SetText( double value );\n    /// Convenience method for setting text inside an element. See SetText() for important limitations.\n    void SetText( float value );\n\n    /**\n    \tConvenience method to query the value of a child text node. This is probably best\n    \tshown by example. Given you have a document is this form:\n    \t@verbatim\n    \t\t<point>\n    \t\t\t<x>1</x>\n    \t\t\t<y>1.4</y>\n    \t\t</point>\n    \t@endverbatim\n\n    \tThe QueryIntText() and similar functions provide a safe and easier way to get to the\n    \t\"value\" of x and y.\n\n    \t@verbatim\n    \t\tint x = 0;\n    \t\tfloat y = 0;\t// types of x and y are contrived for example\n    \t\tconst XMLElement* xElement = pointElement->FirstChildElement( \"x\" );\n    \t\tconst XMLElement* yElement = pointElement->FirstChildElement( \"y\" );\n    \t\txElement->QueryIntText( &x );\n    \t\tyElement->QueryFloatText( &y );\n    \t@endverbatim\n\n    \t@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted\n    \t\t\t to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.\n\n    */\n    XMLError QueryIntText( int* ival ) const;\n    /// See QueryIntText()\n    XMLError QueryUnsignedText( unsigned* uval ) const;\n\t/// See QueryIntText()\n\tXMLError QueryInt64Text(int64_t* uval) const;\n\t/// See QueryIntText()\n\tXMLError QueryUnsigned64Text(uint64_t* uval) const;\n\t/// See QueryIntText()\n    XMLError QueryBoolText( bool* bval ) const;\n    /// See QueryIntText()\n    XMLError QueryDoubleText( double* dval ) const;\n    /// See QueryIntText()\n    XMLError QueryFloatText( float* fval ) const;\n\n\tint IntText(int defaultValue = 0) const;\n\n\t/// See QueryIntText()\n\tunsigned UnsignedText(unsigned defaultValue = 0) const;\n\t/// See QueryIntText()\n\tint64_t Int64Text(int64_t defaultValue = 0) const;\n    /// See QueryIntText()\n    uint64_t Unsigned64Text(uint64_t defaultValue = 0) const;\n\t/// See QueryIntText()\n\tbool BoolText(bool defaultValue = false) const;\n\t/// See QueryIntText()\n\tdouble DoubleText(double defaultValue = 0) const;\n\t/// See QueryIntText()\n    float FloatText(float defaultValue = 0) const;\n\n    /**\n        Convenience method to create a new XMLElement and add it as last (right)\n        child of this node. Returns the created and inserted element.\n    */\n    XMLElement* InsertNewChildElement(const char* name);\n    /// See InsertNewChildElement()\n    XMLComment* InsertNewComment(const char* comment);\n    /// See InsertNewChildElement()\n    XMLText* InsertNewText(const char* text);\n    /// See InsertNewChildElement()\n    XMLDeclaration* InsertNewDeclaration(const char* text);\n    /// See InsertNewChildElement()\n    XMLUnknown* InsertNewUnknown(const char* text);\n\n\n    // internal:\n    enum ElementClosingType {\n        OPEN,\t\t// <foo>\n        CLOSED,\t\t// <foo/>\n        CLOSING\t\t// </foo>\n    };\n    ElementClosingType ClosingType() const {\n        return _closingType;\n    }\n    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\n    virtual bool ShallowEqual( const XMLNode* compare ) const;\n\nprotected:\n    char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );\n\nprivate:\n    XMLElement( XMLDocument* doc );\n    virtual ~XMLElement();\n    XMLElement( const XMLElement& );\t// not supported\n    void operator=( const XMLElement& );\t// not supported\n\n    XMLAttribute* FindOrCreateAttribute( const char* name );\n    char* ParseAttributes( char* p, int* curLineNumPtr );\n    static void DeleteAttribute( XMLAttribute* attribute );\n    XMLAttribute* CreateAttribute();\n\n    enum { BUF_SIZE = 200 };\n    ElementClosingType _closingType;\n    // The attribute list is ordered; there is no 'lastAttribute'\n    // because the list needs to be scanned for dupes before adding\n    // a new attribute.\n    XMLAttribute* _rootAttribute;\n};\n\n\nenum Whitespace {\n    PRESERVE_WHITESPACE,\n    COLLAPSE_WHITESPACE\n};\n\n\n/** A Document binds together all the functionality.\n\tIt can be saved, loaded, and printed to the screen.\n\tAll Nodes are connected and allocated to a Document.\n\tIf the Document is deleted, all its Nodes are also deleted.\n*/\nclass TINYXML2_LIB XMLDocument : public XMLNode\n{\n    friend class XMLElement;\n    // Gives access to SetError and Push/PopDepth, but over-access for everything else.\n    // Wishing C++ had \"internal\" scope.\n    friend class XMLNode;\n    friend class XMLText;\n    friend class XMLComment;\n    friend class XMLDeclaration;\n    friend class XMLUnknown;\npublic:\n    /// constructor\n    XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );\n    ~XMLDocument();\n\n    virtual XMLDocument* ToDocument()\t\t\t\t{\n        TIXMLASSERT( this == _document );\n        return this;\n    }\n    virtual const XMLDocument* ToDocument() const\t{\n        TIXMLASSERT( this == _document );\n        return this;\n    }\n\n    /**\n    \tParse an XML file from a character string.\n    \tReturns XML_SUCCESS (0) on success, or\n    \tan errorID.\n\n    \tYou may optionally pass in the 'nBytes', which is\n    \tthe number of bytes which will be parsed. If not\n    \tspecified, TinyXML-2 will assume 'xml' points to a\n    \tnull terminated string.\n    */\n    XMLError Parse( const char* xml, size_t nBytes=static_cast<size_t>(-1) );\n\n    /**\n    \tLoad an XML file from disk.\n    \tReturns XML_SUCCESS (0) on success, or\n    \tan errorID.\n    */\n    XMLError LoadFile( const char* filename );\n\n    /**\n    \tLoad an XML file from disk. You are responsible\n    \tfor providing and closing the FILE*.\n\n        NOTE: The file should be opened as binary (\"rb\")\n        not text in order for TinyXML-2 to correctly\n        do newline normalization.\n\n    \tReturns XML_SUCCESS (0) on success, or\n    \tan errorID.\n    */\n    XMLError LoadFile( FILE* );\n\n    /**\n    \tSave the XML file to disk.\n    \tReturns XML_SUCCESS (0) on success, or\n    \tan errorID.\n    */\n    XMLError SaveFile( const char* filename, bool compact = false );\n\n    /**\n    \tSave the XML file to disk. You are responsible\n    \tfor providing and closing the FILE*.\n\n    \tReturns XML_SUCCESS (0) on success, or\n    \tan errorID.\n    */\n    XMLError SaveFile( FILE* fp, bool compact = false );\n\n    bool ProcessEntities() const\t\t{\n        return _processEntities;\n    }\n    Whitespace WhitespaceMode() const\t{\n        return _whitespaceMode;\n    }\n\n    /**\n    \tReturns true if this document has a leading Byte Order Mark of UTF8.\n    */\n    bool HasBOM() const {\n        return _writeBOM;\n    }\n    /** Sets whether to write the BOM when writing the file.\n    */\n    void SetBOM( bool useBOM ) {\n        _writeBOM = useBOM;\n    }\n\n    /** Return the root element of DOM. Equivalent to FirstChildElement().\n        To get the first node, use FirstChild().\n    */\n    XMLElement* RootElement()\t\t\t\t{\n        return FirstChildElement();\n    }\n    const XMLElement* RootElement() const\t{\n        return FirstChildElement();\n    }\n\n    /** Print the Document. If the Printer is not provided, it will\n        print to stdout. If you provide Printer, this can print to a file:\n    \t@verbatim\n    \tXMLPrinter printer( fp );\n    \tdoc.Print( &printer );\n    \t@endverbatim\n\n    \tOr you can use a printer to print to memory:\n    \t@verbatim\n    \tXMLPrinter printer;\n    \tdoc.Print( &printer );\n    \t// printer.CStr() has a const char* to the XML\n    \t@endverbatim\n    */\n    void Print( XMLPrinter* streamer=0 ) const;\n    virtual bool Accept( XMLVisitor* visitor ) const;\n\n    /**\n    \tCreate a new Element associated with\n    \tthis Document. The memory for the Element\n    \tis managed by the Document.\n    */\n    XMLElement* NewElement( const char* name );\n    /**\n    \tCreate a new Comment associated with\n    \tthis Document. The memory for the Comment\n    \tis managed by the Document.\n    */\n    XMLComment* NewComment( const char* comment );\n    /**\n    \tCreate a new Text associated with\n    \tthis Document. The memory for the Text\n    \tis managed by the Document.\n    */\n    XMLText* NewText( const char* text );\n    /**\n    \tCreate a new Declaration associated with\n    \tthis Document. The memory for the object\n    \tis managed by the Document.\n\n    \tIf the 'text' param is null, the standard\n    \tdeclaration is used.:\n    \t@verbatim\n    \t\t<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    \t@endverbatim\n    */\n    XMLDeclaration* NewDeclaration( const char* text=0 );\n    /**\n    \tCreate a new Unknown associated with\n    \tthis Document. The memory for the object\n    \tis managed by the Document.\n    */\n    XMLUnknown* NewUnknown( const char* text );\n\n    /**\n    \tDelete a node associated with this document.\n    \tIt will be unlinked from the DOM.\n    */\n    void DeleteNode( XMLNode* node );\n\n    void ClearError() {\n        SetError(XML_SUCCESS, 0, 0);\n    }\n\n    /// Return true if there was an error parsing the document.\n    bool Error() const {\n        return _errorID != XML_SUCCESS;\n    }\n    /// Return the errorID.\n    XMLError  ErrorID() const {\n        return _errorID;\n    }\n\tconst char* ErrorName() const;\n    static const char* ErrorIDToName(XMLError errorID);\n\n    /** Returns a \"long form\" error description. A hopefully helpful\n        diagnostic with location, line number, and/or additional info.\n    */\n\tconst char* ErrorStr() const;\n\n    /// A (trivial) utility function that prints the ErrorStr() to stdout.\n    void PrintError() const;\n\n    /// Return the line where the error occurred, or zero if unknown.\n    int ErrorLineNum() const\n    {\n        return _errorLineNum;\n    }\n\n    /// Clear the document, resetting it to the initial state.\n    void Clear();\n\n\t/**\n\t\tCopies this document to a target document.\n\t\tThe target will be completely cleared before the copy.\n\t\tIf you want to copy a sub-tree, see XMLNode::DeepClone().\n\n\t\tNOTE: that the 'target' must be non-null.\n\t*/\n\tvoid DeepCopy(XMLDocument* target) const;\n\n\t// internal\n    char* Identify( char* p, XMLNode** node );\n\n\t// internal\n\tvoid MarkInUse(const XMLNode* const);\n\n    virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const\t{\n        return 0;\n    }\n    virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const\t{\n        return false;\n    }\n\nprivate:\n    XMLDocument( const XMLDocument& );\t// not supported\n    void operator=( const XMLDocument& );\t// not supported\n\n    bool\t\t\t_writeBOM;\n    bool\t\t\t_processEntities;\n    XMLError\t\t_errorID;\n    Whitespace\t\t_whitespaceMode;\n    mutable StrPair\t_errorStr;\n    int             _errorLineNum;\n    char*\t\t\t_charBuffer;\n    int\t\t\t\t_parseCurLineNum;\n\tint\t\t\t\t_parsingDepth;\n\t// Memory tracking does add some overhead.\n\t// However, the code assumes that you don't\n\t// have a bunch of unlinked nodes around.\n\t// Therefore it takes less memory to track\n\t// in the document vs. a linked list in the XMLNode,\n\t// and the performance is the same.\n\tDynArray<XMLNode*, 10> _unlinked;\n\n    MemPoolT< sizeof(XMLElement) >\t _elementPool;\n    MemPoolT< sizeof(XMLAttribute) > _attributePool;\n    MemPoolT< sizeof(XMLText) >\t\t _textPool;\n    MemPoolT< sizeof(XMLComment) >\t _commentPool;\n\n\tstatic const char* _errorNames[XML_ERROR_COUNT];\n\n    void Parse();\n\n    void SetError( XMLError error, int lineNum, const char* format, ... );\n\n\t// Something of an obvious security hole, once it was discovered.\n\t// Either an ill-formed XML or an excessively deep one can overflow\n\t// the stack. Track stack depth, and error out if needed.\n\tclass DepthTracker {\n\tpublic:\n\t\texplicit DepthTracker(XMLDocument * document) {\n\t\t\tthis->_document = document;\n\t\t\tdocument->PushDepth();\n\t\t}\n\t\t~DepthTracker() {\n\t\t\t_document->PopDepth();\n\t\t}\n\tprivate:\n\t\tXMLDocument * _document;\n\t};\n\tvoid PushDepth();\n\tvoid PopDepth();\n\n    template<class NodeType, int PoolElementSize>\n    NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );\n};\n\ntemplate<class NodeType, int PoolElementSize>\ninline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool )\n{\n    TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );\n    TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() );\n    NodeType* returnNode = new (pool.Alloc()) NodeType( this );\n    TIXMLASSERT( returnNode );\n    returnNode->_memPool = &pool;\n\n\t_unlinked.Push(returnNode);\n    return returnNode;\n}\n\n/**\n\tA XMLHandle is a class that wraps a node pointer with null checks; this is\n\tan incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2\n\tDOM structure. It is a separate utility class.\n\n\tTake an example:\n\t@verbatim\n\t<Document>\n\t\t<Element attributeA = \"valueA\">\n\t\t\t<Child attributeB = \"value1\" />\n\t\t\t<Child attributeB = \"value2\" />\n\t\t</Element>\n\t</Document>\n\t@endverbatim\n\n\tAssuming you want the value of \"attributeB\" in the 2nd \"Child\" element, it's very\n\teasy to write a *lot* of code that looks like:\n\n\t@verbatim\n\tXMLElement* root = document.FirstChildElement( \"Document\" );\n\tif ( root )\n\t{\n\t\tXMLElement* element = root->FirstChildElement( \"Element\" );\n\t\tif ( element )\n\t\t{\n\t\t\tXMLElement* child = element->FirstChildElement( \"Child\" );\n\t\t\tif ( child )\n\t\t\t{\n\t\t\t\tXMLElement* child2 = child->NextSiblingElement( \"Child\" );\n\t\t\t\tif ( child2 )\n\t\t\t\t{\n\t\t\t\t\t// Finally do something useful.\n\t@endverbatim\n\n\tAnd that doesn't even cover \"else\" cases. XMLHandle addresses the verbosity\n\tof such code. A XMLHandle checks for null pointers so it is perfectly safe\n\tand correct to use:\n\n\t@verbatim\n\tXMLHandle docHandle( &document );\n\tXMLElement* child2 = docHandle.FirstChildElement( \"Document\" ).FirstChildElement( \"Element\" ).FirstChildElement().NextSiblingElement();\n\tif ( child2 )\n\t{\n\t\t// do something useful\n\t@endverbatim\n\n\tWhich is MUCH more concise and useful.\n\n\tIt is also safe to copy handles - internally they are nothing more than node pointers.\n\t@verbatim\n\tXMLHandle handleCopy = handle;\n\t@endverbatim\n\n\tSee also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.\n*/\nclass TINYXML2_LIB XMLHandle\n{\npublic:\n    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.\n    explicit XMLHandle( XMLNode* node ) : _node( node ) {\n    }\n    /// Create a handle from a node.\n    explicit XMLHandle( XMLNode& node ) : _node( &node ) {\n    }\n    /// Copy constructor\n    XMLHandle( const XMLHandle& ref ) : _node( ref._node ) {\n    }\n    /// Assignment\n    XMLHandle& operator=( const XMLHandle& ref )\t\t\t\t\t\t\t{\n        _node = ref._node;\n        return *this;\n    }\n\n    /// Get the first child of this handle.\n    XMLHandle FirstChild() \t\t\t\t\t\t\t\t\t\t\t\t\t{\n        return XMLHandle( _node ? _node->FirstChild() : 0 );\n    }\n    /// Get the first child element of this handle.\n    XMLHandle FirstChildElement( const char* name = 0 )\t\t\t\t\t\t{\n        return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );\n    }\n    /// Get the last child of this handle.\n    XMLHandle LastChild()\t\t\t\t\t\t\t\t\t\t\t\t\t{\n        return XMLHandle( _node ? _node->LastChild() : 0 );\n    }\n    /// Get the last child element of this handle.\n    XMLHandle LastChildElement( const char* name = 0 )\t\t\t\t\t\t{\n        return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );\n    }\n    /// Get the previous sibling of this handle.\n    XMLHandle PreviousSibling()\t\t\t\t\t\t\t\t\t\t\t\t{\n        return XMLHandle( _node ? _node->PreviousSibling() : 0 );\n    }\n    /// Get the previous sibling element of this handle.\n    XMLHandle PreviousSiblingElement( const char* name = 0 )\t\t\t\t{\n        return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );\n    }\n    /// Get the next sibling of this handle.\n    XMLHandle NextSibling()\t\t\t\t\t\t\t\t\t\t\t\t\t{\n        return XMLHandle( _node ? _node->NextSibling() : 0 );\n    }\n    /// Get the next sibling element of this handle.\n    XMLHandle NextSiblingElement( const char* name = 0 )\t\t\t\t\t{\n        return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );\n    }\n\n    /// Safe cast to XMLNode. This can return null.\n    XMLNode* ToNode()\t\t\t\t\t\t\t{\n        return _node;\n    }\n    /// Safe cast to XMLElement. This can return null.\n    XMLElement* ToElement() \t\t\t\t\t{\n        return ( _node ? _node->ToElement() : 0 );\n    }\n    /// Safe cast to XMLText. This can return null.\n    XMLText* ToText() \t\t\t\t\t\t\t{\n        return ( _node ? _node->ToText() : 0 );\n    }\n    /// Safe cast to XMLUnknown. This can return null.\n    XMLUnknown* ToUnknown() \t\t\t\t\t{\n        return ( _node ? _node->ToUnknown() : 0 );\n    }\n    /// Safe cast to XMLDeclaration. This can return null.\n    XMLDeclaration* ToDeclaration() \t\t\t{\n        return ( _node ? _node->ToDeclaration() : 0 );\n    }\n\nprivate:\n    XMLNode* _node;\n};\n\n\n/**\n\tA variant of the XMLHandle class for working with const XMLNodes and Documents. It is the\n\tsame in all regards, except for the 'const' qualifiers. See XMLHandle for API.\n*/\nclass TINYXML2_LIB XMLConstHandle\n{\npublic:\n    explicit XMLConstHandle( const XMLNode* node ) : _node( node ) {\n    }\n    explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) {\n    }\n    XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) {\n    }\n\n    XMLConstHandle& operator=( const XMLConstHandle& ref )\t\t\t\t\t\t\t{\n        _node = ref._node;\n        return *this;\n    }\n\n    const XMLConstHandle FirstChild() const\t\t\t\t\t\t\t\t\t\t\t{\n        return XMLConstHandle( _node ? _node->FirstChild() : 0 );\n    }\n    const XMLConstHandle FirstChildElement( const char* name = 0 ) const\t\t\t\t{\n        return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );\n    }\n    const XMLConstHandle LastChild()\tconst\t\t\t\t\t\t\t\t\t\t{\n        return XMLConstHandle( _node ? _node->LastChild() : 0 );\n    }\n    const XMLConstHandle LastChildElement( const char* name = 0 ) const\t\t\t\t{\n        return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );\n    }\n    const XMLConstHandle PreviousSibling() const\t\t\t\t\t\t\t\t\t{\n        return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );\n    }\n    const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const\t\t{\n        return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );\n    }\n    const XMLConstHandle NextSibling() const\t\t\t\t\t\t\t\t\t\t{\n        return XMLConstHandle( _node ? _node->NextSibling() : 0 );\n    }\n    const XMLConstHandle NextSiblingElement( const char* name = 0 ) const\t\t\t{\n        return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );\n    }\n\n\n    const XMLNode* ToNode() const\t\t\t\t{\n        return _node;\n    }\n    const XMLElement* ToElement() const\t\t\t{\n        return ( _node ? _node->ToElement() : 0 );\n    }\n    const XMLText* ToText() const\t\t\t\t{\n        return ( _node ? _node->ToText() : 0 );\n    }\n    const XMLUnknown* ToUnknown() const\t\t\t{\n        return ( _node ? _node->ToUnknown() : 0 );\n    }\n    const XMLDeclaration* ToDeclaration() const\t{\n        return ( _node ? _node->ToDeclaration() : 0 );\n    }\n\nprivate:\n    const XMLNode* _node;\n};\n\n\n/**\n\tPrinting functionality. The XMLPrinter gives you more\n\toptions than the XMLDocument::Print() method.\n\n\tIt can:\n\t-# Print to memory.\n\t-# Print to a file you provide.\n\t-# Print XML without a XMLDocument.\n\n\tPrint to Memory\n\n\t@verbatim\n\tXMLPrinter printer;\n\tdoc.Print( &printer );\n\tSomeFunction( printer.CStr() );\n\t@endverbatim\n\n\tPrint to a File\n\n\tYou provide the file pointer.\n\t@verbatim\n\tXMLPrinter printer( fp );\n\tdoc.Print( &printer );\n\t@endverbatim\n\n\tPrint without a XMLDocument\n\n\tWhen loading, an XML parser is very useful. However, sometimes\n\twhen saving, it just gets in the way. The code is often set up\n\tfor streaming, and constructing the DOM is just overhead.\n\n\tThe Printer supports the streaming case. The following code\n\tprints out a trivially simple XML file without ever creating\n\tan XML document.\n\n\t@verbatim\n\tXMLPrinter printer( fp );\n\tprinter.OpenElement( \"foo\" );\n\tprinter.PushAttribute( \"foo\", \"bar\" );\n\tprinter.CloseElement();\n\t@endverbatim\n*/\nclass TINYXML2_LIB XMLPrinter : public XMLVisitor\n{\npublic:\n    /** Construct the printer. If the FILE* is specified,\n    \tthis will print to the FILE. Else it will print\n    \tto memory, and the result is available in CStr().\n    \tIf 'compact' is set to true, then output is created\n    \twith only required whitespace and newlines.\n    */\n    XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );\n    virtual ~XMLPrinter()\t{}\n\n    /** If streaming, write the BOM and declaration. */\n    void PushHeader( bool writeBOM, bool writeDeclaration );\n    /** If streaming, start writing an element.\n        The element must be closed with CloseElement()\n    */\n    void OpenElement( const char* name, bool compactMode=false );\n    /// If streaming, add an attribute to an open element.\n    void PushAttribute( const char* name, const char* value );\n    void PushAttribute( const char* name, int value );\n    void PushAttribute( const char* name, unsigned value );\n\tvoid PushAttribute( const char* name, int64_t value );\n\tvoid PushAttribute( const char* name, uint64_t value );\n\tvoid PushAttribute( const char* name, bool value );\n    void PushAttribute( const char* name, double value );\n    /// If streaming, close the Element.\n    virtual void CloseElement( bool compactMode=false );\n\n    /// Add a text node.\n    void PushText( const char* text, bool cdata=false );\n    /// Add a text node from an integer.\n    void PushText( int value );\n    /// Add a text node from an unsigned.\n    void PushText( unsigned value );\n\t/// Add a text node from a signed 64bit integer.\n\tvoid PushText( int64_t value );\n\t/// Add a text node from an unsigned 64bit integer.\n\tvoid PushText( uint64_t value );\n\t/// Add a text node from a bool.\n    void PushText( bool value );\n    /// Add a text node from a float.\n    void PushText( float value );\n    /// Add a text node from a double.\n    void PushText( double value );\n\n    /// Add a comment\n    void PushComment( const char* comment );\n\n    void PushDeclaration( const char* value );\n    void PushUnknown( const char* value );\n\n    virtual bool VisitEnter( const XMLDocument& /*doc*/ );\n    virtual bool VisitExit( const XMLDocument& /*doc*/ )\t\t\t{\n        return true;\n    }\n\n    virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );\n    virtual bool VisitExit( const XMLElement& element );\n\n    virtual bool Visit( const XMLText& text );\n    virtual bool Visit( const XMLComment& comment );\n    virtual bool Visit( const XMLDeclaration& declaration );\n    virtual bool Visit( const XMLUnknown& unknown );\n\n    /**\n    \tIf in print to memory mode, return a pointer to\n    \tthe XML file in memory.\n    */\n    const char* CStr() const {\n        return _buffer.Mem();\n    }\n    /**\n    \tIf in print to memory mode, return the size\n    \tof the XML file in memory. (Note the size returned\n    \tincludes the terminating null.)\n    */\n    int CStrSize() const {\n        return _buffer.Size();\n    }\n    /**\n    \tIf in print to memory mode, reset the buffer to the\n    \tbeginning.\n    */\n    void ClearBuffer( bool resetToFirstElement = true ) {\n        _buffer.Clear();\n        _buffer.Push(0);\n\t\t_firstElement = resetToFirstElement;\n    }\n\nprotected:\n\tvirtual bool CompactMode( const XMLElement& )\t{ return _compactMode; }\n\n\t/** Prints out the space before an element. You may override to change\n\t    the space and tabs used. A PrintSpace() override should call Print().\n\t*/\n    virtual void PrintSpace( int depth );\n    virtual void Print( const char* format, ... );\n    virtual void Write( const char* data, size_t size );\n    virtual void Putc( char ch );\n\n    inline void Write(const char* data) { Write(data, strlen(data)); }\n\n    void SealElementIfJustOpened();\n    bool _elementJustOpened;\n    DynArray< const char*, 10 > _stack;\n\nprivate:\n    /**\n       Prepares to write a new node. This includes sealing an element that was\n       just opened, and writing any whitespace necessary if not in compact mode.\n     */\n    void PrepareForNewNode( bool compactMode );\n    void PrintString( const char*, bool restrictedEntitySet );\t// prints out, after detecting entities.\n\n    bool _firstElement;\n    FILE* _fp;\n    int _depth;\n    int _textDepth;\n    bool _processEntities;\n\tbool _compactMode;\n\n    enum {\n        ENTITY_RANGE = 64,\n        BUF_SIZE = 200\n    };\n    bool _entityFlag[ENTITY_RANGE];\n    bool _restrictedEntityFlag[ENTITY_RANGE];\n\n    DynArray< char, 20 > _buffer;\n\n    // Prohibit cloning, intentionally not implemented\n    XMLPrinter( const XMLPrinter& );\n    XMLPrinter& operator=( const XMLPrinter& );\n};\n\n\n}\t// tinyxml2\n\n#if defined(_MSC_VER)\n#   pragma warning(pop)\n#endif\n\n#endif // TINYXML2_INCLUDED\n"
  },
  {
    "path": "TrafficMonitor.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.7.34031.279\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"TrafficMonitor\", \"TrafficMonitor\\TrafficMonitor.vcxproj\", \"{09483BED-B1E9-4827-8120-A18302C84AA8}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26} = {C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}\n\tEndProjectSection\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"OpenHardwareMonitorApi\", \"OpenHardwareMonitorApi\\OpenHardwareMonitorApi.vcxproj\", \"{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"PluginDemo\", \"PluginDemo\\PluginDemo.vcxproj\", \"{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug (lite)|ARM64EC = Debug (lite)|ARM64EC\n\t\tDebug (lite)|x64 = Debug (lite)|x64\n\t\tDebug (lite)|x86 = Debug (lite)|x86\n\t\tDebug|ARM64EC = Debug|ARM64EC\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease (lite)|ARM64EC = Release (lite)|ARM64EC\n\t\tRelease (lite)|x64 = Release (lite)|x64\n\t\tRelease (lite)|x86 = Release (lite)|x86\n\t\tRelease|ARM64EC = Release|ARM64EC\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug (lite)|ARM64EC.ActiveCfg = Debug (lite)|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug (lite)|ARM64EC.Build.0 = Debug (lite)|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug (lite)|x64.ActiveCfg = Debug (lite)|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug (lite)|x64.Build.0 = Debug (lite)|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug (lite)|x86.ActiveCfg = Debug (lite)|Win32\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug (lite)|x86.Build.0 = Debug (lite)|Win32\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug|ARM64EC.Build.0 = Debug|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug|x64.Build.0 = Debug|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Debug|x86.Build.0 = Debug|Win32\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release (lite)|ARM64EC.ActiveCfg = Release (lite)|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release (lite)|ARM64EC.Build.0 = Release (lite)|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release (lite)|x64.ActiveCfg = Release (lite)|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release (lite)|x64.Build.0 = Release (lite)|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release (lite)|x86.ActiveCfg = Release (lite)|Win32\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release (lite)|x86.Build.0 = Release (lite)|Win32\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release|ARM64EC.ActiveCfg = Release|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release|ARM64EC.Build.0 = Release|ARM64EC\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release|x64.ActiveCfg = Release|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release|x64.Build.0 = Release|x64\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release|x86.ActiveCfg = Release|Win32\n\t\t{09483BED-B1E9-4827-8120-A18302C84AA8}.Release|x86.Build.0 = Release|Win32\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug (lite)|ARM64EC.ActiveCfg = Debug|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug (lite)|x64.ActiveCfg = Debug|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug (lite)|x86.ActiveCfg = Debug|Win32\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug|ARM64EC.ActiveCfg = Debug|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug|ARM64EC.Build.0 = Debug|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug|x64.Build.0 = Debug|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Debug|x86.Build.0 = Debug|Win32\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release (lite)|ARM64EC.ActiveCfg = Release|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release (lite)|x64.ActiveCfg = Release|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release (lite)|x86.ActiveCfg = Release|Win32\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release|ARM64EC.ActiveCfg = Release|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release|ARM64EC.Build.0 = Release|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release|x64.ActiveCfg = Release|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release|x64.Build.0 = Release|x64\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release|x86.ActiveCfg = Release|Win32\n\t\t{C0A42F4A-ABB3-4575-B4D5-CEDD8379AC26}.Release|x86.Build.0 = Release|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug (lite)|ARM64EC.ActiveCfg = Debug|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug (lite)|ARM64EC.Build.0 = Debug|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug (lite)|x64.ActiveCfg = Debug|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug (lite)|x64.Build.0 = Debug|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug (lite)|x86.ActiveCfg = Debug|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug (lite)|x86.Build.0 = Debug|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug|ARM64EC.ActiveCfg = Debug|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug|ARM64EC.Build.0 = Debug|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug|x64.Build.0 = Debug|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Debug|x86.Build.0 = Debug|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release (lite)|ARM64EC.ActiveCfg = Release|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release (lite)|ARM64EC.Build.0 = Release|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release (lite)|x64.ActiveCfg = Release|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release (lite)|x64.Build.0 = Release|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release (lite)|x86.ActiveCfg = Release|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release (lite)|x86.Build.0 = Release|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release|ARM64EC.ActiveCfg = Release|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release|ARM64EC.Build.0 = Release|ARM64EC\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release|x64.ActiveCfg = Release|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release|x64.Build.0 = Release|x64\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release|x86.ActiveCfg = Release|Win32\n\t\t{D1CA3ECC-DC32-445A-B734-C4DB08D4BA34}.Release|x86.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {2DE8C8C3-89CE-4313-978B-DADEC5CB141A}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "UpdateLog/update_log.md",
    "content": "**简体中文 | [繁體中文](./update_log_zh-tw.md) | [English](./update_log_en-us.md)**\n\n# TrafficMonitor 更新日志\n## V1.85.1 (2025/02/10)\n\n* 修正Windows11下使用第三方软件改成旧版任务栏时，任务栏窗口设置中“任务栏窗口显示在任务栏左侧”选项不可用的问题\n* 修正当任务栏上没有任何图标时任务栏窗口的位置不正确的问题 #1913\n* 修正任务栏窗口设置中点击“应用”时网速数据宽度不生效的问题 #1916\n* 任务栏设置中Windows11相关设置移动到单独的对话框中，增加避免与右侧小组件重叠的选项\n* 修正未启用硬件监控中的CPU监控时，CPU使用率获取方式改成使用性能计数器后，会改回基于CPU使用时间的问题\n* 修正鸣谢界面有乱码的问题\n* 修正当监控时间间隔设置得过小时，显示的网速可能会大于实际网速问题 #1263 #1674\n* 修正当内存超过100G时显示任务栏剩余内存显示不全的问题 #1722\n\n## V1.85 (2025/01/21)\n\n**功能更新：**\n* 任务栏窗口增加Direct2D的渲染方式，解决有时字体边缘有锯齿的问题 #1156\n* 显卡监控功能增加对英特尔显卡的支持 \\#1751\n* 右击插件项目时的右键菜单中增加插件菜单\n* 插件管理界面增加插件图标的显示，右键菜单中增加插件命令\n* 监控时间间隔的最大值调整为30s\n* 任务栏窗口设置中增加“窗口顶部边距”和“垂直边距”的选项\n* 主窗口增加对png格式透明背景图片的支持\n* 新增根据Windows深浅色模式自动切换皮肤的功能 #1013\n* 新增在任务栏的插件项目中显示资源占用图的功能，并更新对应的插件接口 #1077\n* 主窗口和任务栏窗口中新增今日总流量的显示 #1174\n* 任务栏窗口设置中新增“使用彩色emoji”的选项（仅Direct2D渲染方式）\n* 常规设置中的温度通知上限调整为120度 #1814\n* 新增Arm64EC的支持 #1703\n* 新增Lite版显示CPU频率的功能\n* 任务栏设置-预设方案中的方案2和方案3增加默认的文本颜色\n\n**问题修正：**\n* LibreHardwareMonitorLib.dll更新到0.9.4版本，解决部分设备硬件监控信息无法正常显示的问题\n* 修正Windows 11 build 22621版本后触屏设备任务栏窗口位置不正确的问题\n* 修正Windows 11下小组件不存在时，任务栏窗口的位置不正确的问题的问题 #1582\n* 修正Windows 11下，当任务栏窗口显示在右侧时，会和系统小组件重叠的问题\n* 修正选项设置对话框中使用触摸板手势时滚动过快的问题\n* 修正主窗口鼠标提示中CPU频率显示不正确的问题\n* 修正皮肤文件中插件项目的显示文本无效的问题 #1813\n* 修正如果隐藏了通知区图标，弹出通知后通知区图标再次出现的问题 #1814 #1812 #1811\n\n## V1.84.1 (2022/11/18)\n\n* 修正Windows11下任务栏窗口无法显示到左边的问题。\n* 修正任务栏显示在桌面两侧时任务栏窗口会显示不全的问题。\n* 修正Windows11 22H2中，关闭了所有窗口且任务栏上没有固定任何图标时，任务栏窗口位置不正确的问题。\n* 为触屏设备添加长按右键菜单的支持。\n* 修正由于最新版本Windows11中搜索按钮比较宽导致任务栏窗口的位置不正确的问题。\n* 修正“关于”对话框的大小有时不正确的问题。\n\n## V1.84 (2022/10/05)\n\n* 修正Windows11 22H2版本中任务栏窗口位置不正确的问题。\n* 修正Windows11下任务栏窗口显示在左侧时会和系统自带的小组件重叠的问题。\n* 新增CPU频率的显示。\n* 修正主窗口网速单位缺少“/s”的问题。\n* 修正写入ini文件时可能导致字符串缓冲区不足的问题。\n* 插件接口更新，允许插件响应键盘事件。\n* 修正任务栏窗口在不同DPI显示器切换后显示不正常的问题。\n* 修正简体中文语言下历史流量统计中的“转到今天”命令无效的问题。\n* 修正“插件管理”界面中在右键菜单中选择“详细信息”会弹出“选项”对话框的问题。\n* 更新HardwareMonitor lib 以解决无法获取 Intel 12 代处理器温度的问题。\n\n## V1.83 (2022/02/03)\n\n* 修正当已经存在一个开机自启动的任务计划时，无法设置开机自启动的问题，\n* 新增当已经存在TrafficMonitor进程时启动程序，弹出“程序已经在运行”对话框。\n* 鼠标提示中新增插件信息的显示。\n* 修正插件被禁用后仍然会被加载的问题。\n* 任务栏中的插件项目支持自由排序。\n* 选项设置中新增可以选择要在“网络连接列表”中显示的网络的功能。\n* 新增显示总网速的功能。\n* 新增在任务栏中显示网速占用图的功能。\n* 修正硬件监控中有多个名称相同的硬盘时只能显示一个硬盘的问题。\n* 优化任务栏窗口横向滚动图的显示效果。\n* 任务栏窗口右键菜单中的“显示设置”由菜单改为对话框形式。\n* “选择网络连接”菜单中添加“刷新网络连接列表”命令。\n* 修正几处导致程序崩溃的问题。\n\n## V1.82 (2021/12/12)\n\n* 新增插件系统，可以通过插件在任务栏窗口和主窗口显示更多自定义内容。\n* 任务栏右键菜单中增加“任务管理器”命令。\n* 选项设置中新增“应用”按钮。\n* 历史流量统计中增加周视图。\n* 新增任务栏项目间距的设置。\n* 修正Windows11深色模式下任务栏右键菜单无法弹出的问题。\n* 修正Windows11下使用StartAllBack等软件将任务栏恢复为Windows10样式时，任务栏窗口无法显示的问题。\n\n## V1.81 (2021/07/27)\n\n* 修正1.80版本以来的一些崩溃的问题\n* 任务栏窗口显示项目支持自定义排序\n* 任务栏窗口中显示的项目数量为奇数时，最后一个项目垂直排列，以节省任务栏空间\n* 新增显示硬盘利用率的功能\n* 将右键菜单中的一些设置添加到选项设置界面中\n* 新增主窗口对多显示器的支持，在不勾选“允许超出屏幕边界”的情况下也能移动到其他显示器了\n\n## V1.80.3 (2021/05/29)\n\n* 修正无法显示CPU温度的问题\n* 新增可以选择监控指定CPU核心的温度的功能\n* 修正一处导致程序崩溃的问题\n\n## V1.80.2 (2021/05/22)\n\n* 修正几处导致程序崩溃的问题\n* 获取温度信息改用LibreHardwareMonitor\n* 新增可选择要监控哪块硬盘的温度的功能\n* 新增可选择要监控哪些硬件的功能\n* 修正程序退出时LibreHardwareMonitorLib.sys文件没有解除占用的问题\n\n## V1.80.1 (2021/05/17)\n\n* 修正无法获取AMD显卡温度的问题\n* 修正自动切换为浅色模式颜色预设时程序崩溃的问题\n* 修正无法获取11代Intel处理器温度的问题\n* 修正设置开机自启动无效的问题\n\n## V1.80 (2021/05/15)\n\n* 新增CPU、显卡、硬盘和主板温度监控的功能\n* 新增显卡利用率监控的功能\n* 修正历史流量统计数值溢出导致统计数值不正确的问题\n* 修正屏幕分辨率更改后主窗口位置不正确的问题\n* 修正系统DPI更改后，主窗口和任务栏窗口界面元素的大小不会随DPI变化的问题\n* 新增任务栏窗口自由指定显示项目的功能\n* 新增xml格式的主窗口皮肤，支持温度显示\n* 修正使用触屏设备时，选项设置中的子窗口无法使用触屏滚动的问题\n* 将检查更新的处理放到后台线程中，以解决检查更新时程序长时间没有响应的问题\n* 修正任务栏窗口中按Alt+F4后程序异常的问题\n* 新增对每秒4GB以上网速的支持\n* 新增可选择更新源为Gitee，以解决中国大陆地区有时无法访问GitHub导致程序无法更新的问题\n* 新增内存显示方式设置\n* 修正当前监控的网卡被关闭或禁用，再次启动后无法自动选择之前监控的网卡的问题\n* 开机自启动采用任务计划实现，以解决有时开机自启动无效的问题\n* 修正一些崩溃的问题\n* 其他细节方面的改进\n\n## V1.79.1 (2020/08/05)\n\n* 修正注册表句柄泄漏的问题。\n* 修正当主窗口和任务栏窗口都不显示时，不统计CPU和内存利用率的问题。\n\n## V1.79 (2020/07/30)\n\n* 新增任务栏窗口颜色自动适应Windows10深色/浅色主题的功能。\n* 新增通知区图标自动适应Windows10深色/浅色主题的功能。\n* 增加CPU获取方式的设置，解决部分用户出现的CPU利用率始终为0的问题。\n* 选项设置>任务栏设置中去掉“透明色”的设置，新增“背景色透明”的选项。\n* 新增允许任务栏只显示CPU和内存利用率而不显示网速。\n* 修正了关机后设置可能会没有保存的问题。\n* 历史流量统计-日历视图中增加了每周第一天的设置。\n* 历史流量统计-列表视图中增加了按年、月、日、季度统计的功能。\n* 可能解决了历史流量数据有小概率丢失的问题。\n* 修正Windows10浅色主题时，如果任务栏窗口背景设置为透明，会无法弹出右键菜单的问题。\n* 修正流量统计不支持统计超过2TB数据的问题。\n* 为菜单项添加了图标。\n* 当程序所在目录无法写入时，将数据保存到AppData目录。\n* 新增设置监控时间间隔的功能。\n\n## V1.78 (2020/03/21)\n\n* 新增双击主窗口或任务栏窗口打开指定应用程序的功能\n* 新增任务栏窗口中显示CPU和内存利用率状态条的功能\n* 修正Windows10中CPU利用率和任务管理器不一致的问题\n* 新增是否显示鼠标提示的选项\n* 新增程序首次启启动时根据Windows10浅色模式设置任务栏颜色的功能\n* 任务栏设置中增加预设方案的功能\n* 其他细节方面的改进\n\n## V1.77 (2019/05/01)\n* 增加任务窗口透明色设置，修正任务栏为白色时任务栏窗口文字颜色无法设置为黑色的问题（在“选项”——“任务栏窗口设置”中设置透明色）\n* 新增程序崩溃时显示崩溃信息的功能\n* 修正显示任务栏窗口的情况下，资源管理器重启时会导致屏幕闪烁的问题\n* 新增鼠标指向通知区图标时显示监控信息\n* 修正使用蓝牙网络时无法显示网速的问题\n* 新增x64的版本\n* 其他细节方面的改进\n### 更新说明：\n本次更新在一定程度上解决了Win10最新版本中白色任务栏时文字看不清的问题。需要手动在“选项”——“任务栏窗口设置”——“透明色”设置透明色。当透明色不为黑色且和背景色不同时为不透明效果，如果和背景色相同则为透明效果。在Win10白色任务栏中建议如下图所示设置：\n![白色任务栏截图](https://user-images.githubusercontent.com/30562462/57004858-36b55300-6c05-11e9-89d8-9911dc99f09c.PNG)\n## V1.76 (2018/11/11)\n* 修正了分辨率更改可能会导致程序崩溃的问题；\n* 新增配置文件保存位置的选项；\n* 修正了当分辨率变化时任务栏窗口的垂直位置不正确的问题；\n* 新增今日上传和下载流量的显示，历史流量统计中增加上传和下载流量的统计；\n* 其他细节方面的改进。\n## V1.75 (2018/08/11)\n* 任务栏窗口右键菜单增加“选择网络连接”菜单项\n* 写入配置文件时改为使用UTF8编码\n* 新增网速单位为B(字节)或b(比特)的设置\n* 修正部分电脑中无法获取网速的问题\n* 修正部分电脑中会反复产生错误日志的问题\n* 皮肤11 UI调整，修正有时文本显示不全的问题\n其他细节方面的改进\n## V1.74 (2018/06/17)\n* 修正两处导致程序崩溃的问题\n* 新增：监控所有连接的网速的功能\n* 右键菜单“选择网络连接”中显示所有的网络接口，不显示loopback接口\n* 新增：任务栏窗口项目可以水平排列\n* 新增：繁体中文语言支持\n* 其他细节方面的改进。\n## V1.73 (2018/05/13)\n* 新增：多语言支持，增加英语\n* 新增：字体设置支持粗体、斜体、下划线等字体样式\n* 新增：历史流量统计中的日历视图\n* 修正：当悬浮窗在右下角时，有时程序启动后悬浮窗会往左或往上移动一段距离的问题\n* 配置文件转移到C:\\Users\\用户名\\AppData\\Roaming\\TrafficMonitor目录下，防止由于程序所在目录无法写入数据导致配置文件无法保存的问题\n* 新增：网速数据位数设置的选项；修正有时当网速超过10M/s时数据显示的全的问题\n## V1.72 (2018/04/21)\n* 新增：任务栏窗口数值右对齐的选项\n* 新增：每个项目文本颜色单独设置的功能\n* 新增：设置鼠标双击动作的功能\n* 新增：设置当流量或内存使用率超过一定值时弹出通知的功能\n* 新增：获取外网IP地址的功能\n* 其他细节方面的改进。\n## V1.71 (2018/04/06)\n* 优化背景图片的显示效果，解决了由于图片缩放时导致的失真的问题\n* 增加不规则形状皮肤的支持\n* 增加可以通过皮肤文件设定项目的对齐方式和字体\n* 改善了优化通知区图标在125%缩放比时的显示效果\n* 一些细节方面的改进。\n## V1.70 (2018/03/30)\n* 新增：自定义皮肤功能，可以通过皮肤文件更加自由地定义悬浮窗中的每个项目的大小和位置\n* “更换皮肤”对话框中预览图可以预览悬浮窗中显示的文本和字体，当预览图过大时会显示滚动条\n* “更换皮肤”对话框中增加“皮肤制作教程”和“更多皮肤下载”链接\n* 新增允许悬浮窗超出屏幕边界的选项，解决多显示器时无法移动到其他显示器的问题\n## V1.69 (2018/03/17)\n* 新增单位设置，允许隐藏单位\n* 新增：单位设置、网速显示简洁模式可应用到主窗口\n* 新增更换通知区图标的功能\n* 一些细节方面的改进\n* 增加两款皮肤。\n## V1.68 (2018/03/03)\n* 修正当程序启动时，如果设置了隐藏主窗口，主窗口还是会显示1秒钟再消失的问题\n* 修正当窗口为左上角(0,0)时，下次启动时无法记住该位置的问题\n* 修正有时在进入选项设置再点击“确定”时，会弹出“注册表项删除失败”提示框的问题\n* 新增任务栏窗口网速显示简洁模式（选项——任务栏窗口设置——网速显示简洁模式）\n## V1.67 (2018/01/21)\n* 修正当主窗口和任务栏窗口都不显示CPU和内存利用率时，鼠标提示中的CPU和内存利用率不刷新的问题\n* 修正了当任务栏左侧有自定义工具栏或快速启动栏时，任务栏窗口位置不正确的问题\n* 新增自动检查更新功能\n* 开机自启动功能改为写入注册表实现，去掉右键菜单中的“开机自动运行”项，移至选项设置——常规设置\n* 增加任务栏窗口可以放在任务栏的左侧\n* 其他细节方面的改进\n## V1.66 (2017/12/31)\n* 新增鼠标悬浮提示会实时更新\n* 优化关于启动时弹出“已经有一个程序正在运行”对话框的处理\n* 增加无法嵌入任务栏时自动重试的处理\n* 增加任务栏窗口的刷新频率，在一定程度上解决通知区域图标变化时任务栏窗口闪烁的问题\n* 历史流量统计对话框中增加图形指示\n## V1.65 (2017/11.16)\n* 修正了更新Win10秋季创意者更新后，设置了开机启动时会弹出“已经有一个程序正在运行”的对话框的问题\n* 增加了选项设置对话框，将字体和字体颜色设置放到了选项设置对话框中，增加了显示文本的设置\n* 修正了有时开机启动时会弹出“窗口无法嵌入任务栏”的提示的问题\n* 增加程序全屏时隐藏悬浮窗的选项，并修正了全屏视频或游戏时悬浮窗会自己跳出来的问题\n* 任务栏窗口的宽度不再固定，而是会根据文本宽度自动调整\n* 连接详情对话框中增加右键菜单复制功能\n## V1.64 (2017/07/28)\n* 任务栏窗口信息显示改成了双缓冲绘图，彻底修正了任务栏窗口显示出现难看的色块的问题\n* 当任务栏从桌面底部移动到两旁时，任务栏窗口会实时切换横排和竖排显示\n## V1.63 (2017/07/05)\n* 增加当无法保存设置时的警告信息\n* 优化通知区图标行为，当设置了隐藏主窗口时，双击通知区图标才显示主窗口\n* 调整了任务栏窗口显示网速部分的宽度，以修正网速过大时显示不全的问题\n* 任务栏窗口右键菜单中增加显示通知区图标选项\n* 修正有时设置了去掉通知区图标后再次启动时图标还在的问题\n* 如果设置了主窗口总是置顶，每隔5分钟自动执行一次置顶操作，以解决有时窗口没有置顶的问题\n## V1.62 (2017/05/29)\n* 启动时如果检测到历史流量统计中有重复的日期就将它们合并\n* 去掉一些菜单项中不必要的省略号\n* 其他细节方面的改进\n## V1.61 (2017/05/19)\n* 连接详情中增加物理地址、IP地址、子网掩码和默认网关几个项目显示\n* 鼠标提示信息合并为一个提示，如果设置为不显示CPU和内存利用率时在提示信息里显示\n* 修正了连接详情窗口中的鼠标提示显示在窗口后面的问题\n* 修正了主窗口没有置顶时任务栏窗口的鼠标提示在窗口后面的问题\n* 修正了切换网络连接后的1秒网速显示为一个很大的值的问题\n* 修正了当切换网络连接时统计的流量不正确的问题\n## V1.60 (2017/05/11)\n* 连接详情界面改为列表显示，增加程序已运行时间项目\n* 新增历史流量统计功能，可以记录每一天总共使用的流量\n* 关于对话框中增加捐赠功能\n* 关于对话框中增加检查更新链接，点击可跳转到百度网盘链接\n* 优化了自动选择的处理，在较大程度上解决了有时无法显示网速的问题\n* 较大程度上解决了少数情况下设置总是置顶、鼠标穿透时无效的问题\n* 新增当鼠标指向主窗口或任务栏窗口对应的项目时，提示今日已使用流量和内存使用详情\n* 更换了程序图标和通知区域图标，风格更加简洁\n## V1.54 (2017/04/29)\n* 修正当设置了隐藏主窗口和显示任务栏窗口时，在任务视图中有一个看不见的窗口的问题\n* 修正某些情况下会导致变成灰色的菜单项变回可用状态的问题\n* 修正在“自动选择”模式时，当断开WIFI再重新连接后可能会出现无法自动选择有网络的连接的问题\n 优化：当显示任务栏窗口时，允许隐藏通知区图标。\n## V1.53 (2017/03/07)\n* 修正选择皮肤时可能会出现顺序错乱的问题\n* 优化：ini文件保存选择的皮肤的名称而不是序号，以解决添加或删除皮肤后选择的皮肤不正确的问题\n* 修正将焦点设置到任务栏窗口后按回车或ESC键任务栏窗口关闭的问题\n* 新增设置字体功能\n## V1.52 (2017/03/04)\n* 修正当显示任务栏窗口时，打开或关闭通知区图标会导致资源管理器卡住的问题\n* 优化：打开任务栏窗口时，窗口中的信息可以立即显示出来\n* 新增：允许取消开机自启动，“开机自动运行”菜单项增加复选标志\n## V1.51 (2017/03/02)\n* 修正重启资源管理器之后任务栏窗口无法正常显示的问题\n* 修正重启资源管理器之后通知区图标消失的问题\n* 修正任务栏窗口上网速显示字符串过长时字符显示不全的问题\n* 修正在特定情况下可能会导致程序停止工作的问题\n* 优化：当任务栏在屏幕左侧或右侧时，任务栏窗口的4个项目以竖排显示（必须关闭任务栏窗口再打开才能生效）\n* “关于”对话框中增加“联系作者”超链接\n## V1.50 (2017/02/25)\n* 新增更换皮肤功能（点击右键菜单——其他功能——更换皮肤，新增了7套皮肤）\n* 新增当网络变化时，自动更新“选择网络连接”中的子菜单项\n* 新增允许交换上传和下载的位置\n## V1.43 (2017/02/22)\n* 优化自动选择连接的处理，不选择已断开的连接\n* 修正任务栏窗口切换“显示CPU和内容利用率”后，“隐藏主窗口”的复选框消失的问题\n* 优化：当任务栏窗口无法嵌入任务栏时（如被安全软件阻止），如果任务栏把窗口覆盖，则窗口自动置顶。\n## V1.42 (2017/02/19)\n* 优化：任务栏窗口的位置不再总是固定，当任务栏最小化区域宽度变化时自动调整任务栏窗口的位置\n* 修正了当把任务放在桌面的左边或右边时任务栏窗口位置不正确的问题\n## V1.41 (2017/02/18)\n* 新增隐藏主界面功能\n* 更改设置时实时保存，解决关机时无法保存设置的问题\n* 新增开机自动运行功能，程序会创建快捷方式到开始菜单的启动目录\n* 新增在无法嵌入任务栏时强行将窗口移动到正确的位置，并弹出提示信息\n## V1.40 (2017/02/16)\n* 增加任务栏窗口，作为工具栏样式嵌入任务栏，不再占用屏幕区域\n* 增加主悬浮窗文字颜色设置\n* 任务栏窗口支持背景颜色和文字颜色设置\n## V1.30 (2017/02/13)\n* 增加CPU和内存利用率显示。\n* 增加鼠标穿透功能，悬浮窗不再影响鼠标操作\n## V1.20 (2017/02/11)\n* 去掉任务栏图标，增加通知区图标，右击通知区图标可弹出右键菜单\n* 右键菜单增加“锁定窗口位置”、“显示通知区域图标”项目\n* 增加移动时不允许超过屏幕边界的处理\n* 增加程序只允许一个实例运行的处理\n* 连接详情中增加自程序启动以来已发送和接收字节数显示，并增加数据以KB、MB或GB为单位的显示\n* 修正了当上传速度的字符串太长时可能会导致下载速度显示不全的BUG\n## V1.00 (2017/02/10)\n* 初版发行\n"
  },
  {
    "path": "UpdateLog/update_log_en-us.md",
    "content": "**[简体中文](./update_log.md) | [繁體中文](./update_log_zh-tw.md) | English**\n\n# TrafficMonitor Update log\n## V1.85.1 (2025/02/10)\n\n* Fixed the problem that when using third-party software to change to the classical taskbar in Windows 11, the option \"Taskbar window appears to the left of the taskbar\" in the Taskbar Window Settings is not available.\n\n* Fixed the problem that the position of the taskbar windows is not correct when there is no any icon on the taskbar. #1913\n* Fixed the problem that the \"Network speed data width\" does not take effect when clicking \"Apply\" in the Taskbar Window Settings. #1916\n* Windows 11 related settings in Taskbar Windows Settings moved to the new dialog. Add an option to avoid overlapping with right Widgets.\n* Fixed the problem that when \"CPU\" in Hardware Monitoring is not enabled, the \"CPU usage acquisition method\" will be changed back to the \"Based on CPU time\" when set it to \"Use the performance counter\".\n* Fixed the problem of messy charactors in the acknowledgement dialog.\n* Fixed the problem that the displayed net speed may be larger than the actual net speed when the \"Monitoring intervals\" is set too small. #1263 #1674\n* Fixed the problem that the \"Memory available\" in the taskbar window cannot be fully displayed when the memory exceeds 100G. #1722\n\n## V1.85 (2025/01/21)\n\n**Feature Updates:**\n\n* Add Direct2D rendering method to the taskbar window, whitch solve the problem that sometimes the edges of fonts are jagged. #1156\n* Add the support for Intel graphics cards for graphics card monitoring function.\n* Add a plugin menu to the context menu when right-clicking on a plugin item.\n* Add the plugin icon in the plugin management dialog, add plugin command for the context menu.\n* The maximum value of the monitoring interval is adjusted to 30s.\n* Add the options for \"Window offset top\" and \"Vertical Margin\" in the Taskbar Window Settings.\n* Add the support for transparent background images in png format to the main window.\n* Add the function of automatically switching skins according to the dark / light Windows color mode. #1013\n* Add the function of displaying the resource usage graph of the plug-in items in the taskbar, and updated the corresponding plug-in interface. #1077\n* Add the display of today's total traffic in the main window and taskbar window. #1174\n* Add \"Enable colorful emoji\" option in the taskbar window settings (Direct2D rendering only).\n* Upper limit of temperature notification in general settings adjusted to 120 degrees. #1814\n* Add the support for Arm64EC. #1703\n* Add the ability to display CPU frequency in Lite version.\n* Add default text color to \"Preset 2\" and \"Preset 3\" in Taskbar Settings - Preset.\n\n**Issue fixed:**\n* LibreHardwareMonitorLib.dll is updated to version 0.9.4. Solve the problem that hardware monitor information of some devices can't be displayed correctly.\n* Fixed the problem that the position of the  taskbar window is incorrect for touchscreen devices after Windows 11 build 22621.\n* Fixed the problem that the position of the taskbar window is incorrect when the Widgets did not exist under Windows 11. #1582\n* Fixed the problem that the taskbar window would overlap with the system Widgets when it was displayed on the right side under Windows 11.\n* Fixed the problem of scrolling too fast when using touchpad gestures in the Options Settings dialog.\n* Fixed the problem that the display of CPU frequency in the mouse tip of the main window is incorrect.\n* Fixed the problem that the display text for the plugin items in the skin files is invalid. #1813\n* Fixed the problem that if the notification area icon is hidden, it reappears after the notification popup. #1814 #1812 #1811\n\n## V1.84.1 (2022/11/18)\n\n* Fixed the issue that the taskbar window cannot be displayed on the left side in Window 11.\n* Fixed the issue that the information in the taskbar window could not be fully displayed when the taskbar on the left or right side of the desktop.\n* Fixed the issue in Windows 11 22H2, when all the windows are closed and no icons are fixed on the taskbar, the position of the taskbar window is not correct.\n* Added the support of long press to show context menu in touchscreen devices.\n* Fixed the issue that the position of the taskbar window is not correct due to the wide search button in the latest version of Windows 11.\n* Fixed the issue that the size of \"About\" dialog box is not correct.\n\n## V1.84 (2022/10/05)\n\n* Fixed the problem that the position of the taskbar window is not correct in Windows 11 22H2.\n* Fixed the problem that the taskbar window overlapped with the system widgets when the taskbar window displayed on the left side in Windows 11.\n* Added display of CPU frequency.\n* Fixed the problem that the \"/s\" of the net speed is missing in the main window.\n* Fixed the problem that may cause insufficient string buffer when writing INI files.\n* Updated the plugin interface that allows plugin response keyboard events.\n* Fixed the problem that the taskbar window would not display properly after switching between different DPI monitors.\n* Fixed the problem where \"Options\" dialog box would pop up when selecting \"Details\" from the context menu in the \"Plugin Management\" dialog.\n* Update the HardwareMonitor lib to resolve the problem that the temperature of Intel 12th Gen processor cannot be obtained.\n\n## V1.83 (2022/02/03)\n\n* Fixed the problem that when there is already a task plan of auto-run, the auto-run at start up will be failed to set.\n* Added the \"Program is already running\" dialog box at the program is started when there is already a TrafficMonitor process running.\n* Added the plug-in information in the mouse tool tips.\n* Fixed an issue where plugins could still be loaded if they were disabled.\n* Added the support of free sorting of plugin items in the taskbar.\n* Added the function to select the network connections to be displayed in the \"Network Connection List\" in the option settings.\n* Added the function of displaying the total network speed.\n* Added the function of displaying the network speed graph in the taskbar.\n* Fixed the problem that only one hard disk can be displayed when there are multiple hard disks with the same name in the hardware monitor.\n* Optimize the display effect of the resource usage graph in plot mode of the taskbar window.\n* Change the \"Display Settings\" in the taskbar window context menu from menu to dialog box.\n* Added \"Refresh connection list\" command to \"Select Network Connections\" menu.\n* Fixed some crashes.\n\n## V1.82 (2021/12/12)\n\n* Added a new plug-in system, you can display more customized content in the taskbar window and the main window through the plug-in.\n* Added the \"Task Manager\" command to the taskbar window context menu.\n* Added the \"Apply\" button to the option settings dialog.\n* Added weekly view in historical traffic statistics.\n* Added the setting of task bar item spacing.\n* Fixed the problem that the taskbar window context menu cannot pop up in the dark mode of Windows 11.\n* Fixed the problem that the taskbar window could not be displayed when the taskbar was restored to the Windows 10 style using software such as StartAllBack under Windows 11.\n\n## V1.81 (2021/07/27)\n\n* Fixed some crashes since version 1.80.\n* Added the support of custom sorting of the items in the taskbar window.\n* When the number of items displayed in the taskbar window is odd, the last item is arranged vertically to save space on the taskbar.\n* Added the function of monitoring the hard disk usage.\n* Add some settings in the right-click menu to the option settings dialog.\n* Added the support for multiple monitors of the main window. You can move the main window to other monitors without checking \"Allow out of screen boundaries\".\n\n## V1.80.3 (2021/05/29)\n\n* Fixed the problem that the CPU temperature cannot be displayed\n* Added the function to select the temperature of specified CPU core to monitor.\n* Fixed a problem that caused the program crashed.\n\n## V1.80.2 (2021/05/22)\n\n* Fixed several issues that cause the program crashed.\n* Use LibreHardwareMonitor to obtain temperature information.\n* Added the function to select the temperature of which hard drive to monitor.\n* Added the function to select the hardware to monitor.\n* Fix the problem that the LibreHardwareMonitorLib.sys file is not released when the program exits.\n\n## V1.80.1 (2021/05/17)\n\n* Fixed the problem that the temperature of AMD GPU could not be obtained.\n* Fixed the problem that the program crashes when automatically switching to the light mode color preset.\n* Fixed the problem that the temperature of the 11th generation Intel processor cannot be obtained.\n* Fixed the problem that the auto-start setting does not work.\n\n## V1.80 (2021/05/15)\n\n* Added the function of monitoring the temperature of CPU, GPU, hard disk and main board.\n* Added the function of monitoring the GPU usage.\n* Fixed the problem that the historical traffic statistics is not correct caused by the data overflowed.\n* Fixed the problem that the main window position was incorrect after the screen resolution was changed.\n* Fixed the problem that the size of the interface elements of the main window and taskbar window would not change after the system DPI was changed.\n* Added the ability to freely specify display items in the taskbar window.\n* Added xml format of the main window skin, supporting temperature display.\n* Fixed the problem that the sub-windows in the option settings cannot be scrolled by the touch screen when using a touch screen device.\n* Put the processing of checking for updates into a background thread to solve the problem that the program does not respond for a long time when checking for update.\n* Fix the problem that the program is abnormal after pressing Alt+F4 in the taskbar window.\n* Added support for net speeds above 4GB per second.\n* Added the option to set the update source as Gitee to solve the problem that the program cannot be updated sometimes due to the inaccessibility of GitHub in mainland China.\n* Added setting of memory display mode.\n* Fix the problem that the currently monitored network connection is closed or disabled, the previously monitored network connection cannot be automatically selected after restarted.\n* Auto run at boot is realized by Task Scheduler to solve the problem that the auto run at boot dose not work sometimes.\n* Fix some crashes.\n* Improvements in other details.\n\n## V1.79.1 (2020/08/05)\n\n* Fix the problem of registry handle leak.\n* Fixed the problem that CPU and memory usage are not counted when the main window and taskbar window are not displayed.\n\n## V1.79 (2020/07/30)\n\n* Add the function of automatically adapts to the Windows 10 dark/light theme of the taskbar window color.\n* Add the function of automatically adapts to the Windows 10 dark/light theme of the notification area icon.\n* Add the option of CPU usage acquisition method. Fix the problem that the CPU usage may always 0 of some users.\n* Remove the option of \"Transparent color\" in \"Options\"-\"Taskbar Window Settings\", and add the option of \"Background Color Transparent\".\n* Allows only CPU and memory usage displayed in the taskbar window without the net speed.\n* Fixes an problem that the settings may not be saved after the shutdown.\n* Add the setting of \"the first day of the week\" in the \"Historical Traffic Statistics\"-\"Calendar View\".\n* Add the function of displaying history traffic by day, month, quarter and year in the \"Historical Traffic Statistics\"-\"List View\".\n* May fixed the problem of the loss of historical traffic data in small probability.\n* Fixed the problem that the right-click menu cannot pop up if the taskbar window background is set to transparent in Windows 10 light theme.\n* Fixed the problem that traffic statistics does not support data exceeding 2TB.\n* Added icons for menu items.\n* Save the data to the AppData directory when the program's directory cannot be written.\n* Add the function of setting the monitoring interval.\n\n## V1.78 (2020/03/21)\n\n* Add the function to open the specified application by double-clicking the main window or taskbar window.\n* Add the function to display the CPU and memory utilization status bar in the taskbar window.\n* Fix the inconsistence of CPU usage with the task manager in Windows 10.\n* Added option to show mouse tool tips.\n* Added the function to set the taskbar color according to Windows 10 light mode when the program is first started.\n* Added the function of preset schemes in the taskbar settings.\n* Improvements in other details.\n\n## V1.77 (2019/05/01)\n* Add the transparent color setting of the task window. Fix the problem that the text color of the taskbar window cannot be set to black when the taskbar is white (Set the transparent color in \"Options\" - \"Taskbar Window Settings\").\n* Add the function to display crash information when the program crashes.\n* Fix the problem that the screen will flicker when the Windows Explorer restarts if the taskbar window is displayed.\n* Display monitoring information when the mouse points to the notification area icon.\n* Fixed the problem that the network speed could not be displayed when using a Bluetooth network.\n* Added x64 version.\n* Improvements in other details.\n### Release Notes:\nThis update solves the problem that the text is not clear in the taskbar when the taskbar is white in the latest version of Windows 10. You need to manually set the transparent color in \"Options\" - \"Taskbar Window Settings\" - \"Transparent Color\". It is an opaque effect when the transparent color is not black and is different from the background color, and is transparent if it is the same as the background color. In the Windows 10 white taskbar, it is recommended to set as the following picture:\n![白色任务栏截图](https://user-images.githubusercontent.com/30562462/57004858-36b55300-6c05-11e9-89d8-9911dc99f09c.PNG)\n## V1.76 (2018/11/11)\n* Fix the problem that the resolution changes may cause the program crash.\n* Add the options for the saving location of the configuration files.\n* Fix the problem that the vertical position of the taskbar window was incorrect when the resolution changed.\n* Add the display of today’s upload and download traffic. Add the upload and download traffic statics in the history traffic static dialog.\n* Improvements in other details.\n"
  },
  {
    "path": "UpdateLog/update_log_zh-tw.md",
    "content": "**[简体中文](./update_log.md) | 繁體中文 | [English](./update_log_en-us.md)**\n\n# TrafficMonitor 更新日誌\n\n## V1.85.1 (2025/02/10)\n\n* 修正Windows11下使用第三方軟體改成舊版工作列時，工作列視窗設定中“工作列視窗顯示在工作列左側”選項不可用的問題\n* 修正當工作列上沒有任何圖示時工作列視窗的位置不正確的問題 #1913\n* 修正工作列視窗設定中點選“應用”時網速資料寬度不生效的問題 #1916\n* 工作列設定中Windows11相關設定移動到單獨的對話方塊中，增加避免與右側小元件重疊的選項\n* 修正未啟用硬體監控中的CPU監控時，CPU使用率獲取方式改成使用效能計數器後，會改回基於CPU使用時間的問題\n* 修正鳴謝介面有亂碼的問題\n* 修正當監控時間間隔設定得過小時，顯示的網速可能會大於實際網速問題 #1263 #1674\n* 修正當記憶體超過100G時顯示工作列剩餘記憶體顯示不全的問題 #1722\n\n## V1.85 (2025/01/21)\n\n**功能更新：**\n\n* 工作列視窗增加Direct2D的渲染方式，解決有時字型邊緣有鋸齒的問題 #1156\n* 顯示卡監控功能增加對英特爾顯示卡的支援 \\#1751\n* 右擊外掛條目時的右鍵選單中增加外掛選單\n* 外掛管理介面增加外掛圖示的顯示，右鍵選單中增加外掛命令\n* 監控時間間隔的最大值調整為30s\n* 工作列視窗設定中增加“視窗頂部邊距”和“垂直邊距”的選項\n* 主視窗增加對png格式透明背景圖片的支援\n* 新增根據Windows深淺色模式自動切換面板的功能 #1013\n* 新增在工作列的外掛條目中顯示資源佔用圖的功能，並更新對應的外掛介面 #1077\n* 主視窗和工作列視窗中新增今日總流量的顯示 #1174\n* 工作列視窗設定中新增“使用彩色emoji”的選項（僅Direct2D渲染方式）\n* 常規設定中的溫度通知上限調整為120度 #1814\n* 新增Arm64EC的支援 #1703\n* 新增Lite版顯示CPU頻率的功能\n* 工作列設定-預設方案中的方案2和方案3增加預設的文字顏色\n\n**問題修正：**\n\n* LibreHardwareMonitorLib.dll更新到0.9.4版本，解決部分裝置硬體監控資訊無法正常顯示的問題\n* 修正Windows 11 build 22621版本後觸屏裝置工作列視窗位置不正確的問題\n* 修正Windows 11下小工具不存在時，工作列視窗的位置不正確的問題的問題 #1582\n* 修正Windows 11下，當工作列視窗顯示在右側時，會和系統小工具重疊的問題\n* 修正選項設定對話方塊中使用觸控板手勢時滾動過快的問題\n* 修正主視窗滑鼠提示中CPU頻率顯示不正確的問題\n* 修正面板檔案中外掛專案的顯示文字無效的問題 #1813\n* 修正如果隱藏了通知區圖示，彈出通知後通知區圖示再次出現的問題 #1814 #1812 #1811\n\n## V1.84.1 (2022/11/18)\n\n* 修正Windows11下工作列視窗無法顯示到左邊的問題。\n* 修正工作列顯示在桌面兩側時工作列視窗會顯示不全的問題。\n* 修正Windows11 22H2中，關閉了所有視窗且工作列上沒有固定任何圖示時，工作列視窗位置不正確的問題。\n* 為觸屏裝置新增長按右鍵選單的支援。\n* 修正由於最新版本Windows11中搜索按鈕比較寬導致工作列視窗的位置不正確的問題。\n* 修正“關於”對話方塊的大小有時不正確的問題。\n\n## V1.84 (2022/10/05)\n\n* 修正Windows11 22H2版本中工作列視窗位置不正確的問題。\n* 修正Windows11下工作列視窗顯示在左側時會和系統自帶的小元件重疊的問題。\n* 新增CPU頻率的顯示。\n* 修正主視窗網速單位缺少“/s”的問題。\n* 修正寫入ini檔時可能導致字串緩衝區不足的問題。\n* 外掛程式介面更新，允許外掛程式回應鍵盤事件。\n* 修正工作列視窗在不同DPI顯示器切換後顯示不正常的問題。\n* 修正“外掛管理”介面中在右鍵功能表中選擇“詳細資訊”會彈出“選項”對話方塊的問題。\n* 更新HardwareMonitor lib 以解決無法獲取 Intel 12 代處理器溫度的問題。\n\n## V1.82 (2021/12/12)\n\n* 修正當已經存在一個開機自啟動的任務計劃時，無法設定開機自啟動的問題，\n* 新增當已經存在TrafficMonitor程序時啟動程式，彈出“程式已經在執行”對話方塊。\n* 滑鼠提示中新增外掛資訊的顯示。\n* 修正外掛被禁用後仍然會被載入的問題。\n* 工作列中的外掛專案支援自由排序。\n* 選項設定中新增可以選擇要在“網路連線列表”中顯示的網路的功能。\n* 新增顯示總網速的功能。\n* 新增在工作列中顯示網速佔用圖的功能。\n* 修正硬體監控中有多個名稱相同的硬碟時只能顯示一個硬碟的問題。\n* 最佳化工作列視窗橫向滾動圖的顯示效果。\n* 工作列視窗右鍵選單中的“顯示設定”由選單改為對話方塊形式。\n* “選擇網路連線”選單中新增“重新整理網路連線列表”命令。\n* 修正幾處導致程式崩潰的問題。\n\n## V1.82 (2021/12/12)\n\n* 新增外掛系統，可以透過外掛在工作列視窗和主視窗顯示更多自定義內容。\n* 工作列右鍵選單中增加“工作管理員”命令。\n* 選項設定中新增“應用”按鈕。\n* 歷史流量統計中增加周檢視。\n* 新增工作列專案間距的設定。\n* 修正Windows11深色模式下工作列右鍵選單無法彈出的問題。\n* 修正Windows11下使用StartAllBack等軟體將工作列恢復為Windows10樣式時，工作列視窗無法顯示的問題。\n\n## V1.81 (2021/07/27)\n\n* 修正1.80版本以來的一些崩潰的問題\n* 工作列視窗顯示專案支援自定義排序\n* 工作列視窗中顯示的專案數量為奇數時，最後一個專案垂直排列，以節省工作列空間\n* 新增顯示硬碟利用率的功能\n* 將右鍵選單中的一些設定新增到選項設定介面中\n* 新增主視窗對多顯示器的支援，在不勾選“允許超出螢幕邊界”的情況下也能移動到其他顯示器了\n\n## V1.80.3 (2021/05/29)\n\n* 修正無法顯示CPU溫度的問題\n* 新增可以選擇監控指定CPU核心的溫度的功能\n* 修正一處導致程式崩潰的問題\n\n## V1.80.2 (2021/05/22)\n\n* 修正幾處導致程式崩潰的問題\n* 獲取溫度資訊改用LibreHardwareMonitor\n* 新增可選擇要監控哪塊硬碟的溫度的功能\n* 新增可選擇要監控哪些硬體的功能\n* 修正程式退出時LibreHardwareMonitorLib.sys檔案沒有解除佔用的問題\n\n## V1.80.1 (2021/05/17)\n\n* 修正無法獲取AMD顯示卡溫度的問題\n* 修正自動切換為淺色模式顏色預設時程式崩潰的問題\n* 修正無法獲取11代Intel處理器溫度的問題\n* 修正設定開機自啟動無效的問題\n\n## V1.80 (2021/05/15)\n\n* 新增CPU、顯示卡、硬碟和主機板溫度監控的功能\n* 新增顯示卡利用率監控的功能\n* 修正歷史流量統計數值溢位導致統計數值不正確的問題\n* 修正螢幕解析度更改後主視窗位置不正確的問題\n* 修正系統DPI更改後，主視窗和工作列視窗介面元素的大小不會隨DPI變化的問題\n* 新增工作列視窗自由指定顯示專案的功能\n* 新增xml格式的主視窗面板，支援溫度顯示\n* 修正使用觸屏裝置時，選項設定中的子視窗無法使用觸屏滾動的問題\n* 將檢查更新的處理放到後臺執行緒中，以解決檢查更新時程式長時間沒有響應的問題\n* 修正工作列視窗中按Alt+F4後程序異常的問題\n* 新增對每秒4GB以上網速的支援\n* 新增可選擇更新源為Gitee，以解決中國大陸地區有時無法訪問GitHub導致程式無法更新的問題\n* 新增記憶體顯示方式設定\n* 修正當前監控的網絡卡被關閉或禁用，再次啟動後無法自動選擇之前監控的網絡卡的問題\n* 開機自啟動採用任務計劃實現，以解決有時開機自啟動無效的問題\n* 修正一些崩潰的問題\n* 其他細節方面的改進\n\n## V1.79.1 (2020/08/05)\n\n* 修正登錄檔控制碼洩漏的問題。\n* 修正當主視窗和工作列視窗都不顯示時，不統計CPU和記憶體利用率的問題。\n\n## V1.79 (2020/07/30)\n\n* 新增工作列視窗顏色自動適應Windows10深色/淺色主題的功能。\n* 新增通知區圖示自動適應Windows10深色/淺色主題的功能。\n* 增加CPU獲取方式的設定，解決部分使用者出現的CPU利用率始終為0的問題。\n* 選項設定>工作列設定中去掉「透明色」選項，新增「背景色透明」的選項。\n* 新增允許工作列只顯示CPU和記憶體利用量而不顯示網速。\n* 修正了關機後設置可能會沒有儲存的問題。\n* 歷史流量統計-日曆檢視中增加了每週第一天的設定。\n* 歷史流量統計-列表檢視中增加了按年、月、日、季度統計的功能。\n* 可能解決了歷史流量資料有小概率丟失的問題。\n* 修正Windows10淺色主題時，如果工作列視窗背景設定為透明，會無法彈出右鍵選單的問題。\n* 修正流量統計不支援統計超過2TB的問題。\n* 為選單項添加了圖示。\n* 當程式所在目錄無法寫入時，將資料儲存到AppData目錄。\n* 新增設定監視時間間隔的功能。\n\n## V1.78 (2020/03/21)\n\n* 新增按兩下主視窗或工作列視窗開啟指定應用程式的功能\n* 新增工作列視窗中顯示CPU和RAM可用狀態條的功能\n* 修正 Windows 10 中 CPU 使用量和工作管理員不一致的問題\n* 新增是否顯示游標提示的選項\n* 新增程式首次啟動時根據 Windows 10 淺色模式設定工作列顏色的功能\n* 工作列設定中增加預設方案的功能\n* 其他細節方面的改進\n\n## V1.77 (2019/05/01)\n* 新增工作列視窗透明色設定，修正工作列為白色時工作列視窗文字顏色無法設定為黑色的問題（在 [選項] —— [工作列視窗設定] 中設定透明色）\n* 新增程式崩潰時顯示崩潰資訊的功能\n* 修正顯示工作列視窗的情况下，檔案總管重新啟動時會導致螢幕畫面閃爍的問題\n* 新增滑鼠指向通知區域圖示時顯示監控資訊\n* 修正使用藍牙網路時無法顯示網速的問題\n* 新增x64的版本\n* 其他細節方面的改進\n### 更新說明：\n本次更新在一定程度上解決了Win10最新版本中白色工作列時文字看不清的問題。需要手動在“選項”——“工作列視窗設定”——“透明色”設定透明色。當透明色不為黑色且和背景色不同時為不透明效果，如果和背景色相同則為透明效果。在Win10白色工作列中建議如下圖所示設定：\n![白色任务栏截图](https://user-images.githubusercontent.com/30562462/57004858-36b55300-6c05-11e9-89d8-9911dc99f09c.PNG)\n\n## V1.76 (2018/11/11)\n* 修正了解析度更改可能會導致程式崩潰的問題；\n* 新增設定檔儲存位置的選項；\n* 修正了當解析度更改時工作列視窗的垂直位置不正確的問題；\n* 新增今日上傳和下載流量的顯示，歷史流量統計中增加上傳和下載流量的統計；\n* 其他細節方面的改進。\n\n"
  },
  {
    "path": "include/OpenHardwareMonitor/OpenHardwareMonitorApi.h",
    "content": "﻿#pragma once\n#include <memory>\n#include \"OpenHardwareMonitorGlobal.h\"\n#include <map>\n#include <string>\n\nnamespace OpenHardwareMonitorApi\n{\n    class IOpenHardwareMonitor\n    {\n    public:\n        virtual void GetHardwareInfo() = 0;     //获取一次硬件信息\n        virtual float CpuTemperature() = 0;     //返回获取到的CPU温度\n        virtual float GpuTemperature() = 0;     //返回获取到的GPU温度\n        virtual float HDDTemperature() = 0;     //返回获取到的硬盘温度\n        virtual float MainboardTemperature() = 0;   //返回获取到的主板温度\n        virtual float GpuUsage() = 0;           //返回获取到的GPU利用率\n        virtual float CpuFreq() = 0;            //返回获取到的CPU频率\n        virtual float CpuUsage() = 0;           //返回获取的CPU利用率\n        virtual const std::map<std::wstring, float>& AllHDDTemperature() = 0;   //返回所有硬盘的温度。map的key是硬盘的名称，value是硬盘的温度\n        virtual const std::map<std::wstring, float>& AllCpuTemperature() = 0;   //返回所有CPU（核心）的温度。map的key是CPU的名称，value是硬盘的温度\n        virtual const std::map<std::wstring, float>& AllHDDUsage() = 0;         //返回所有硬盘的使用率\n\n        virtual void SetCpuEnable(bool enable) = 0;\n        virtual void SetGpuEnable(bool enable) = 0;\n        virtual void SetHddEnable(bool enable) = 0;\n        virtual void SetMainboardEnable(bool enable) = 0;\n    };\n\n    OPENHARDWAREMONITOR_API std::shared_ptr<IOpenHardwareMonitor> CreateInstance();\n    OPENHARDWAREMONITOR_API std::wstring GetErrorMessage();\n}\n"
  },
  {
    "path": "include/OpenHardwareMonitor/OpenHardwareMonitorGlobal.h",
    "content": "﻿#pragma once\n\n#ifdef OPENHARDWAREMONITOR_EXPORTS\n#define OPENHARDWAREMONITOR_API __declspec(dllexport)\n#else\n#define OPENHARDWAREMONITOR_API __declspec(dllimport)\n#endif\n"
  },
  {
    "path": "include/PluginInterface.h",
    "content": "﻿/*********************************************************\n* TrafficMonitor 插件接口\n* Copyright (C) by Zhong Yang 2021\n* zhongyang219@hotmail.com\n**********************************************************/\n#pragma once\n\n//插件显示项目的接口\nclass IPluginItem\n{\npublic:\n    /**\n     * @brief   获取显示项目的名称\n     * @return  const wchar_t*\n     */\n    virtual const wchar_t* GetItemName() const = 0;\n\n    /**\n     * @brief   获取显示项目的唯一ID\n     * @return  const wchar_t*\n     */\n    virtual const wchar_t* GetItemId() const = 0;\n\n    /**\n     * @brief   获取项目标签的文本\n     * @return  const wchar_t*\n     */\n    virtual const wchar_t* GetItemLableText() const = 0;\n\n    /**\n     * @brief   获取项目数值的文本\n     * @detail  由于此函数可能会被频繁调用，因此不要在这里获取监控数据，\n     *  而是在ITMPlugin::DataRequired函数中获取数据后保存起来，然后在这里返回获取的数值\n     * @return  const wchar_t*\n     */\n    virtual const wchar_t* GetItemValueText() const = 0;\n\n    /**\n     * @brief   获取项目数值的示例文本\n     * @detail  此函数返回的字符串的长度会用于计算显示区域的宽度\n     * @return  const wchar_t*\n     */\n    virtual const wchar_t* GetItemValueSampleText() const = 0;\n\n    /**\n     * @brief   显示区域是否由插件自行绘制\n     * @detail\n     *  如果返回false，则根据GetItemLableText和GetItemValueText返回的文本由主程序绘制显示区域，重写DrawItem函数将不起作用。\n     *  如果重写此函数并返回true，则必须重写DrawItem函数并在里面添加绘制显示区域的代码，\n     *  此时GetItemLableText、GetItemValueText和GetItemValueSampleText的返回值将被主程序忽略\n     * @return  bool\n     */\n    virtual bool IsCustomDraw() const { return false; }\n\n    /**\n     * @brief   获取显示区域的宽度\n     * @detail\n     *  只有当CustomDraw()函数返回true时重写此函数才有效。\n     *  返回的值为DPI为96（100%）时的宽度，主程序会根据当前系统DPI的设置自动按比例放大，\n     *  因此你不需要为不同的DPI设置返回不同的值。\n     *  需要注意的是，这里的返回值代表了自绘区域所需要的最小宽度，DrawItem函数中的参数w的值可能会大于这个值\n     * @return  int\n     */\n    virtual int GetItemWidth() const { return 0; }\n\n    /**\n     * @brief   自定义绘制显示区域的函数，只有当CustomDraw()函数返回true时重写此函数才有效\n     * @param   void * hDC 绘图的上下文句柄\n     * @param   int x 绘图的矩形区域\n     * @param   int y\n     * @param   int w\n     * @param   int h\n     * @param   bool dark_mode 深色模式为true，浅色模式为false\n     * @return  void\n     */\n    virtual void DrawItem(void* hDC, int x, int y, int w, int h, bool dark_mode) {}\n\n    /**\n     * @brief   获取显示区域的宽度\n     * @detail\n     *  只有当CustomDraw()函数返回true时重写此函数才有效。\n     *  此函数和GetItemWidth不同，插件可以根据参数hDC来计算需要的宽度，\n     *  它返回的是实际的宽度，主程序不会根据当前系统的DPI对返回值进行放大。\n     *  需要注意的是，这里的返回值代表了自绘区域所需要的最小宽度，DrawItem函数中的参数w的值可能会大于这个值\n     * @param   void * hDC 绘图的上下文句柄\n     * @return  int\n     */\n    virtual int GetItemWidthEx(void* hDC) const { return 0; }\n\n    /** 鼠标事件的类型 */\n    enum MouseEventType\n    {\n        MT_LCLICKED,    /**< 点击了鼠标左键 */\n        MT_RCLICKED,    /**< 点击了鼠标右键 */\n        MT_DBCLICKED,   /**< 双击了鼠标左键 */\n        MT_WHEEL_UP,    /**< 向上滚动了鼠标滚轮 */\n        MT_WHEEL_DOWN,  /**< 向下滚动了鼠标滚轮 */\n    };\n\n    enum MouseEventFlag\n    {\n        MF_TASKBAR_WND = 1 << 0,        /**< 是否为任务栏窗口的鼠标事件 */\n    };\n\n    /**\n     * @brief   当插件显示区域有鼠标事件时由主程序调用\n     * @param   MouseEventType type 鼠标事件的类型\n     * @param   int x 鼠标指针所在的x坐标\n     * @param   int y 鼠标指针所在的y坐标\n     * @param   void* hWnd 产生此鼠标事件的窗口的句柄（主窗口或任务栏窗口）\n     * @param   int flag 为若干MouseEventFlag枚举常量的组合\n     * @return  int 如果返回非0，则主程序认为插件已经对此鼠标事件作出了全部的响应，主程序将不会再对此鼠标事件做额外的响应。\n     *   例如当type为MT_RCLICKED时，如果程序返回0，则会弹出主程序提供的右键菜单；而返回非0时，主程序不会再做任何处理。\n     */\n    virtual int OnMouseEvent(MouseEventType type, int x, int y, void* hWnd, int flag) { return 0; }\n\n    enum KeyboardEventFlag\n    {\n        KF_TASKBAR_WND = 1 << 0,        /**< 是否为任务栏窗口的键盘事件 */\n    };\n\n    /**\n     * @brief   当插件显示区域有键盘事件时由主程序调用\n     * @param   int key 按下的键\n     * @param   bool ctrl 是否按下了Ctrl键\n     * @param   bool shift 是否按下了Shift键\n     * @param   bool alt 是否按下了Alt键\n     * @param   void* hWnd 产生此键盘事件的窗口的句柄（主窗口或任务栏窗口）\n     * @param   int flag 为若干KeyboardEventFlag枚举常量的组合\n     * @return  int 如果返回非0，则主程序认为插件已经对此键盘事件作出了全部的响应，主程序将不会再对此键盘事件做额外的响应。\n     */\n    virtual int OnKeboardEvent(int key, bool ctrl, bool shift, bool alt, void* hWnd, int flag) { return 0; }\n\n    enum ItemInfoType\n    {\n\n    };\n    //预留的接口\n    virtual void* OnItemInfo(ItemInfoType, void* para1, void* para2) { return 0; }\n\n    /**\n     * @brief 是否在在任务栏中显示此项目的资源占用图\n     * @return 1：显示，0：不显示\n     */\n    virtual int IsDrawResourceUsageGraph() const { return 0; }\n\n    /**\n     * @brief 获取资源占用图的值。当IsDrawResourceUsageGraphType返回值不为0时有效\n     * @return float 资源占用图的值，范围为0.0~1.0。\n     */\n    virtual float GetResourceUsageGraphValue() const { return 0.0; }\n};\n\nclass ITrafficMonitor;\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////\n//插件接口\nclass ITMPlugin\n{\npublic:\n    /**\n     * @brief   插件接口的版本，仅当修改了插件接口时才会修改这里的返回值。\n     * @attention 插件开发者不应该修改这里的返回值，也不应该重写此虚函数。\n     * @return  int\n     */\n    virtual int GetAPIVersion() const { return 7; }\n\n    /**\n     * @brief   获取插件显示项目的对象\n     * @detail  一个插件dll可以提供多个实现IPluginItem接口的对象，对应多个显示项目。\n     *  当index的值大于或等于0且小于IPluginItem接口的对象的个数时，返回对象的IPluginItem接口的指针，其他情况应该返回空指针。\n     *  例如插件提供两个显示项目，则当index等于0或1时返回对应IPluginItem接口的对象，其他值时必须返回空指针。\n     * @param   int index 对象的索引\n     * @return  IPluginItem* 插件显示项目的对象\n     */\n    virtual IPluginItem* GetItem(int index) = 0;\n\n    /**\n     * @brief   主程序会每隔一定时间调用此函数，插件需要在函数里获取一次监控的数据\n     */\n    virtual void DataRequired() = 0;\n\n    /** 选项设置对话框的返回值 */\n    enum OptionReturn\n    {\n        OR_OPTION_CHANGED,          /**< 选项设置对话框中更改了选项设置 */\n        OR_OPTION_UNCHANGED,        /**< 选项设置对话框中未更改选项设置 */\n        OR_OPTION_NOT_PROVIDED      /**< 未提供选项设置对话框 */\n    };\n\n    /**\n     * @brief   主程序调用此函数以打开插件的选项设置对话框\n     * @detail  此函数不一定要重写。如果插件提供了选项设置界面，则应该重写此函数，并在最后返回OR_OPTION_CHANGED或OR_OPTION_UNCHANGED。\n     * @param   void * hParent 父窗口的句柄\n     *  返回值为OR_OPTION_NOT_PRVIDED则认为插件不提供选项设置对话框。\n     * @return  ITMPlugin::OptionReturn\n     */\n    virtual OptionReturn ShowOptionsDialog(void* hParent) { return OR_OPTION_NOT_PROVIDED; }\n\n    /** 插件信息的索引 */\n    enum PluginInfoIndex\n    {\n        TMI_NAME,           /**< 名称 */\n        TMI_DESCRIPTION,    /**< 描述 */\n        TMI_AUTHOR,         /**< 作者 */\n        TMI_COPYRIGHT,      /**< 版权 */\n        TMI_VERSION,        /**< 版本 */\n        TMI_URL,            /**< 主页 */\n        TMI_MAX             /**< 插件信息的最大值 */\n    };\n\n    /**\n     * @brief   获取此插件的信息，根据index的值返回对应的信息\n     */\n    virtual const wchar_t* GetInfo(PluginInfoIndex index) = 0;\n\n    /** 主程序的监控信息 */\n    struct MonitorInfo\n    {\n        unsigned long long up_speed{};\n        unsigned long long down_speed{};\n        int cpu_usage{};\n        int memory_usage{};\n        int gpu_usage{};\n        int hdd_usage{};\n        int cpu_temperature{};\n        int gpu_temperature{};\n        int hdd_temperature{};\n        int main_board_temperature{};\n        int cpu_freq{};\n    };\n\n    /**\n     * @brief   主程序调用此函数以向插件传递所有获取到的监控信息\n     */\n    virtual void OnMonitorInfo(const MonitorInfo& monitor_info) {}\n\n    /**\n     * @brief   获取插件要在鼠标提示中显示的文本\n     */\n    virtual const wchar_t* GetTooltipInfo() { return L\"\"; }\n\n    enum ExtendedInfoIndex\n    {\n        EI_LABEL_TEXT_COLOR,    //绘图的标签文本颜色\n        EI_VALUE_TEXT_COLOR,    //绘图的数值文本颜色\n        EI_DRAW_TASKBAR_WND,    //是否绘制任务栏窗口\n\n        //主窗口选项设置\n        EI_NAIN_WND_NET_SPEED_SHORT_MODE,   //网速显示简洁模式\n        EI_MAIN_WND_SPERATE_WITH_SPACE,     //数值和单位使用空格分隔\n        EI_MAIN_WND_UNIT_BYTE,              //网速单位是否使用B（字节）\n        EI_MAIN_WND_UNIT_SELECT,            //网速单位选择（0：自动，1：固定为KB/s，2：固定为MB/s）\n        EI_MAIN_WND_NOT_SHOW_UNIT,          //不显示网速单位\n        EI_MAIN_WND_NOT_SHOW_PERCENT,       //不显示百分号\n\n        //任务栏窗口设置\n        EI_TASKBAR_WND_NET_SPEED_SHORT_MODE,    //网速显示简洁模式\n        EI_TASKBAR_WND_SPERATE_WITH_SPACE,      //数值和单位使用空格分隔\n        EI_TASKBAR_WND_VALUE_RIGHT_ALIGN,       //数值右对齐\n        EI_TASKBAR_WND_NET_SPEED_WIDTH,         //网速数据宽度\n        EI_TASKBAR_WND_UNIT_BYTE,               //网速单位是否使用B（字节）\n        EI_TASKBAR_WND_UNIT_SELECT,             //网速单位选择（0：自动，1：固定为KB/s，2：固定为MB/s）\n        EI_TASKBAR_WND_NOT_SHOW_UNIT,           //不显示网速单位\n        EI_TASKBAR_WND_NOT_SHOW_PERCENT,        //不显示百分号\n\n        EI_CONFIG_DIR,                      //配置文件的目录\n    };\n\n    /**\n     * @brief   主程序调用此函数以向插件传递更多信息\n     * @param   ExtendedInfoIndex index 信息的索引，用于区分向插件传递的信息\n     * @param   const wchar_t* data 传递的数据\n     * @return  void\n     */\n    virtual void OnExtenedInfo(ExtendedInfoIndex index, const wchar_t* data) {}\n\n    /**\n     * @brief   获取插件的图标，HICON格式\n     */\n    virtual void* GetPluginIcon() { return nullptr; }\n\n    /**\n     * @brief   获取插件的命令的数量\n     * @return  int 插件的命令的数量\n     */\n    virtual int GetCommandCount() { return 0; }\n\n    /**\n     * @brief   获取插件的命令名称\n     * @param   int command_index 插件命令的索引（从0开始，小于GetCommandCount()的返回值）\n     * @return  wchar_t* 插件命令的名称\n     */\n    virtual const wchar_t* GetCommandName(int command_index) { return nullptr; }\n\n    /**\n     * @brief   获取插件的命令图标\n     * @param   int command_index 插件命令的索引（从0开始，小于GetCommandCount()的返回值）\n     * @return  void* 插件命令的图标，HICON格式\n     */\n    virtual void* GetCommandIcon(int command_index) { return nullptr; }\n\n    /**\n     * @brief   执行一个插件命令时由框架调用\n     * @param   int command_index 插件命令的索引（从0开始，小于GetCommandCount()的返回值）\n     * @param   void* hWnd 发送此命令的窗口句柄\n     * @param   void* para 预留参数\n     */\n    virtual void OnPluginCommand(int command_index, void* hWnd, void* para) {}\n\n    /**\n    * @brief   获取插件命令是否处于勾选状态\n    * @param   int command_index 插件命令的索引（从0开始，小于GetCommandCount()的返回值）\n    * @return  1：已勾选；0：未勾选\n    */\n    virtual int IsCommandChecked(int command_index) { return false; }\n\n    /**\n     * @brief   插件初始化\n     * @detail  当插件被加载时被调用，传递ITrafficMonitor接口的指针。插件可以保存此指针以调用ITrafficMonitor接口中的函数\n     * @param   pApp\n     */\n    virtual void OnInitialize(ITrafficMonitor* pApp) {}\n};\n\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////\n//主程序接口\nclass ITrafficMonitor\n{\npublic:\n    /**\n     * @brief   获取此接口的版本。\n     * @attention 插件在调用ITrafficMonitor中的函数时需要先判断接口的版本\n     * @return  int\n     */\n    virtual int GetAPIVersion() = 0;\n\n    /**\n     * @brief   获取TrafficMonitor的版本。\n     * @return  const wchar_t*\n     */\n    virtual const wchar_t* GetVersion() = 0;\n\n    /** 主程序的所有监控信息 */\n    enum MonitorItem\n    {\n        MI_UP,                  /**< 上传速度 */\n        MI_DOWN,                /**< 下载速度 */\n        MI_CPU,                 /**< CPU利用率 */\n        MI_MEMORY,              /**< 内存利用率 */\n        MI_GPU_USAGE,           /**< 显卡利用率 */\n        MI_CPU_TEMP,            /**< CPU温度 */\n        MI_GPU_TEMP,            /**< 显卡温度 */\n        MI_HDD_TEMP,            /**< 硬盘温度 */\n        MI_MAIN_BOARD_TEMP,     /**< 主板温度 */\n        MI_HDD_USAGE,           /**< 硬盘利用率 */\n        MI_CPU_FREQ,            /**< CPU频率 */\n        MI_TODAY_UP_TRAFFIC,    /**< 今日上传流量 */\n        MI_TODAY_DOWN_TRAFFIC   /**< 今日下载流量 */\n    };\n\n    /**\n     * @brief   获取一个主程序的监控信息的数值\n     *          （ITMPlugin::OnMonitorInfo将被弃用）\n     * @param   item 要获取监控信息的项目\n     * @return  获取到监控信息\n     */\n    virtual double GetMonitorValue(MonitorItem item) = 0;\n\n    /**\n     * @brief   以字符串的形式获取一个主程序监控信息的数值\n     * @param   item 要获取监控信息的项目\n     * @param   is_main_window 是否为主窗口的数值\n     * @return  获取到监控信息\n     */\n    virtual const wchar_t* GetMonitorValueString(MonitorItem item, int is_main_window = false) = 0;\n\n    /**\n     * @brief   显示一个通知消息\n     * @param   strMsg 要显示的通知消息\n     */\n    virtual void ShowNotifyMessage(const wchar_t* strMsg) = 0;\n\n    /**\n     * @brief   获取当前语言id\n     * @return  当前主程序的语言id\n     */\n    virtual unsigned short GetLanguageId() const = 0;\n\n    /**\n     * @brief   获取配置文件目录\n     * @return  配置文件目录\n     */\n    virtual const wchar_t* GetPluginConfigDir() const = 0;\n\n    /** 主程序DPI类型 */\n    enum DPIType\n    {\n        DPI_MAIN_WND,   /**< 主窗口的DPI */\n        DPI_TASKBAR     /**< 任务栏窗口的DPI */\n    };\n\n    /**\n     * @brief   获取主程序DPI\n     * @return  主程序DPI\n     */\n    virtual int GetDPI(DPIType type) const = 0;\n\n    /**\n     * @brief   获取当前系统主题颜色\n     * @return  COLORREF格式的颜色值\n     */\n    virtual unsigned int GetThemeColor() const = 0;\n\n    /**\n     * @brief   获取当前语言的字符串资源\n     * @param   str_id 字符串资源id\n     * @param   str_section 字符串资源在ini文件中的段名称\n     * @return \n     */\n    virtual const wchar_t* GetStringRes(const wchar_t* key, const wchar_t* section) = 0;\n};\n\n\n/*\n* 注意：插件dll需导出以下函数\n* ITMPlugin* TMPluginGetInstance();\n*   函数返回一个ITMPlugin接口的对象的指针。\n*   此对象通常应该为一个全局或静态的对象，在程序运行结束前，它都不应该被释放。\n*/\n\n\n/*\n* 更新记录：\n* ITMPlugin\n* -------------------------------------------------------------------------\n* API version |                       更新内容\n* -------------------------------------------------------------------------\n*     1       | 第一个版本\n* -------------------------------------------------------------------------\n*     2       | 新增 ITMPlugin::GetTooltipInfo 函数\n* -------------------------------------------------------------------------\n*     3       | 新增 IPluginItem::GetItemWidthEx, IPluginItem::OnMouseEvent 函数\n* -------------------------------------------------------------------------\n*     4       | 新增 IPluginItem::OnKeboardEvent IPluginItem::OnItemInfo 函数\n* -------------------------------------------------------------------------\n*     5       | 新增 ITMPlugin::GetCommandName ITMPlugin::GetCommandIcon ITMPlugin::OnPluginCommand 函数\n* -------------------------------------------------------------------------\n*     6       | 新增 IPluginItem::GetResourceUsageGraphType IPluginItem::GetResourceUsageGraphValue 函数\n* -------------------------------------------------------------------------\n*     7       | 新增 ITMPlugin::OnInitialize 函数\n* -------------------------------------------------------------------------\n*/\n"
  },
  {
    "path": "version.info",
    "content": "<version>1.85.1</version>\n<link>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x86_Lite.zip</link>\n<link_x64>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x64_Lite.zip</link_x64>\n<contents>Windows11ʹõĳɾɰʱСʾࡱѡõ\\nûκͼʱڵλòȷ\\nеӦáʱݿȲЧ\\nWindows11ƶĶԻУӱҲСصѡ\\nδӲеCPUʱCPUʹʻȡʽĳʹܼ󣬻ĻػCPUʹʱ\\nл\\nʱõùСʱʾٿܻʵ\\nڴ泬100Gʱʾʣڴʾȫ</contents>"
  },
  {
    "path": "version_utf8.info",
    "content": "﻿<root>\n\t<version>1.85.1</version>\n\t<GitHub>\n\t\t<link>https://github.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x86.zip</link>\n\t\t<link_x64>https://github.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x64.zip</link_x64>\n\t\t<link_arm64ec>https://github.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_arm64ec.zip</link_arm64ec>\n\t\t<link_without_temperature>https://github.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x86_Lite.zip</link_without_temperature>\n\t\t<link_without_temperature_x64>https://github.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x64_Lite.zip</link_without_temperature_x64>\n\t\t<link_without_temperature_arm64ec>https://github.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_arm64ec_Lite.zip</link_without_temperature_arm64ec>\n\t</GitHub>\n\t<Gitee>\n\t\t<link>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x86.zip</link>\n\t\t<link_x64>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x64.zip</link_x64>\n\t\t<link_arm64ec>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_arm64ec.zip</link_arm64ec>\n\t\t<link_without_temperature>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x86_Lite.zip</link_without_temperature>\n\t\t<link_without_temperature_x64>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_x64_Lite.zip</link_without_temperature_x64>\n\t\t<link_without_temperature_arm64ec>https://gitee.com/zhongyang219/TrafficMonitor/releases/download/V1.85.1/TrafficMonitor_V1.85.1_arm64ec_Lite.zip</link_without_temperature_arm64ec>\n\t</Gitee>\n\t<update_contents>\n\t\t<contents_zh_cn>修正Windows11下使用第三方软件改成旧版任务栏时，任务栏窗口设置中“任务栏窗口显示在任务栏左侧”选项不可用的问题\\n修正当任务栏上没有任何图标时任务栏窗口的位置不正确的问题\\n修正任务栏窗口设置中点击“应用”时网速数据宽度不生效的问题\\n任务栏设置中Windows11相关设置移动到单独的对话框中，增加避免与右侧小组件重叠的选项\\n修正未启用硬件监控中的CPU监控时，CPU使用率获取方式改成使用性能计数器后，会改回基于CPU使用时间的问题\\n修正鸣谢界面有乱码的问题\\n修正当监控时间间隔设置得过小时，显示的网速可能会大于实际网速问题\\n修正当内存超过100G时显示任务栏剩余内存显示不全的问题</contents_zh_cn>\n\t\t<contents_en>Fixed the problem that when using third-party software to change to the classical taskbar in Windows 11, the option \"Taskbar window appears to the left of the taskbar\" in the Taskbar Window Settings is not available.\\nFixed the problem that the position of the taskbar windows is not correct when there is no any icon on the taskbar.\\nFixed the problem that the \"Network speed data width\" does not take effect when clicking \"Apply\" in the Taskbar Window Settings.\\nWindows 11 related settings in Taskbar Windows Settings moved to the new dialog. Add an option to avoid overlapping with right Widgets.\\nFixed the problem that when \"CPU\" in Hardware Monitoring is not enabled, the \"CPU usage acquisition method\" will be changed back to the \"Based on CPU time\" when set it to \"Use the performance counter\".\\nFixed the problem of messy charactors in the acknowledgement dialog.\\nFixed the problem that the displayed net speed may be larger than the actual net speed when the \"Monitoring intervals\" is set too small.\\nFixed the problem that the \"Memory available\" in the taskbar window cannot be fully displayed when the memory exceeds 100G.</contents_en>\n\t\t<contents_zh_tw>修正Windows11下使用第三方軟體改成舊版工作列時，工作列視窗設定中“工作列視窗顯示在工作列左側”選項不可用的問題\\n修正當工作列上沒有任何圖示時工作列視窗的位置不正確的問題\\n修正工作列視窗設定中點選“應用”時網速資料寬度不生效的問題\\n工作列設定中Windows11相關設定移動到單獨的對話方塊中，增加避免與右側小元件重疊的選項\\n修正未啟用硬體監控中的CPU監控時，CPU使用率獲取方式改成使用效能計數器後，會改回基於CPU使用時間的問題\\n修正鳴謝介面有亂碼的問題\\n修正當監控時間間隔設定得過小時，顯示的網速可能會大於實際網速問題\\n修正當記憶體超過100G時顯示工作列剩餘記憶體顯示不全的問題</contents_zh_tw>\n\t</update_contents>\n</root>\n"
  },
  {
    "path": "皮肤制作教程.md",
    "content": "**皮肤制作教程已经移至Wiki页面：**\n\n[皮肤制作教程 · zhongyang219/TrafficMonitor Wiki (github.com)](https://github.com/zhongyang219/TrafficMonitor/wiki/皮肤制作教程)\n\n"
  }
]