├── .gitignore ├── HelpFileProject ├── HelpFileProject.sln └── HelpFileProject │ ├── Content │ ├── VersionHistory │ │ ├── VersionHistory.aml │ │ └── v1.0.0.0.aml │ └── Welcome.aml │ ├── ContentLayout.content │ ├── HelpFileProject.shfbproj │ └── icons │ └── Help.png ├── LICENSE ├── Medical-Nurse-Male-Light-icon.png ├── MessageBoxEx.sln ├── MessageBoxEx ├── Classes │ ├── MessageBoxEx.cs │ ├── MessageBoxExButton.cs │ ├── MessageBoxExConfig.cs │ └── ResourceTextConfig.cs ├── Enums │ ├── MessageBoxExIcons.cs │ ├── MessageBoxExResult.cs │ ├── MessageBoxExType.cs │ └── OptionTextMode.cs ├── Forms │ ├── DropDownPlacement.cs │ ├── frmMsgBox.Designer.cs │ ├── frmMsgBox.cs │ └── frmMsgBox.resx ├── MessageBoxEx.csproj └── Resources │ ├── AppResources.Designer.cs │ ├── AppResources.fr-FR.resx │ ├── AppResources.it-IT.resx │ └── AppResources.resx ├── MsgExHelper ├── MsgExHelper.csproj └── Program.cs ├── README.md ├── Screenshots ├── screenshot1.png ├── screenshot2.png ├── screenshot3.png ├── screenshot4.png ├── screenshot5.png ├── screenshot6.png ├── screenshot7.png ├── screenshot8.png └── screenshot9.png └── TestApp ├── Form1.Designer.cs ├── Form1.cs ├── Form1.resx ├── Program.cs ├── Resources ├── AppResources.Designer.cs ├── AppResources.fr.resx ├── AppResources.resx ├── Medical-Nurse-Male-Light-icon.png └── icons8-color-50.png └── TestApp.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /HelpFileProject/HelpFileProject.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30406.217 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{7CF6DF6D-3B04-46F8-A40B-537D21BCA0B4}") = "HelpFileProject", "HelpFileProject\HelpFileProject.shfbproj", "{41C6EA19-254D-43C9-81F8-161E7944895E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {41C6EA19-254D-43C9-81F8-161E7944895E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {41C6EA19-254D-43C9-81F8-161E7944895E}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {41C6EA19-254D-43C9-81F8-161E7944895E}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {41C6EA19-254D-43C9-81F8-161E7944895E}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B3DF6991-3B44-4F11-BDF2-9107FBEAF76E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /HelpFileProject/HelpFileProject/Content/VersionHistory/VersionHistory.aml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | The topics in this section describe the various changes made to the [TODO: Project Title] over the 6 | life of the project. 7 | 8 | 9 |
10 | Version History 11 | 12 | Select a version below to see a description of its changes. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | [TODO: Add links to each specific version page] 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 | -------------------------------------------------------------------------------- /HelpFileProject/HelpFileProject/Content/VersionHistory/v1.0.0.0.aml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Version [TODO: Version] was released on [TODO: Date]. 6 | 7 | 8 | 9 |
10 | Changes in This Release 11 | 12 | 13 | 14 | 15 | [TODO: Add change items here] 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /HelpFileProject/HelpFileProject/Content/Welcome.aml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DataTools.MessageBoxEx is a highly customizable replacement for the system MessageBox class for both WPF and WinForms applications. 6 | It is intended to look and behave as closely as possible to the native MessageBox. 7 | 8 | 9 |
10 | Features 11 | 12 | Some of the features of this class are: 13 | 14 | 15 | 16 | ContentLayout.content - Use the content layout file to manage the 17 | conceptual content in the project and define its layout in the table of contents. 18 | 19 | 20 | 21 | The .\media folder - Place images in this folder that you will reference 22 | from conceptual content using medialLink or mediaLinkInline 23 | elements. If you will not have any images in the file, you may remove this folder. 24 | 25 | 26 | 27 | The .\icons folder - This contains a default logo for the help file. You 28 | may replace it or remove it and the folder if not wanted. If removed or if you change the file name, update 29 | the Transform Args project properties page by removing or changing the filename in the 30 | logoFile transform argument. Note that unlike images referenced from conceptual topics, 31 | the logo file should have its BuildAction property set to Content. 32 | 33 | 34 | 35 | The .\Content folder - Use this to store your conceptual topics. You may 36 | name the files and organize them however you like. One suggestion is to lay the files out on disk as you have 37 | them in the content layout file as shown in this project but the choice is yours. Files can be added via the 38 | Solution Explorer or from within the content layout file editor. Files must appear in the content layout file 39 | in order to be compiled into the help file. 40 | 41 | 42 | 43 | See the Conceptual Content topics in the Sandcastle Help File Builder's 44 | help file for more information. See the Sandcastle MAML Guide for details on Microsoft 45 | Assistance Markup Language (MAML) which is used to create these topics. 46 | 47 |
48 | 49 | 50 | 51 | 52 |
53 |
54 | -------------------------------------------------------------------------------- /HelpFileProject/HelpFileProject/ContentLayout.content: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /HelpFileProject/HelpFileProject/HelpFileProject.shfbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 6 | Debug 7 | AnyCPU 8 | 2.0 9 | 41c6ea19-254d-43c9-81f8-161e7944895e 10 | 2017.9.26.0 11 | 12 | HelpFileProject 13 | HelpFileProject 14 | HelpFileProject 15 | 16 | .NET Framework 4.7.2 17 | ..\..\..\MessageBoxEx.wiki\ 18 | HelpFileProject 19 | en-US 20 | 21 | 22 | 23 | 24 | 25 | Markdown 26 | C#, Visual Basic 27 | Markdown 28 | True 29 | True 30 | False 31 | False 32 | OnlyWarningsAndErrors 33 | 100 34 | DataTools.MessageBoxEx User Guide 35 | 1.0.0.0 36 | MemberName 37 | BelowNamespaces 38 | False 39 | False 40 | 2 41 | False 42 | Blank 43 | False 44 | 45 | 46 | 47 | 48 | Msdn 49 | True 50 | False 51 | Msdn 52 | False 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | DataTools.MessageBoxEx namespace. 61 | DataTools.MessageBoxEx is a highly customizable replacement for the system MessageBox class for both WPF and WinForms applications. 62 | 63 | It is intended to look and behave as closely as possible to the native MessageBox. 64 | InheritedMembers, InheritedFrameworkMembers, Protected, ProtectedInternalAsProtected, NonBrowsable 65 | Summary, Parameter, AutoDocumentCtors, TypeParameter, AutoDocumentDispose 66 | 67 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 111 | OnBuildSuccess 112 | 113 | -------------------------------------------------------------------------------- /HelpFileProject/HelpFileProject/icons/Help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/HelpFileProject/HelpFileProject/icons/Help.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Nathaniel N Moschkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Medical-Nurse-Male-Light-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Medical-Nurse-Male-Light-icon.png -------------------------------------------------------------------------------- /MessageBoxEx.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33205.214 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MessageBoxEx", "MessageBoxEx\MessageBoxEx.csproj", "{37A2537D-70C6-4A26-B6C6-CBC6A2D6CA75}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp", "TestApp\TestApp.csproj", "{0EF332B5-93BB-4DED-9174-4F3559B845F5}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MsgExHelper", "MsgExHelper\MsgExHelper.csproj", "{D57A0C3C-DC54-4894-B870-D7AE8CD674DC}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | NuGet|Any CPU = NuGet|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {37A2537D-70C6-4A26-B6C6-CBC6A2D6CA75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {37A2537D-70C6-4A26-B6C6-CBC6A2D6CA75}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {37A2537D-70C6-4A26-B6C6-CBC6A2D6CA75}.NuGet|Any CPU.ActiveCfg = NuGet|Any CPU 22 | {37A2537D-70C6-4A26-B6C6-CBC6A2D6CA75}.NuGet|Any CPU.Build.0 = NuGet|Any CPU 23 | {37A2537D-70C6-4A26-B6C6-CBC6A2D6CA75}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {37A2537D-70C6-4A26-B6C6-CBC6A2D6CA75}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {0EF332B5-93BB-4DED-9174-4F3559B845F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {0EF332B5-93BB-4DED-9174-4F3559B845F5}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {0EF332B5-93BB-4DED-9174-4F3559B845F5}.NuGet|Any CPU.ActiveCfg = NuGet|Any CPU 28 | {0EF332B5-93BB-4DED-9174-4F3559B845F5}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {0EF332B5-93BB-4DED-9174-4F3559B845F5}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {D57A0C3C-DC54-4894-B870-D7AE8CD674DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {D57A0C3C-DC54-4894-B870-D7AE8CD674DC}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {D57A0C3C-DC54-4894-B870-D7AE8CD674DC}.NuGet|Any CPU.ActiveCfg = NuGet|Any CPU 33 | {D57A0C3C-DC54-4894-B870-D7AE8CD674DC}.NuGet|Any CPU.Build.0 = NuGet|Any CPU 34 | {D57A0C3C-DC54-4894-B870-D7AE8CD674DC}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {D57A0C3C-DC54-4894-B870-D7AE8CD674DC}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {DCABCAD4-9C33-4022-BAE2-BA98D9B4AA1A} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /MessageBoxEx/Classes/MessageBoxEx.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Media; 9 | using System.Runtime.InteropServices; 10 | using System.Text; 11 | 12 | namespace DataTools.MessageBoxEx 13 | { 14 | [StructLayout(LayoutKind.Sequential, Pack = 0)] 15 | internal unsafe struct DxStruct 16 | { 17 | public MessageBoxExResult result; 18 | public int CustomResult; 19 | public bool OptionResult; 20 | public int jDataLen; 21 | public char* jData; 22 | public bool vs; 23 | } 24 | 25 | /// 26 | /// Enhanced Windows Desktop MessageBox replacement 27 | /// 28 | public static class MessageBoxEx 29 | { 30 | private static frmMsgBox form = new frmMsgBox(); 31 | 32 | static MessageBoxEx() 33 | { 34 | ResourceTextConfig = new ResourceTextConfig(); 35 | } 36 | 37 | /// 38 | /// Gets or sets the current localized text resources configuration. 39 | /// 40 | public static ResourceTextConfig ResourceTextConfig { get; set; } 41 | 42 | private static List MakeButtons(MessageBoxExType b) 43 | { 44 | if (ResourceTextConfig == null) 45 | { 46 | ResourceTextConfig = new ResourceTextConfig(); 47 | } 48 | 49 | var rtc = ResourceTextConfig; 50 | var btnOut = new List(); 51 | 52 | switch (b) 53 | { 54 | case MessageBoxExType.AbortRetryIgnore: 55 | 56 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Abort), MessageBoxExResult.Abort)); 57 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Retry), MessageBoxExResult.Retry, true)); 58 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Ignore), MessageBoxExResult.Ignore)); 59 | 60 | break; 61 | 62 | case MessageBoxExType.OK: 63 | 64 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.OK), MessageBoxExResult.OK, true)); 65 | break; 66 | 67 | case MessageBoxExType.OKCancel: 68 | 69 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.OK), MessageBoxExResult.OK, true)); 70 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Cancel), MessageBoxExResult.Cancel, false)); 71 | 72 | break; 73 | 74 | case MessageBoxExType.YesNo: 75 | 76 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Yes), MessageBoxExResult.Yes, true)); 77 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.No), MessageBoxExResult.No, false)); 78 | 79 | break; 80 | 81 | case MessageBoxExType.YesNoCancel: 82 | 83 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Yes), MessageBoxExResult.Yes, true)); 84 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.No), MessageBoxExResult.No, false)); 85 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Cancel), MessageBoxExResult.Cancel, false)); 86 | 87 | break; 88 | 89 | case MessageBoxExType.YesNoAll: 90 | 91 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Yes), MessageBoxExResult.Yes, true)); 92 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.YesToAll), MessageBoxExResult.YesToAll, false)); 93 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.No), MessageBoxExResult.No, false)); 94 | 95 | break; 96 | 97 | case MessageBoxExType.YesNoAllCancel: 98 | 99 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Yes), MessageBoxExResult.Yes, true)); 100 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.YesToAll), MessageBoxExResult.YesToAll, false)); 101 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.No), MessageBoxExResult.No, false)); 102 | btnOut.Add(new MessageBoxExButton(rtc.GetText(MessageBoxExResult.Cancel), MessageBoxExResult.Cancel, false)); 103 | 104 | break; 105 | } 106 | 107 | return btnOut; 108 | } 109 | 110 | /// 111 | /// Start the message box out-of-process to change visual styles. 112 | /// 113 | /// The object to use to configure the dialog box. 114 | /// Whether to enable Visual Styles by calling . 115 | /// A value 116 | public static MessageBoxExResult ShowInNewProcess(MessageBoxExConfig config, bool visualStyles = true) 117 | { 118 | int i; 119 | MessageBoxExResult result; 120 | bool wasStd; 121 | 122 | List stashed = new List(); 123 | 124 | if (config.CustomButtons?.Count > 0) 125 | { 126 | wasStd = false; 127 | i = 0; 128 | 129 | foreach (var btn in config.CustomButtons) 130 | { 131 | if (btn.CustomResult != null) 132 | { 133 | stashed.Add(btn.CustomResult); 134 | btn.CustomResult = i++; 135 | } 136 | 137 | if (btn.DropDownMenuButtons?.Count > 0) 138 | { 139 | foreach (var btn2 in btn.DropDownMenuButtons) 140 | { 141 | if (btn2.CustomResult != null) 142 | { 143 | stashed.Add(btn2.CustomResult); 144 | btn2.CustomResult = i++; 145 | } 146 | } 147 | } 148 | } 149 | } 150 | else 151 | { 152 | wasStd = true; 153 | config.CustomButtons = MakeButtons(config.MessageBoxType); 154 | } 155 | 156 | try 157 | { 158 | string json; 159 | string json2; 160 | 161 | json = JsonConvert.SerializeObject(config); 162 | 163 | using (Process proc = new Process()) 164 | { 165 | proc.StartInfo.FileName = "MsgExHelper.exe"; 166 | proc.StartInfo.UseShellExecute = false; 167 | proc.StartInfo.RedirectStandardOutput = true; 168 | proc.StartInfo.RedirectStandardInput = true; 169 | 170 | proc.Start(); 171 | 172 | proc.StandardInput.Write(json + (char)26 + (visualStyles ? '1' : '0')); 173 | 174 | json2 = proc.StandardOutput.ReadToEnd(); 175 | proc.WaitForExit(); 176 | 177 | result = (MessageBoxExResult)proc.ExitCode; 178 | proc.Dispose(); 179 | } 180 | 181 | var newConfig = JsonConvert.DeserializeObject(json2); 182 | 183 | config.CustomResult = stashed.Count > 0 ? stashed[int.Parse(newConfig.CustomResult.ToString())] : null; 184 | config.OptionResult = newConfig.OptionResult; 185 | config.Dismissed = newConfig.Dismissed; 186 | 187 | if (wasStd) config.CustomButtons.Clear(); 188 | 189 | stashed.Clear(); 190 | 191 | GC.Collect(0); 192 | return result; 193 | } 194 | catch 195 | { 196 | return MessageBoxExResult.None; 197 | } 198 | } 199 | 200 | /// 201 | /// Shows a message box according to a object. 202 | /// Custom return values will be found in the object after the dialog box closes. 203 | /// This method allows more flexibility in how your dialog box behaves. 204 | /// 205 | /// The object to use to configure the dialog box. 206 | /// A value 207 | public static MessageBoxExResult Show(MessageBoxExConfig config) 208 | { 209 | form.SetMessage(config.Message /*, config.HtmlMessage */); 210 | form.Text = config.Title; 211 | 212 | form.TopMost = config.AlwaysOnTop; 213 | 214 | if (config.CustomButtons != null && config.CustomButtons.Count > 0) 215 | { 216 | form.SetButtons(config.CustomButtons); 217 | } 218 | else 219 | { 220 | form.SetButtons(MakeButtons(config.MessageBoxType)); 221 | } 222 | 223 | if (config.CustomIcon != null) 224 | { 225 | form.SetIcon(config.CustomIcon); 226 | } 227 | else 228 | { 229 | form.SetIcon(GetIcon(config.Icon)); 230 | } 231 | 232 | if (string.IsNullOrEmpty(config.OptionText)) 233 | { 234 | form.SetUrl(false); 235 | form.SetOption(false); 236 | } 237 | else 238 | { 239 | if (config.OptionMode == OptionTextMode.Checkbox) 240 | { 241 | form.SetOption(true, config.OptionText); 242 | } 243 | else 244 | { 245 | form.SetUrl(true, config.OptionText, config.OptionTextUrl, config.UrlClickDismiss); 246 | } 247 | } 248 | 249 | form.OptionResult = config.OptionResult; 250 | form.FormatBox(); 251 | 252 | if (!config.MuteSound) 253 | PlaySound(config.Icon); 254 | 255 | form.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 256 | form.ShowDialog(); 257 | 258 | config.Dismissed = form.Dismissed; 259 | config.CustomResult = form.CustomResult; 260 | config.OptionResult = form.OptionResult; 261 | 262 | return form.Result; 263 | } 264 | 265 | /// 266 | /// Creates a message box with custom buttons, custom icon, and an option toggle. 267 | /// 268 | /// Text to display in the dialog box 269 | /// Title of the dialog box 270 | /// Text of the option checkbox 271 | /// An of objects 272 | /// The custom icon for the box. 273 | /// The result of the button that was pressed 274 | /// The result of the option toggle 275 | /// A value 276 | public static MessageBoxExResult Show(string message, string title, string optionText, IEnumerable buttons, Bitmap icon, out object customResult, out bool optionResult) 277 | { 278 | var cfg = new MessageBoxExConfig() 279 | { 280 | Message = message, 281 | Title = title, 282 | OptionText = optionText, 283 | OptionMode = OptionTextMode.Checkbox, 284 | Icon = MessageBoxExIcons.Custom, 285 | CustomIcon = icon, 286 | MessageBoxType = MessageBoxExType.Custom 287 | }; 288 | 289 | foreach (var button in buttons) 290 | { 291 | cfg.CustomButtons.Add(button); 292 | } 293 | 294 | var ret = Show(cfg); 295 | 296 | customResult = cfg.CustomResult; 297 | optionResult = cfg.OptionResult; 298 | 299 | return ret; 300 | } 301 | 302 | /// 303 | /// Creates a message box with custom buttons, custom icon, and an option toggle. 304 | /// 305 | /// Text to display in the dialog box 306 | /// Title of the dialog box 307 | /// Text of the option checkbox 308 | /// An of objects 309 | /// A standard value 310 | /// The result of the button that was pressed 311 | /// The result of the option toggle 312 | /// A value 313 | public static MessageBoxExResult Show(string message, string title, string optionText, IEnumerable buttons, MessageBoxExIcons icon, out object customResult, out bool optionResult) 314 | { 315 | var cfg = new MessageBoxExConfig() 316 | { 317 | Message = message, 318 | Title = title, 319 | OptionText = optionText, 320 | OptionMode = OptionTextMode.Checkbox, 321 | Icon = icon, 322 | MessageBoxType = MessageBoxExType.Custom 323 | }; 324 | 325 | foreach (var button in buttons) 326 | { 327 | cfg.CustomButtons.Add(button); 328 | } 329 | 330 | var ret = Show(cfg); 331 | 332 | customResult = cfg.CustomResult; 333 | optionResult = cfg.OptionResult; 334 | 335 | return ret; 336 | } 337 | 338 | /// 339 | /// Shows a message box with a message, title, custom buttons, and a standard icon. 340 | /// 341 | /// Text to display in the dialog box 342 | /// Title of the dialog box 343 | /// An of objects 344 | /// A standard value 345 | /// The result of the button that was pressed 346 | /// A value 347 | public static MessageBoxExResult Show(string message, string title, IEnumerable buttons, MessageBoxExIcons icon, out object customResult) 348 | { 349 | var cfg = new MessageBoxExConfig() 350 | { 351 | Message = message, 352 | Title = title, 353 | Icon = icon, 354 | MessageBoxType = MessageBoxExType.Custom 355 | }; 356 | 357 | foreach (var button in buttons) 358 | { 359 | cfg.CustomButtons.Add(button); 360 | } 361 | 362 | var ret = Show(cfg); 363 | customResult = cfg.CustomResult; 364 | 365 | return ret; 366 | } 367 | 368 | /// 369 | /// Shows a message box with a message, title, standard buttons, and a standard icon. 370 | /// 371 | /// Text to display in the dialog box 372 | /// Title of the dialog box 373 | /// A standard value 374 | /// A standard value. 375 | /// A value 376 | 377 | public static MessageBoxExResult Show(string message, string title, MessageBoxExType type, MessageBoxExIcons icon) 378 | { 379 | var cfg = new MessageBoxExConfig() 380 | { 381 | Message = message, 382 | Title = title, 383 | Icon = icon, 384 | MessageBoxType = type 385 | }; 386 | 387 | return Show(cfg); 388 | } 389 | 390 | /// 391 | /// Shows a message box with a message, title, standard buttons, a standard icon, and an option toggle. 392 | /// 393 | /// Text to display in the dialog box 394 | /// Title of the dialog box 395 | /// Option toggle button message 396 | /// A standard value 397 | /// A standard value 398 | /// The result of the option toggle button 399 | /// A value 400 | public static MessageBoxExResult Show(string message, string title, string optionText, MessageBoxExType type, MessageBoxExIcons icon, out bool optionResult) 401 | { 402 | var cfg = new MessageBoxExConfig() 403 | { 404 | Message = message, 405 | Title = title, 406 | OptionText = optionText, 407 | OptionMode = OptionTextMode.Checkbox, 408 | Icon = icon, 409 | MessageBoxType = type 410 | }; 411 | 412 | var ret = Show(cfg); 413 | 414 | optionResult = cfg.OptionResult; 415 | return ret; 416 | } 417 | 418 | /// 419 | /// Show a standard box with a message, a title. 420 | /// 421 | /// Text to display in the box 422 | /// The title of the dialog box 423 | /// A standard value 424 | /// A value 425 | public static MessageBoxExResult Show(string message, string title, MessageBoxExType type) 426 | { 427 | var cfg = new MessageBoxExConfig() 428 | { 429 | Message = message, 430 | Title = title, 431 | MessageBoxType = type 432 | }; 433 | 434 | return Show(cfg); 435 | } 436 | 437 | /// 438 | /// Show a box with a message and OK button 439 | /// 440 | /// Text to display in the box 441 | /// A value 442 | public static MessageBoxExResult Show(string message) 443 | { 444 | var cfg = new MessageBoxExConfig() 445 | { 446 | Message = message, 447 | MessageBoxType = MessageBoxExType.OK 448 | }; 449 | 450 | return Show(cfg); 451 | } 452 | 453 | private static void PlaySound(MessageBoxExIcons icon) 454 | { 455 | switch (icon) 456 | { 457 | case MessageBoxExIcons.Asterisk: 458 | 459 | System.Media.SystemSounds.Asterisk.Play(); 460 | return; 461 | 462 | case MessageBoxExIcons.Error: 463 | 464 | System.Media.SystemSounds.Beep.Play(); 465 | return; 466 | 467 | case MessageBoxExIcons.Exclamation: 468 | System.Media.SystemSounds.Exclamation.Play(); 469 | return; 470 | 471 | case MessageBoxExIcons.Question: 472 | SystemSounds.Question.Play(); 473 | return; 474 | 475 | case MessageBoxExIcons.Shield: 476 | SystemSounds.Exclamation.Play(); 477 | return; 478 | 479 | case MessageBoxExIcons.Warning: 480 | System.Media.SystemSounds.Exclamation.Play(); 481 | return; 482 | } 483 | } 484 | 485 | private static System.Drawing.Bitmap GetIcon(MessageBoxExIcons icon) 486 | { 487 | switch (icon) 488 | { 489 | case MessageBoxExIcons.Asterisk: 490 | 491 | return SystemIcons.Asterisk.ToBitmap(); 492 | 493 | case MessageBoxExIcons.Error: 494 | 495 | return SystemIcons.Error.ToBitmap(); 496 | 497 | case MessageBoxExIcons.Exclamation: 498 | 499 | return SystemIcons.Exclamation.ToBitmap(); 500 | 501 | case MessageBoxExIcons.Hand: 502 | 503 | return SystemIcons.Hand.ToBitmap(); 504 | 505 | case MessageBoxExIcons.Information: 506 | 507 | return SystemIcons.Information.ToBitmap(); 508 | 509 | case MessageBoxExIcons.Question: 510 | 511 | return SystemIcons.Question.ToBitmap(); 512 | 513 | case MessageBoxExIcons.Shield: 514 | 515 | return SystemIcons.Shield.ToBitmap(); 516 | 517 | case MessageBoxExIcons.Warning: 518 | 519 | return SystemIcons.Warning.ToBitmap(); 520 | } 521 | 522 | return null; 523 | } 524 | } 525 | } -------------------------------------------------------------------------------- /MessageBoxEx/Classes/MessageBoxExButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Drawing; 7 | using System.Windows.Forms; 8 | using System.IO; 9 | using Newtonsoft.Json; 10 | using System.Drawing.Imaging; 11 | 12 | namespace DataTools.MessageBoxEx 13 | { 14 | /// 15 | /// Class that represents a button on the dialog box. 16 | /// 17 | public class MessageBoxExButton 18 | { 19 | 20 | /// 21 | /// Collection of buttons for a drop-down menu. 22 | /// 23 | public List DropDownMenuButtons { get; set; } = new List(); 24 | 25 | /// 26 | /// Specifies the custom icon to display. 27 | /// 28 | [JsonIgnore] 29 | public Bitmap Image { get; set; } = null; 30 | 31 | 32 | [JsonProperty("EncodedIcon")] 33 | internal string EncodedIcon 34 | { 35 | get 36 | { 37 | if (Image == null) return null; 38 | MemoryStream m = new MemoryStream(); 39 | 40 | Image.Save(m, ImageFormat.Png); 41 | var conv = Convert.ToBase64String(m.ToArray()); 42 | 43 | m.Dispose(); 44 | 45 | return conv; 46 | } 47 | set 48 | { 49 | if (value == null) 50 | { 51 | Image = null; 52 | return; 53 | } 54 | 55 | MemoryStream m = new MemoryStream(Convert.FromBase64String(value)); 56 | 57 | Image = (Bitmap)System.Drawing.Image.FromStream(m); 58 | m.Dispose(); 59 | } 60 | } 61 | 62 | /// 63 | /// Button text 64 | /// 65 | public string Message { get; set; } 66 | 67 | /// 68 | /// MessageBox result 69 | /// 70 | public MessageBoxExResult Result { get; set; } = MessageBoxExResult.OK; 71 | 72 | /// 73 | /// Custom result 74 | /// 75 | public object CustomResult { get; set; } = null; 76 | 77 | /// 78 | /// Marks this button as default. 79 | /// Note, if there is more than one default button set, the first one wins. 80 | /// 81 | public bool IsDefault { get; set; } 82 | 83 | /// 84 | /// Sets the placement for the drop-down menu. 85 | /// 86 | public DropDownPlacement DropDownPlacement { get; set; } = DropDownPlacement.None; 87 | 88 | internal PictureBox Container { get; set; } 89 | 90 | internal ContextMenuStrip ContextMenu { get; set; } 91 | 92 | internal Control DropDown { get; set; } 93 | 94 | internal Control Button { get; set; } 95 | 96 | /// 97 | /// Create a new empty button. 98 | /// 99 | public MessageBoxExButton() 100 | { 101 | 102 | } 103 | 104 | /// 105 | /// Create a new standard button. 106 | /// 107 | /// The button text 108 | /// The button result 109 | /// Is the default button 110 | /// 111 | public MessageBoxExButton(string caption, MessageBoxExResult result, bool isDefault = false) 112 | { 113 | Message = caption; 114 | Result = result; 115 | IsDefault = isDefault; 116 | CustomResult = null; 117 | } 118 | 119 | /// 120 | /// Create a new custom button with a custom result value. 121 | /// 122 | /// The button text 123 | /// The custom result this button will return 124 | /// Is the default button 125 | public MessageBoxExButton(string caption, object customResult, bool isDefault = false) 126 | { 127 | Message = caption; 128 | CustomResult = customResult; 129 | Result = MessageBoxExResult.Custom; 130 | IsDefault = isDefault; 131 | } 132 | 133 | /// 134 | /// Create a new standard button with an image. 135 | /// 136 | /// The button text 137 | /// The button result 138 | /// The button image 139 | /// Is the default button 140 | public MessageBoxExButton(string caption, MessageBoxExResult result, Bitmap image, bool isDefault = false) 141 | { 142 | Message = caption; 143 | Result = result; 144 | IsDefault = isDefault; 145 | Image = image; 146 | 147 | } 148 | 149 | /// 150 | /// Create a new custom button with an image. 151 | /// 152 | /// The button text 153 | /// The custom result this button will return 154 | /// The button image 155 | /// Is the default button 156 | public MessageBoxExButton(string caption, object customResult, Bitmap image, bool isDefault = false) 157 | { 158 | Message = caption; 159 | CustomResult = customResult; 160 | Result = MessageBoxExResult.Custom; 161 | IsDefault = isDefault; 162 | Image = image; 163 | } 164 | 165 | 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /MessageBoxEx/Classes/MessageBoxExConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Drawing; 7 | using Newtonsoft.Json; 8 | using System.IO; 9 | using System.Drawing.Imaging; 10 | 11 | namespace DataTools.MessageBoxEx 12 | { 13 | /// 14 | /// Configuration object to be passed to MessageBoxEx.Show() containing 15 | /// parameters and customization options for the dialog box. 16 | /// 17 | public class MessageBoxExConfig 18 | { 19 | 20 | /// 21 | /// Sets a value indicating that the dialog box shall be the top-most window on the desktop 22 | /// until it is dismissed. 23 | /// 24 | public bool AlwaysOnTop { get; set; } = true; 25 | 26 | /// 27 | /// List of custom buttons. 28 | /// Default buttons arae only displayed if this list is empty. 29 | /// 30 | public List CustomButtons { get; set; } = new List(); 31 | 32 | /// 33 | /// Specifies the message box type. 34 | /// 35 | public MessageBoxExType MessageBoxType { get; set; } = MessageBoxExType.OK; 36 | 37 | /// 38 | /// Specifies whether to mute alert sounds. 39 | /// 40 | public bool MuteSound { get; set; } = false; 41 | 42 | /// 43 | /// Play a custom sound when the dialog box opens, regardless of the default sound for the selected icon. 44 | /// 45 | public MessageBoxExIcons SoundIcon { get; set; } = MessageBoxExIcons.None; 46 | 47 | /// 48 | /// Specifies the icon displayed to the left of the message, in the message box. 49 | /// 50 | public MessageBoxExIcons Icon { get; set; } = MessageBoxExIcons.None; 51 | 52 | ///// 53 | ///// Specifies that the content of the message is HTML and will be rendered in a web browser. 54 | ///// 55 | ////public bool HtmlMessage { get; set; } = false; 56 | 57 | /// 58 | /// Specifies the custom icon to display. 59 | /// 60 | [JsonIgnore] 61 | public Bitmap CustomIcon { get; set; } = null; 62 | 63 | [JsonProperty("EncodedIcon")] 64 | internal string EncodedIcon 65 | { 66 | get 67 | { 68 | if (CustomIcon == null) return null; 69 | MemoryStream m = new MemoryStream(); 70 | 71 | CustomIcon.Save(m, ImageFormat.Png); 72 | var conv = Convert.ToBase64String(m.ToArray()); 73 | 74 | m.Dispose(); 75 | return conv; 76 | } 77 | set 78 | { 79 | if (value == null) 80 | { 81 | CustomIcon = null; 82 | return; 83 | } 84 | 85 | MemoryStream m = new MemoryStream(Convert.FromBase64String(value)); 86 | 87 | CustomIcon = (Bitmap)Image.FromStream(m); 88 | m.Dispose(); 89 | } 90 | } 91 | 92 | /// 93 | /// Specifies the title of the dialog box. 94 | /// 95 | public string Title { get; set; } = null; 96 | 97 | 98 | /// 99 | /// Specifies the message to be displayed. 100 | /// 101 | public string Message { get; set; } = null; 102 | 103 | /// 104 | /// Toggle option text. 105 | /// If this text is not null, either a URL or a check box will be displayed. 106 | /// The state of the toggle when the dialog closes can be found in the OptionResult property. 107 | /// In URL mode this can be any file or process that you have permission to start. 108 | /// 109 | public string OptionText { get; set; } = null; 110 | 111 | /// 112 | /// The mode of the option text. Default is checkbox. 113 | /// In Url mode the OptionText can be any file or process that you have permission to start. 114 | /// 115 | public OptionTextMode OptionMode { get; set; } = OptionTextMode.Checkbox; 116 | 117 | /// 118 | /// Specify whether or not clicking the Url dismisses the dialog box. 119 | /// The default result will be returned. 120 | /// 121 | public bool UrlClickDismiss { get; set; } = false; 122 | 123 | /// 124 | /// The URL linked to the option text. 125 | /// 126 | public string OptionTextUrl { get; set; } = null; 127 | 128 | /// 129 | /// The custom result of the button that was pressed. 130 | /// 131 | public object CustomResult { get; set; } = null; 132 | 133 | 134 | /// 135 | /// The state of the checkbox when the dialog box was closed. 136 | /// 137 | public bool OptionResult { get; set; } = false; 138 | 139 | 140 | /// 141 | /// Indicates that the box was dismissed without the user clicking any button 142 | /// (either by navigating to a URL or closing the window with the X.) 143 | /// 144 | public bool Dismissed { get; set; } = false; 145 | 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /MessageBoxEx/Classes/ResourceTextConfig.cs: -------------------------------------------------------------------------------- 1 | using DataTools.MessageBoxEx.Resources; 2 | 3 | using System; 4 | using System.Collections.Specialized; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Resources; 9 | using System.Text; 10 | using System.Windows.Forms; 11 | 12 | namespace DataTools.MessageBoxEx 13 | { 14 | /// 15 | /// Class to customize the localization of system message box types. 16 | /// 17 | /// This class is indexed by values mapped to resource keys. 18 | /// See the Indexer help page for more information. 19 | /// 20 | public class ResourceTextConfig 21 | { 22 | private CultureInfo ci = null; 23 | 24 | /// 25 | /// Gets the current Resource type name string. 26 | /// 27 | public string ResourceTypeName { get; private set; } 28 | 29 | internal NameValueCollection ResourceKeys { get; private set; } 30 | 31 | private ResourceManager ResMgr; 32 | 33 | public ResourceTextConfig() : this(typeof(AppResources).FullName, Assembly.GetAssembly(typeof(AppResources))) 34 | { 35 | } 36 | 37 | /// 38 | /// Create a new instance of 39 | /// 40 | /// The fully qualified type name of the resource class. 41 | /// The assembly that contains the resource class. 42 | /// CultureInfo to reference when rendering a string. 43 | public ResourceTextConfig(string resourceTypeName, Assembly assembly, CultureInfo cultureInfo = null) 44 | { 45 | ResourceTypeName = resourceTypeName; 46 | ResMgr = new ResourceManager(ResourceTypeName, assembly); 47 | ci = cultureInfo ?? Application.CurrentCulture; 48 | 49 | GenerateResourceKeys(); 50 | } 51 | 52 | /// 53 | /// Gets or sets the CultureInfo associated with this instance. 54 | /// 55 | public CultureInfo CultureInfo 56 | { 57 | get => ci; 58 | set => ci = value; 59 | } 60 | 61 | /// 62 | /// Gets or sets the resource key to use for the specified index. 63 | /// 64 | /// For localization, each member of has a 65 | /// default resource key associated with it. Use this indexer to set a different value. 66 | /// 67 | /// enumeration value 68 | /// A string representing a resource key 69 | public string this[MessageBoxExResult index] 70 | { 71 | get 72 | { 73 | string s = index.ToString(); 74 | return ResourceKeys[s]; 75 | } 76 | set 77 | { 78 | string s = index.ToString(); 79 | ResourceKeys[s] = value; 80 | } 81 | } 82 | 83 | private void GenerateResourceKeys() 84 | { 85 | NameValueCollection lOut = new NameValueCollection(); 86 | 87 | FieldInfo[] fields = typeof(MessageBoxExResult).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); 88 | 89 | foreach (var field in fields) 90 | { 91 | if (field.Name == "value__") continue; 92 | lOut.Add(field.Name, field.Name); 93 | } 94 | 95 | ResourceKeys = lOut; 96 | } 97 | 98 | /// 99 | /// Gets the localized resource text for the specified index. 100 | /// 101 | /// MessageBoxExResult enumeration value 102 | /// 103 | public string GetText(MessageBoxExResult index) 104 | { 105 | var s = index.ToString(); 106 | return ProvideValue(ResourceKeys[s]); 107 | } 108 | 109 | private string ProvideValue(string resourceKey) 110 | { 111 | if (resourceKey == null) 112 | return string.Empty; 113 | 114 | string translation = null; 115 | 116 | try 117 | { 118 | translation = ResMgr.GetString(resourceKey, ci); 119 | } 120 | catch 121 | { 122 | try 123 | { 124 | translation = ResMgr.GetString(resourceKey, new CultureInfo("en")); // default to English 125 | } 126 | catch 127 | { 128 | translation = "bad translation for " + resourceKey; 129 | } 130 | } 131 | 132 | if (translation == null) 133 | { 134 | ArgumentException ex = new ArgumentException( 135 | string.Format("Key '{0}' was not found in resources '{1}' for culture '{2}'.", resourceKey, ResourceTypeName, ci.Name), 136 | "Text"); 137 | #if DEBUG 138 | throw ex; 139 | #else 140 | try 141 | { 142 | translation = ResMgr.GetString(resourceKey, new CultureInfo("en")); // default to English 143 | } 144 | catch 145 | { 146 | translation = resourceKey; // HACK: returns the key, which GETS DISPLAYED TO THE USER 147 | } 148 | #endif 149 | } 150 | return translation; 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /MessageBoxEx/Enums/MessageBoxExIcons.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | 8 | namespace DataTools.MessageBoxEx 9 | { 10 | /// 11 | /// Icon Types. 12 | /// 13 | public enum MessageBoxExIcons 14 | { 15 | /// 16 | /// None 17 | /// 18 | None, 19 | 20 | /// 21 | /// Asterisk 22 | /// 23 | Asterisk, 24 | 25 | /// 26 | /// Error 27 | /// 28 | Error, 29 | 30 | /// 31 | /// Exclamation 32 | /// 33 | Exclamation, 34 | 35 | /// 36 | /// Hand 37 | /// 38 | Hand, 39 | 40 | /// 41 | /// Information 42 | /// 43 | Information, 44 | 45 | /// 46 | /// Question 47 | /// 48 | Question, 49 | 50 | /// 51 | /// Shield 52 | /// 53 | Shield, 54 | 55 | /// 56 | /// Warning 57 | /// 58 | Warning, 59 | 60 | /// 61 | /// User provides the icon. It will be sized to fit in the box. 62 | /// 63 | Custom = 0x100 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /MessageBoxEx/Enums/MessageBoxExResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | 8 | namespace DataTools.MessageBoxEx 9 | { 10 | 11 | /// 12 | /// Enumeration of results returned from a dialog box. 13 | /// Where possible, these values correspond directly to the equivalent values. 14 | /// 15 | public enum MessageBoxExResult 16 | { 17 | /// 18 | /// None 19 | /// 20 | None = DialogResult.None, 21 | /// 22 | /// OK 23 | /// 24 | OK = DialogResult.OK, 25 | 26 | /// 27 | /// Cancel 28 | /// 29 | Cancel = DialogResult.Cancel, 30 | 31 | /// 32 | /// Abort 33 | /// 34 | Abort = DialogResult.Abort, 35 | 36 | /// 37 | /// Retry 38 | /// 39 | Retry = DialogResult.Retry, 40 | 41 | /// 42 | /// Ignore 43 | /// 44 | Ignore = DialogResult.Ignore, 45 | 46 | /// 47 | /// Yes 48 | /// 49 | Yes = DialogResult.Yes, 50 | 51 | /// 52 | /// No 53 | /// 54 | No = DialogResult.No, 55 | 56 | /// 57 | /// All can be combined with any other flag (for future features) 58 | /// 59 | All = 0x80, 60 | 61 | /// 62 | /// Yes To All; a bitwise OR of Yes and All 63 | /// 64 | YesToAll = Yes | All, 65 | 66 | /// 67 | /// Custom result to be retrieved from the CustomResult parameter. 68 | /// 69 | Custom = 0x100 70 | 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /MessageBoxEx/Enums/MessageBoxExType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | 8 | namespace DataTools.MessageBoxEx 9 | { 10 | /// 11 | /// message box types (a collection of standard buttons.) 12 | /// Where possible, these values correspond directly to the equivalent values. 13 | /// 14 | public enum MessageBoxExType 15 | 16 | { 17 | /// 18 | /// OK button 19 | /// 20 | OK = MessageBoxButtons.OK, 21 | 22 | /// 23 | /// OK and Cancel buttons 24 | /// 25 | OKCancel = MessageBoxButtons.OKCancel, 26 | 27 | /// 28 | /// Abort, Retry, and Ignore buttons 29 | /// 30 | AbortRetryIgnore = MessageBoxButtons.AbortRetryIgnore, 31 | 32 | /// 33 | /// Yes, No, and Cancel buttons 34 | /// 35 | YesNoCancel = MessageBoxButtons.YesNoCancel, 36 | 37 | /// 38 | /// Yes and No buttons 39 | /// 40 | YesNo = MessageBoxButtons.YesNo, 41 | 42 | /// 43 | /// Abort, Retry, and Ignore buttons 44 | /// 45 | RetryCancel = MessageBoxButtons.RetryCancel, 46 | 47 | /// 48 | /// Yes, No, and Yes To All buttons 49 | /// 50 | YesNoAll, 51 | 52 | /// 53 | /// Yes, No, Yes To All, and Cancel buttons 54 | /// 55 | YesNoAllCancel, 56 | 57 | /// 58 | /// Custom buttons defined by the user 59 | /// 60 | Custom = 0x100 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /MessageBoxEx/Enums/OptionTextMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DataTools.MessageBoxEx 8 | { 9 | /// 10 | /// The modes to be used for the OptionTextMode parameter in MessageBoxExConfig. 11 | /// 12 | public enum OptionTextMode 13 | { 14 | /// 15 | /// Causes the option text to behave as a checkbox 16 | /// whose result will be available to the caller. 17 | /// 18 | Checkbox, 19 | 20 | /// 21 | /// Causes the option text to behave as a URL 22 | /// that will open when clicked. 23 | /// 24 | Url 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MessageBoxEx/Forms/DropDownPlacement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DataTools.MessageBoxEx 8 | { 9 | /// 10 | /// Specifies where the drop-down button goes. 11 | /// 12 | public enum DropDownPlacement 13 | { 14 | /// 15 | /// No drop-down menu. Items in the DropDownMenu list are ignored. 16 | /// 17 | None, 18 | 19 | /// 20 | /// There is a down-arrow button placed immediately to the left of the button that will act as the trigger for the drop-down menu. 21 | /// 22 | Left, 23 | 24 | /// 25 | /// There is a down-arrow button placed immediately to the right of the button that will act as the trigger for the drop-down menu. 26 | /// 27 | Right 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /MessageBoxEx/Forms/frmMsgBox.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace DataTools.MessageBoxEx 2 | { 3 | partial class frmMsgBox 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.lblMessage = new System.Windows.Forms.Label(); 32 | this.pbIcon = new System.Windows.Forms.PictureBox(); 33 | this.pnlButtons = new System.Windows.Forms.Panel(); 34 | ((System.ComponentModel.ISupportInitialize)(this.pbIcon)).BeginInit(); 35 | this.SuspendLayout(); 36 | 37 | // 38 | // frmMsgBox 39 | // 40 | this.ClientSize = new System.Drawing.Size(284, 261); 41 | this.Name = "frmMsgBox"; 42 | this.TopMost = true; 43 | // 44 | // lblMessage 45 | // 46 | this.lblMessage.AutoSize = true; 47 | this.lblMessage.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 48 | this.lblMessage.Location = new System.Drawing.Point(62, 28); 49 | this.lblMessage.Name = "lblMessage"; 50 | this.lblMessage.Size = new System.Drawing.Size(97, 13); 51 | this.lblMessage.TabIndex = 1; 52 | this.lblMessage.Text = "Example Message"; 53 | // 54 | // pbIcon 55 | // 56 | this.pbIcon.Location = new System.Drawing.Point(22, 19); 57 | this.pbIcon.Name = "pbIcon"; 58 | this.pbIcon.Size = new System.Drawing.Size(32, 32); 59 | this.pbIcon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; 60 | this.pbIcon.TabIndex = 3; 61 | this.pbIcon.TabStop = false; 62 | // 63 | // pnlButtons 64 | // 65 | this.pnlButtons.BackColor = System.Drawing.SystemColors.Control; 66 | this.pnlButtons.Dock = System.Windows.Forms.DockStyle.Bottom; 67 | this.pnlButtons.Location = new System.Drawing.Point(0, 77); 68 | this.pnlButtons.Name = "pnlButtons"; 69 | this.pnlButtons.Size = new System.Drawing.Size(416, 42); 70 | this.pnlButtons.TabIndex = 4; 71 | // 72 | // frmMsgBox 73 | // 74 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 75 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 76 | this.BackColor = System.Drawing.SystemColors.Window; 77 | this.ClientSize = new System.Drawing.Size(416, 119); 78 | this.Controls.Add(this.pnlButtons); 79 | this.Controls.Add(this.pbIcon); 80 | this.Controls.Add(this.lblMessage); 81 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 82 | this.MaximizeBox = false; 83 | this.MinimizeBox = false; 84 | this.Name = "frmMsgBox"; 85 | this.ShowIcon = false; 86 | this.ShowInTaskbar = false; 87 | this.Text = "Form1"; 88 | ((System.ComponentModel.ISupportInitialize)(this.pbIcon)).EndInit(); 89 | this.ResumeLayout(false); 90 | this.PerformLayout(); 91 | 92 | } 93 | 94 | #endregion 95 | private System.Windows.Forms.Label lblMessage; 96 | private System.Windows.Forms.PictureBox pbIcon; 97 | private System.Windows.Forms.Panel pnlButtons; 98 | } 99 | } -------------------------------------------------------------------------------- /MessageBoxEx/Forms/frmMsgBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace DataTools.MessageBoxEx 11 | { 12 | internal partial class frmMsgBox : Form 13 | { 14 | private readonly int MinDlgWidth = 117; 15 | 16 | private readonly int VerticalMargin = 15; 17 | 18 | private readonly int HorizonalMargin = 30; 19 | 20 | private readonly int RMarginLabelImage = 62; 21 | 22 | private readonly int RMarginImage = 22; 23 | 24 | private readonly int ButtonAreaHeight = 42; 25 | 26 | private readonly int ButtonSpacing = 8; 27 | 28 | private readonly int BaseHeight = 158; 29 | 30 | private readonly Size ButtonSize = new Size(76, 24); 31 | 32 | private CheckBox chkOption = new CheckBox(); 33 | 34 | private Label lblUrl = new Label(); 35 | 36 | private List buttons = new List(); 37 | 38 | private bool resultsSet = false; 39 | 40 | private bool urlClickClose = false; 41 | 42 | public bool Dismissed { get; private set; } 43 | 44 | public MessageBoxExResult Result { get; private set; } 45 | 46 | public object CustomResult { get; set; } 47 | 48 | public frmMsgBox() 49 | { 50 | InitializeComponent(); 51 | 52 | lblUrl.ForeColor = Color.Blue; 53 | lblUrl.Font = new Font(lblUrl.Font, FontStyle.Underline); 54 | lblUrl.Cursor = Cursors.Hand; 55 | lblUrl.Click += LblUrl_Click; 56 | 57 | // InitBrowser(); 58 | } 59 | 60 | private void LblUrl_Click(object sender, EventArgs e) 61 | { 62 | try 63 | { 64 | System.Diagnostics.Process.Start((string)lblUrl.Tag); 65 | } 66 | catch (Exception ex) 67 | { 68 | } 69 | 70 | if (urlClickClose) this.Close(); 71 | } 72 | 73 | private void ClearButtons() 74 | { 75 | pnlButtons.Controls.Clear(); 76 | 77 | foreach (var b in this.buttons) 78 | { 79 | if (b.Button != null) 80 | { 81 | b.Button.KeyDown -= Btn_KeyDown; 82 | b.Button.Click -= Btn_Click; 83 | b.Button.Dispose(); 84 | 85 | b.Button = null; 86 | b.Container = null; 87 | b.ContextMenu = null; 88 | } 89 | } 90 | 91 | this.buttons.Clear(); 92 | GC.Collect(0); 93 | } 94 | 95 | protected override void OnShown(EventArgs e) 96 | { 97 | resultsSet = false; 98 | 99 | foreach (var b in buttons) 100 | { 101 | if (b.IsDefault) 102 | { 103 | b.Button.Focus(); 104 | return; 105 | } 106 | } 107 | 108 | base.OnShown(e); 109 | } 110 | 111 | protected override void OnClosing(CancelEventArgs e) 112 | { 113 | if (!resultsSet) 114 | { 115 | Dismissed = true; 116 | 117 | foreach (var b in buttons) 118 | { 119 | if (b.IsDefault) 120 | { 121 | SetResult(b); 122 | break; 123 | } 124 | } 125 | 126 | // still not set? use the first one. 127 | if (!resultsSet) 128 | { 129 | SetResult(buttons[0]); 130 | } 131 | } 132 | else 133 | { 134 | Dismissed = false; 135 | } 136 | 137 | base.OnClosing(e); 138 | } 139 | 140 | public void SetButtons(IEnumerable buttons) 141 | { 142 | ClearButtons(); 143 | Size containerSize; 144 | 145 | foreach (var exBtn in buttons) 146 | { 147 | this.buttons.Add(exBtn); 148 | 149 | containerSize = ButtonSize; 150 | 151 | var container = new PictureBox() 152 | { 153 | Margin = new Padding(0), 154 | Padding = new Padding(0), 155 | BorderStyle = BorderStyle.None, 156 | BackColor = Color.Transparent, 157 | Tag = exBtn 158 | }; 159 | 160 | var btn = new Button() 161 | { 162 | Size = ButtonSize, 163 | Text = exBtn.Message, 164 | Padding = new Padding(0), 165 | Margin = new Padding(0), 166 | BackColor = SystemColors.Control, 167 | Visible = true, 168 | Left = 0, 169 | Top = 0, 170 | Tag = exBtn 171 | }; 172 | 173 | if (exBtn.Image != null) 174 | { 175 | btn.Image = ScaleBitmap(exBtn.Image, 16, 16); 176 | 177 | btn.ImageAlign = System.Drawing.ContentAlignment.TopCenter; 178 | btn.TextAlign = System.Drawing.ContentAlignment.TopCenter; 179 | btn.Width += 28; 180 | btn.Padding = new Padding(0); 181 | btn.TextImageRelation = TextImageRelation.ImageBeforeText; 182 | } 183 | 184 | exBtn.Button = btn; 185 | exBtn.Container = container; 186 | 187 | btn.Visible = true; 188 | btn.Enabled = true; 189 | btn.Click += Btn_Click; 190 | btn.KeyDown += Btn_KeyDown; 191 | 192 | container.Controls.Add(btn); 193 | 194 | if (exBtn.DropDownPlacement != DropDownPlacement.None && exBtn.DropDownMenuButtons?.Count > 0) 195 | { 196 | if (exBtn.DropDownPlacement == DropDownPlacement.Left) 197 | { 198 | btn.Left = 16; 199 | } 200 | 201 | containerSize.Width += 16; 202 | 203 | btn = new Button() 204 | { 205 | Text = "▼", 206 | Font = new Font(new FontFamily("Segoe UI"), 5.0F, FontStyle.Bold), 207 | BackColor = SystemColors.Control, 208 | Padding = new Padding(0), 209 | Margin = new Padding(0), 210 | Visible = true, 211 | Width = 16, 212 | Height = ButtonSize.Height, 213 | ContextMenuStrip = new ContextMenuStrip(), 214 | TabStop = false, 215 | Left = 0, 216 | Top = 0, 217 | Tag = exBtn 218 | }; 219 | 220 | if (exBtn.DropDownPlacement == DropDownPlacement.Right) 221 | { 222 | btn.Left = ButtonSize.Width; 223 | } 224 | 225 | btn.Visible = true; 226 | btn.Enabled = true; 227 | btn.Click += Btn_Click; 228 | 229 | container.Controls.Add(btn); 230 | 231 | exBtn.ContextMenu = btn.ContextMenuStrip; 232 | 233 | foreach (var subBtn in exBtn.DropDownMenuButtons) 234 | { 235 | this.buttons.Add(subBtn); 236 | 237 | var cm = new ToolStripMenuItem 238 | { 239 | Text = subBtn.Message, 240 | Visible = true, 241 | Tag = subBtn 242 | }; 243 | 244 | cm.Click += Btn_Click; 245 | btn.ContextMenuStrip.Items.Add(cm); 246 | 247 | if (subBtn.Image != null) 248 | { 249 | //cm.Im= ScaleBitmap(b.Image, 16, 16); 250 | 251 | //btn.ImageAlign = System.Drawing.ContentAlignment.TopCenter; 252 | //btn.TextAlign = System.Drawing.ContentAlignment.TopCenter; 253 | //btn.Width += 28; 254 | //btn.Padding = new Padding(0); 255 | //btn.TextImageRelation = TextImageRelation.ImageBeforeText; 256 | } 257 | } 258 | } 259 | 260 | container.Size = containerSize; 261 | pnlButtons.Controls.Add(container); 262 | } 263 | } 264 | 265 | private void Btn_KeyDown(object sender, KeyEventArgs e) 266 | { 267 | if (e.KeyCode == Keys.Down && e.Modifiers == Keys.Control) 268 | { 269 | if (sender is Button ctrl && ctrl.Tag is MessageBoxExButton b) 270 | { 271 | if (b.ContextMenu != null) 272 | { 273 | OpenButtonMenu(b); 274 | } 275 | } 276 | } 277 | if (e.KeyCode == Keys.Return && e.Modifiers == Keys.Control) 278 | { 279 | if (pnlButtons.Controls.Contains(lblUrl)) 280 | { 281 | this.LblUrl_Click(this, new EventArgs()); 282 | } 283 | e.SuppressKeyPress = true; 284 | } 285 | } 286 | 287 | private void OpenButtonMenu(MessageBoxExButton b) 288 | { 289 | if (b.Button is Button btnCtl) 290 | { 291 | if (b.DropDownPlacement == DropDownPlacement.Left) 292 | { 293 | b.ContextMenu.Show(btnCtl, new Point(0, btnCtl.Height)); 294 | } 295 | else if (b.DropDownPlacement == DropDownPlacement.Right) 296 | { 297 | b.ContextMenu.Show(btnCtl, new Point(btnCtl.Width, btnCtl.Height), ToolStripDropDownDirection.BelowLeft); 298 | } 299 | } 300 | } 301 | 302 | private void Btn_Click(object sender, EventArgs e) 303 | { 304 | if (sender is Button btnCtl && btnCtl.Tag is MessageBoxExButton b) 305 | { 306 | if (b.ContextMenu != null && btnCtl.ContextMenuStrip != null) 307 | { 308 | OpenButtonMenu(b); 309 | } 310 | else 311 | { 312 | SetResult(b); 313 | this.Close(); 314 | } 315 | } 316 | else if (sender is ToolStripMenuItem item && item.Tag is MessageBoxExButton b2) 317 | { 318 | SetResult(b2); 319 | this.Close(); 320 | } 321 | } 322 | 323 | private void SetResult(MessageBoxExButton result) 324 | { 325 | Result = result.Result; 326 | CustomResult = result.CustomResult; 327 | 328 | if (result.CustomResult == null) 329 | CustomResult = result.Result.ToString(); 330 | 331 | resultsSet = true; 332 | } 333 | 334 | public void SetMessage(string message) 335 | { 336 | lblMessage.Text = message; 337 | lblMessage.Visible = true; 338 | } 339 | 340 | public void SetIcon(Bitmap icon) 341 | { 342 | pbIcon.SizeMode = PictureBoxSizeMode.StretchImage; 343 | pbIcon.Visible = (icon != null); 344 | pbIcon.Image = icon; 345 | } 346 | 347 | public bool OptionResult 348 | { 349 | get => chkOption.Checked; 350 | set => chkOption.Checked = value; 351 | } 352 | 353 | public void SetOption(bool visible, string message = null) 354 | { 355 | if (visible) 356 | { 357 | SetUrl(false); 358 | chkOption.Text = message; 359 | pnlButtons.Controls.Add(chkOption); 360 | } 361 | else 362 | { 363 | chkOption.Text = ""; 364 | pnlButtons.Controls.Remove(chkOption); 365 | } 366 | } 367 | 368 | public void SetUrl(bool visible, string message = null, string url = null, bool urlClickDismiss = false) 369 | { 370 | if (visible) 371 | { 372 | SetOption(false); 373 | urlClickClose = urlClickDismiss; 374 | 375 | lblUrl.Text = message; 376 | lblUrl.Tag = url; 377 | 378 | pnlButtons.Controls.Add(lblUrl); 379 | } 380 | else 381 | { 382 | lblUrl.Text = ""; 383 | lblUrl.Tag = null; 384 | 385 | pnlButtons.Controls.Remove(lblUrl); 386 | } 387 | } 388 | 389 | internal void FormatBox() 390 | { 391 | int btnsTotal = 0; 392 | 393 | int lblStart; 394 | 395 | this.Height = BaseHeight; 396 | 397 | Control msgCtrl; 398 | 399 | msgCtrl = lblMessage; 400 | 401 | int ly = (this.Height / 2) - (msgCtrl.Height / 2) - ButtonAreaHeight; 402 | 403 | if (ly < 0) 404 | { 405 | this.Height += (-2 * ly) + (VerticalMargin * 2); 406 | ly = (this.Height / 2) - (msgCtrl.Height / 2) - ButtonAreaHeight; 407 | } 408 | 409 | int py = (this.Height / 2) - (pbIcon.Height / 2) - ButtonAreaHeight; 410 | int by = (21 - (ButtonSize.Height / 2)); 411 | int bx = 0; 412 | int msgTotal = 0; 413 | int bw; 414 | 415 | if (pbIcon.Image == null) 416 | { 417 | msgTotal += 60; 418 | lblStart = HorizonalMargin; 419 | } 420 | else 421 | { 422 | msgTotal += RMarginLabelImage + 15; 423 | lblStart = RMarginLabelImage; 424 | } 425 | 426 | msgTotal += msgCtrl.Width; 427 | msgCtrl.Left = lblStart; 428 | msgCtrl.Top = ly; 429 | 430 | pbIcon.Top = py; 431 | pbIcon.Left = RMarginImage; 432 | 433 | foreach (var b in buttons) 434 | { 435 | if (b.Container == null) continue; 436 | 437 | btnsTotal += b.Container.Width; 438 | b.Container.Top = by; 439 | } 440 | 441 | if (pnlButtons.Controls.Contains(chkOption)) 442 | { 443 | chkOption.AutoSize = true; 444 | 445 | btnsTotal += chkOption.Width + 32; 446 | 447 | chkOption.Left = 16; 448 | chkOption.Top = (21 - (chkOption.Height / 2)); 449 | 450 | chkOption.Visible = true; 451 | } 452 | else if (pnlButtons.Controls.Contains(lblUrl)) 453 | { 454 | lblUrl.AutoSize = true; 455 | 456 | btnsTotal += lblUrl.Width + 32; 457 | 458 | lblUrl.Left = 16; 459 | lblUrl.Top = (21 - (lblUrl.Height / 2)); 460 | 461 | lblUrl.Visible = true; 462 | } 463 | 464 | if (btnsTotal > msgTotal) 465 | bw = btnsTotal + 30; 466 | else 467 | bw = msgTotal + 30; 468 | 469 | if (bw < MinDlgWidth) 470 | bw = MinDlgWidth; 471 | 472 | this.Width = bw; 473 | 474 | bx = pnlButtons.Width; 475 | 476 | foreach (var b in buttons) 477 | { 478 | if (b.Container == null) continue; 479 | 480 | bx -= (b.Container.Width + ButtonSpacing); 481 | 482 | b.Container.Left = bx; 483 | b.Container.BringToFront(); 484 | b.Container.Visible = true; 485 | } 486 | } 487 | 488 | public Bitmap ScaleBitmap(Bitmap image, int cx, int cy) 489 | { 490 | var bmp = new Bitmap((int)cx, (int)cy); 491 | var graph = Graphics.FromImage(bmp); 492 | 493 | graph.InterpolationMode = InterpolationMode.High; 494 | graph.CompositingQuality = CompositingQuality.HighQuality; 495 | graph.SmoothingMode = SmoothingMode.AntiAlias; 496 | 497 | graph.DrawImage(image, 0, 0, cx, cy); 498 | 499 | graph.Dispose(); 500 | 501 | return bmp; 502 | } 503 | } 504 | } -------------------------------------------------------------------------------- /MessageBoxEx/Forms/frmMsgBox.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /MessageBoxEx/MessageBoxEx.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Library 4 | net6.0-windows;net7.0-windows;net472;net48;net481 5 | true 6 | 7 | 8 | DataTools.MessageBoxEx 9 | MessageBoxEx 10 | AnyCPU;x64 11 | 1.2.0.1011 12 | 1.2.0.1011 13 | Nathaniel Moschkin 14 | 1.2.0.1011 15 | DataTools.MessageBoxEx 16 | DataTools.MessageBoxEx 17 | Extended, customizable MessageBox with internationalization support. 18 | Copyright (C) 2023 Nathaniel Moschkin 19 | https://www.github.com/nmoschkin/MessageBoxEx 20 | GitHub 21 | en-US 22 | 1.2.0.1010 23 | C:\Keys\datatools.snk 24 | True 25 | True 26 | Apache-2.0 27 | DataTools.MessageBoxEx 28 | C:\Keys\datatools.snk 29 | True 30 | Debug;Release;NuGet 31 | Nathaniel Moschkin 32 | 33 | 34 | true 35 | 36 | 37 | true 38 | 39 | 40 | true 41 | 42 | 43 | true 44 | 45 | 46 | true 47 | 48 | 49 | true 50 | 51 | 52 | True 53 | 54 | 55 | True 56 | 57 | 58 | True 59 | 60 | 61 | True 62 | 63 | 64 | 65 | 66 | 67 | 68 | Form 69 | 70 | 71 | AppResources.resx 72 | True 73 | True 74 | 75 | 76 | 77 | 78 | AppResources.Designer.cs 79 | PublicResXFileCodeGenerator 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /MessageBoxEx/Resources/AppResources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace DataTools.MessageBoxEx.Resources { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public class AppResources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal AppResources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DataTools.MessageBoxEx.Resources.AppResources", typeof(AppResources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to &Abort. 65 | /// 66 | public static string Abort { 67 | get { 68 | return ResourceManager.GetString("Abort", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to &All. 74 | /// 75 | public static string All { 76 | get { 77 | return ResourceManager.GetString("All", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to &Cancel. 83 | /// 84 | public static string Cancel { 85 | get { 86 | return ResourceManager.GetString("Cancel", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to Custom Value. 92 | /// 93 | public static string Custom { 94 | get { 95 | return ResourceManager.GetString("Custom", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to &Ignore. 101 | /// 102 | public static string Ignore { 103 | get { 104 | return ResourceManager.GetString("Ignore", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Looks up a localized string similar to &No. 110 | /// 111 | public static string No { 112 | get { 113 | return ResourceManager.GetString("No", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized string similar to &OK. 119 | /// 120 | public static string OK { 121 | get { 122 | return ResourceManager.GetString("OK", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Looks up a localized string similar to &Retry. 128 | /// 129 | public static string Retry { 130 | get { 131 | return ResourceManager.GetString("Retry", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// Looks up a localized string similar to &Yes. 137 | /// 138 | public static string Yes { 139 | get { 140 | return ResourceManager.GetString("Yes", resourceCulture); 141 | } 142 | } 143 | 144 | /// 145 | /// Looks up a localized string similar to Yes To &All. 146 | /// 147 | public static string YesToAll { 148 | get { 149 | return ResourceManager.GetString("YesToAll", resourceCulture); 150 | } 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /MessageBoxEx/Resources/AppResources.fr-FR.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Avorter 122 | 123 | 124 | Tout 125 | 126 | 127 | Annuler 128 | 129 | 130 | Valeur personnalisée 131 | 132 | 133 | Ignorer 134 | 135 | 136 | Non 137 | 138 | 139 | D’ACCORD 140 | 141 | 142 | Réessayer 143 | 144 | 145 | Oui 146 | 147 | 148 | Oui à tous 149 | 150 | -------------------------------------------------------------------------------- /MessageBoxEx/Resources/AppResources.it-IT.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Abortire 122 | 123 | 124 | Tutto 125 | 126 | 127 | Annulla 128 | 129 | 130 | Valore personalizzato 131 | 132 | 133 | Ignorare 134 | 135 | 136 | No 137 | 138 | 139 | OK 140 | 141 | 142 | Ripetere 143 | 144 | 145 | 146 | 147 | 148 | Sì A Tutti 149 | 150 | -------------------------------------------------------------------------------- /MessageBoxEx/Resources/AppResources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | &Abort 122 | 123 | 124 | &All 125 | 126 | 127 | &Cancel 128 | 129 | 130 | Custom Value 131 | 132 | 133 | &Ignore 134 | 135 | 136 | &No 137 | 138 | 139 | &OK 140 | 141 | 142 | &Retry 143 | 144 | 145 | &Yes 146 | 147 | 148 | Yes To &All 149 | 150 | -------------------------------------------------------------------------------- /MsgExHelper/MsgExHelper.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | WinExe 4 | net6.0-windows;net7.0-windows;net472;net48;net481 5 | true 6 | DataTools.MessageBoxEx 7 | MsgExHelper 8 | Debug;Release;NuGet 9 | 1.2.0.1011 10 | 1.2.0.1011 11 | Nathaniel Moschkin 12 | 1.2.0.1011 13 | DataTools.MessageBoxEx.Helper 14 | DataTools.MessageBoxEx.Helper 15 | MessageBoxEx Out-of-process execution helper. 16 | Copyright (C) 2023 Nathaniel Moschkin 17 | https://www.github.com/nmoschkin/MessageBoxEx 18 | GitHub 19 | en-US 20 | 1.2.0.1010 21 | C:\Keys\datatools.snk 22 | True 23 | True 24 | Apache-2.0 25 | DataTools.MessageBoxEx.Helper 26 | 27 | 28 | True 29 | 30 | 31 | True 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /MsgExHelper/Program.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | using System; 4 | using System.Linq; 5 | 6 | // Uncomment to enable attach to debugger. 7 | // using System.Diagnostics; 8 | 9 | using System.Windows.Forms; 10 | 11 | namespace DataTools.MessageBoxEx 12 | { 13 | internal static class Program 14 | { 15 | /// 16 | /// The main entry point for the application. 17 | /// 18 | [STAThread] 19 | private static void Main(string[] args) 20 | { 21 | try 22 | { 23 | #if DEBUG 24 | // Uncomment to enable attach to debugger. 25 | // Debugger.Launch(); 26 | #endif 27 | MessageBoxExConfig config; 28 | bool vs = true; 29 | string json; 30 | 31 | int buffLen = 8192; 32 | char[] chars = new char[buffLen]; 33 | int ch; 34 | int c = 0; 35 | 36 | do 37 | { 38 | ch = Console.Read(); 39 | if (ch == -1) break; 40 | 41 | if (ch != 26) 42 | { 43 | chars[c] = (char)ch; 44 | c++; 45 | 46 | if (c >= buffLen) 47 | { 48 | buffLen *= 2; 49 | Array.Resize(ref chars, buffLen); 50 | } 51 | } 52 | else 53 | { 54 | ch = Console.Read(); 55 | vs = ((char)ch) == '1' ? true : false; 56 | 57 | break; 58 | } 59 | } while (ch != -1); 60 | 61 | // Array.Resize(ref chars, c); 62 | json = new string(chars); 63 | 64 | try 65 | { 66 | var settings = new JsonSerializerSettings(); 67 | 68 | settings.Error = new EventHandler(JsonError); 69 | settings.NullValueHandling = NullValueHandling.Ignore; 70 | 71 | config = JsonConvert.DeserializeObject(json, settings); 72 | } 73 | catch 74 | { 75 | Environment.ExitCode = 0x1000; 76 | Application.Exit(); 77 | return; 78 | } 79 | 80 | if (vs) 81 | { 82 | Application.EnableVisualStyles(); 83 | } 84 | Application.SetCompatibleTextRenderingDefault(false); 85 | 86 | json = null; 87 | 88 | var res = MessageBoxEx.Show(config); 89 | 90 | json = JsonConvert.SerializeObject(config); 91 | 92 | Console.Write(json); 93 | Environment.ExitCode = (int)res; 94 | Application.Exit(); 95 | } 96 | catch (Exception ex) 97 | { 98 | Console.Write(ex.Message); 99 | } 100 | } 101 | 102 | private static void JsonError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e) 103 | { 104 | var em = e; 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DataTools.MessageBoxEx # 2 | 3 | ## Version 1.2 ## 4 | 5 | __January 4th, 2023__ 6 | 7 | Eliminated redundant packages. All projects are now multi-target. 8 | 9 | The minimum .NET version is now .NET 6, and the minimum .NET Framework version is 4.8. 10 | 11 | NuGet packages are coming. 12 | 13 | ## Customizable replacement for the system **MessageBox** class ## 14 | 15 | DataTools.MessageBoxEx is a highly customizable replacement for the system MessageBox class for both WPF and WinForms applications. 16 | 17 | It is intended to look and behave as closely as possible to the native MessageBox. 18 | 19 | *(The message box will render in the [Visual Style](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.application.enablevisualstyles?view=netcore-3.1) of the calling application.)* 20 | 21 | #### [Go to the Wiki for complete API documentation.](https://github.com/ironywrit/MessageBoxEx/wiki) #### 22 | 23 | #### [DataTools.MessageBoxEx.MessageBoxEx Class](https://github.com/ironywrit/MessageBoxEx/wiki/T_DataTools_MessageBoxEx_MessageBoxEx) #### 24 | 25 | #### [DataTools.MessageBoxEx.MessageBoxExConfig Class](https://github.com/ironywrit/MessageBoxEx/wiki/T_DataTools_MessageBoxEx_MessageBoxExConfig) #### 26 | 27 | #### [Browse Form1.cs in the TestApp for usage examples.](https://github.com/ironywrit/MessageBoxEx/blob/master/TestApp/Form1.cs) #### 28 | 29 | ### Some features include: ### 30 | 31 | - **Custom Buttons** 32 | 33 | You can define completely custom buttons that return either a [**MessageBoxExResult**](https://github.com/ironywrit/MessageBoxEx/wiki/T_DataTools_MessageBoxEx_MessageBoxExResult) or a custom result of any type. 34 | 35 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot1.png) 36 | 37 | - **Custom Icons** 38 | 39 | The main icon and buttons icons are completely customizable: 40 | 41 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot6.png) 42 | 43 | - **Control Over Sounds** 44 | 45 | When the message box is shown it can: 46 | 47 | - Play the default system sound for a specific system icon. 48 | - Play a different system sound. 49 | - Mute sounds, altogether. 50 | 51 | - **Standard System Dialog Boxes** 52 | 53 | - OK button 54 | - OK and Cancel buttons 55 | - Yes and No buttons 56 | - Yes, No, and Cancel buttons 57 | - Yes, No, and Yes To All buttons 58 | - Abort, Retry, and Ignore buttons 59 | 60 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot4.png) 61 | 62 | - **Check Boxes** 63 | 64 | A checkbox option can be placed immediately to the left of the buttons on the message box. 65 | * (Note, a checkbox and a hyperlink cannot appear together, at the same time) 66 | 67 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot3.png) 68 | 69 | - **Hyper Links** 70 | 71 | A hyperlink that can execute any location that is valid in the Windows shell (applications, URLs, special folders, etc.) 72 | * Note: a checkbox and a hyperlink cannot appear together, at the same time. 73 | * In keyboard navigation, the hyperlink on the message box can be activated by pressing **Ctrl + Enter** 74 | 75 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot2.png) 76 | 77 | 78 | - **Drop-Down Menus** 79 | 80 | Custom buttons can have a drop-down menu with arrow button attached. 81 | * In keyboard navigation, the drop-down menu can be activated for the button with focus by pressing **Ctrl + Down Arrow** 82 | 83 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot5.png) 84 | 85 | - **Automatic Sizing** 86 | 87 | Gracefully and accurately sizes the dialog box to fit even very large content. 88 | * This feature is limited by screen size. 89 | 90 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot7.png) 91 | 92 | - **Resource-based Internationalization** 93 | 94 | Language resources from your own project can be referenced by MessageBoxEx to render standard dialog types by using the 95 | [ResourceTextConfig](https://github.com/ironywrit/MessageBoxEx/wiki/P_DataTools_MessageBoxEx_MessageBoxEx_ResourceTextConfig) static 96 | property. 97 | 98 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot9.png) 99 | 100 | * [See the example project for an example.](https://github.com/nmoschkin/MessageBoxEx/tree/master/TestApp) 101 | Note that the example project contains two resources, _AppResources.resx_ and _AppResources.fr.resx_. 102 | The _fr_ in the second file is the two letter ISO language code for French. Applications using resource-based internationalization 103 | will automatically pick the best set of resources to use based on the user's current system language and culture settings, but this 104 | behavior can be overridden. Browse [ResourceTextConfig.cs](https://github.com/nmoschkin/MessageBoxEx/blob/master/MessageBoxEx/Classes/ResourceTextConfig.cs) to see what's involved. 105 | 106 | - **If you prefer the old-fashioned 3D look** 107 | 108 | The message box will render in the [**Visual Style**](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.application.enablevisualstyles?view=netcore-3.1) of 109 | the calling application. 110 | 111 | **You can override the default visual style of your application by launching the message box in a new process using [ShowInNewProcess](https://github.com/ironywrit/MessageBoxEx/wiki/M_DataTools_MessageBoxEx_MessageBoxEx_ShowInNewProcess).** 112 | 113 | ![](https://raw.githubusercontent.com/ironywrit/MessageBoxEx/master/Screenshots/screenshot8.png) 114 | 115 | 116 | -------------------------------------------------------------------------------- /Screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot1.png -------------------------------------------------------------------------------- /Screenshots/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot2.png -------------------------------------------------------------------------------- /Screenshots/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot3.png -------------------------------------------------------------------------------- /Screenshots/screenshot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot4.png -------------------------------------------------------------------------------- /Screenshots/screenshot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot5.png -------------------------------------------------------------------------------- /Screenshots/screenshot6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot6.png -------------------------------------------------------------------------------- /Screenshots/screenshot7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot7.png -------------------------------------------------------------------------------- /Screenshots/screenshot8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot8.png -------------------------------------------------------------------------------- /Screenshots/screenshot9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/Screenshots/screenshot9.png -------------------------------------------------------------------------------- /TestApp/Form1.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace TestApp 2 | { 3 | partial class Form1 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.button1 = new System.Windows.Forms.Button(); 32 | this.button2 = new System.Windows.Forms.Button(); 33 | this.button3 = new System.Windows.Forms.Button(); 34 | this.button4 = new System.Windows.Forms.Button(); 35 | this.button5 = new System.Windows.Forms.Button(); 36 | this.button6 = new System.Windows.Forms.Button(); 37 | this.SuspendLayout(); 38 | // 39 | // button1 40 | // 41 | this.button1.Location = new System.Drawing.Point(12, 12); 42 | this.button1.Name = "button1"; 43 | this.button1.Size = new System.Drawing.Size(75, 23); 44 | this.button1.TabIndex = 0; 45 | this.button1.Text = "French"; 46 | this.button1.UseVisualStyleBackColor = true; 47 | this.button1.Click += new System.EventHandler(this.button1_Click); 48 | // 49 | // button2 50 | // 51 | this.button2.Location = new System.Drawing.Point(12, 65); 52 | this.button2.Name = "button2"; 53 | this.button2.Size = new System.Drawing.Size(75, 23); 54 | this.button2.TabIndex = 1; 55 | this.button2.Text = "&About"; 56 | this.button2.UseVisualStyleBackColor = true; 57 | this.button2.Click += new System.EventHandler(this.button2_Click); 58 | // 59 | // button3 60 | // 61 | this.button3.Location = new System.Drawing.Point(93, 65); 62 | this.button3.Name = "button3"; 63 | this.button3.Size = new System.Drawing.Size(75, 23); 64 | this.button3.TabIndex = 2; 65 | this.button3.Text = "External 2"; 66 | this.button3.UseVisualStyleBackColor = true; 67 | this.button3.Click += new System.EventHandler(this.button3_Click); 68 | // 69 | // button4 70 | // 71 | this.button4.Location = new System.Drawing.Point(93, 12); 72 | this.button4.Name = "button4"; 73 | this.button4.Size = new System.Drawing.Size(75, 23); 74 | this.button4.TabIndex = 3; 75 | this.button4.Text = "External 1"; 76 | this.button4.UseVisualStyleBackColor = true; 77 | this.button4.Click += new System.EventHandler(this.button4_Click); 78 | // 79 | // button5 80 | // 81 | this.button5.Location = new System.Drawing.Point(174, 12); 82 | this.button5.Name = "button5"; 83 | this.button5.Size = new System.Drawing.Size(75, 23); 84 | this.button5.TabIndex = 4; 85 | this.button5.Text = "Internal 1"; 86 | this.button5.UseVisualStyleBackColor = true; 87 | this.button5.Click += new System.EventHandler(this.button5_Click); 88 | // 89 | // button6 90 | // 91 | this.button6.Location = new System.Drawing.Point(174, 65); 92 | this.button6.Name = "button6"; 93 | this.button6.Size = new System.Drawing.Size(75, 23); 94 | this.button6.TabIndex = 5; 95 | this.button6.Text = "Internal 2"; 96 | this.button6.UseVisualStyleBackColor = true; 97 | this.button6.Click += new System.EventHandler(this.button6_Click); 98 | // 99 | // Form1 100 | // 101 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 102 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 103 | this.ClientSize = new System.Drawing.Size(262, 102); 104 | this.Controls.Add(this.button6); 105 | this.Controls.Add(this.button5); 106 | this.Controls.Add(this.button4); 107 | this.Controls.Add(this.button3); 108 | this.Controls.Add(this.button2); 109 | this.Controls.Add(this.button1); 110 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 111 | this.Name = "Form1"; 112 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 113 | this.Text = "Demo"; 114 | this.ResumeLayout(false); 115 | 116 | } 117 | 118 | #endregion 119 | 120 | private System.Windows.Forms.Button button1; 121 | private System.Windows.Forms.Button button2; 122 | private System.Windows.Forms.Button button3; 123 | private System.Windows.Forms.Button button4; 124 | private System.Windows.Forms.Button button5; 125 | private System.Windows.Forms.Button button6; 126 | } 127 | } 128 | 129 | -------------------------------------------------------------------------------- /TestApp/Form1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | using DataTools.MessageBoxEx; 12 | using TestApp.Resources; 13 | 14 | namespace TestApp 15 | { 16 | public partial class Form1 : Form 17 | { 18 | public Form1() 19 | { 20 | InitializeComponent(); 21 | } 22 | 23 | //private void button1_Click(object sender, EventArgs e) 24 | //{ 25 | // bool remind; 26 | 27 | // var res = MessageBoxEx.Show( 28 | // "An upgrade to this product is available.\r\nWould you like to upgrade, now?", 29 | // "Upgrade", 30 | // "Remind me, later.", 31 | // MessageBoxExType.YesNo, 32 | // MessageBoxExIcons.Information, out remind); 33 | 34 | 35 | // if (remind) 36 | // { 37 | // if (res == MessageBoxExResult.No) 38 | // MessageBoxEx.Show("You will be reminded, later."); 39 | 40 | // } 41 | // else 42 | // { 43 | // MessageBoxEx.Show("We won't bother you, again."); 44 | 45 | // } 46 | //} 47 | private void button1_Click(object sender, EventArgs e) 48 | { 49 | bool remind; 50 | 51 | MessageBoxEx.ResourceTextConfig = 52 | new ResourceTextConfig("TestApp.Resources.AppResources", 53 | Assembly.GetExecutingAssembly(), 54 | new System.Globalization.CultureInfo("fr")); 55 | 56 | 57 | var res = MessageBoxEx.Show( 58 | "Une mise à niveau de ce produit est disponible.\r\nSouhaitez-vous mettre à niveau maintenant?", 59 | "Faire mise a niveau", 60 | "Rappelle-moi plus tard.", 61 | MessageBoxExType.YesNo, 62 | MessageBoxExIcons.Information, 63 | out remind); 64 | 65 | MessageBoxEx.ResourceTextConfig = null; 66 | 67 | } 68 | 69 | private void button4_Click(object sender, EventArgs e) 70 | { 71 | var cfg = new MessageBoxExConfig() 72 | { 73 | Icon = MessageBoxExIcons.Custom, 74 | CustomIcon = AppResources.Nurse, 75 | OptionTextUrl = "https://outlook.live.com/calendar", 76 | OptionText = "Go To Your Calendar", 77 | Message = "There is an incoming message from you Doctor.", 78 | Title = "New Doctor's Alert", 79 | MessageBoxType = MessageBoxExType.OKCancel, 80 | OptionMode = OptionTextMode.Url, 81 | UrlClickDismiss = true 82 | }; 83 | 84 | var res = MessageBoxEx.ShowInNewProcess(cfg, false); 85 | 86 | } 87 | 88 | private void button3_Click(object sender, EventArgs e) 89 | { 90 | var cfg = new MessageBoxExConfig() 91 | { 92 | Icon = MessageBoxExIcons.Custom, 93 | CustomIcon = AppResources.Tractor, 94 | OptionText = "I work for a subsidiary.", 95 | Title = "Confirm Industry Program", 96 | Message = "Choose your company's default program.", 97 | OptionMode = OptionTextMode.Checkbox 98 | }; 99 | 100 | cfg.CustomButtons.Add(new MessageBoxExButton("&Livestock", "Livestock", false)); 101 | cfg.CustomButtons.Add(new MessageBoxExButton("&Agriculture", "Agriculture", false)); 102 | cfg.CustomButtons.Add(new MessageBoxExButton("&Textiles", "Textiles", false)); 103 | 104 | var button = cfg.CustomButtons[0]; 105 | 106 | button.DropDownMenuButtons.Add(new MessageBoxExButton("&Cattle", "Cattle")); 107 | button.DropDownMenuButtons.Add(new MessageBoxExButton("Por&k", "Pork")); 108 | button.DropDownMenuButtons.Add(new MessageBoxExButton("&Poultry", "Poultry")); 109 | button.DropDownMenuButtons.Add(new MessageBoxExButton("&Husbandry / Other", "Husbandry / Other")); 110 | button.DropDownPlacement = DropDownPlacement.Right; 111 | 112 | var res = MessageBoxEx.ShowInNewProcess(cfg, false); 113 | // var res = MessageBoxEx.Show(cfg); 114 | 115 | 116 | string s; 117 | 118 | 119 | if (cfg.Dismissed) 120 | { 121 | s = "You dismissed the window without making a selection.\r\nTry again, later."; 122 | } 123 | else 124 | { 125 | s = "We have recorded your company's program as '" + (string)cfg.CustomResult + "'"; 126 | 127 | if (cfg.OptionResult) 128 | { 129 | s += "\r\nWe have recorded that you work for a subsidiary."; 130 | } 131 | else 132 | { 133 | s += "\r\nWe have recorded that you do not work for a subsidiary."; 134 | } 135 | 136 | } 137 | 138 | MessageBoxEx.Show(s, "Details Recorded", MessageBoxExType.OK, MessageBoxExIcons.Information); 139 | } 140 | 141 | private void button2_Click(object sender, EventArgs e) 142 | { 143 | var sb = new StringBuilder(); 144 | 145 | sb.AppendLine("DataTools.MessageBoxEx supports a number of features:"); 146 | sb.AppendLine(""); 147 | sb.AppendLine("* Custom Buttons"); 148 | sb.AppendLine("* Custom Icons"); 149 | sb.AppendLine(""); 150 | sb.AppendLine("* Control Over Sounds"); 151 | sb.AppendLine(""); 152 | sb.AppendLine("* Standard System Dialog Boxes"); 153 | sb.AppendLine(""); 154 | sb.AppendLine("* Check Boxes"); 155 | sb.AppendLine("* Hyper Links"); 156 | sb.AppendLine(""); 157 | sb.AppendLine("* Drop Down Menus"); 158 | sb.AppendLine(""); 159 | sb.AppendLine("* Accommodation for Messages of large height, and width. (Although, we trust people to try to be brief as possible.)"); 160 | sb.AppendLine(""); 161 | sb.AppendLine("Copyright (C) Nathaniel Moschkin. Licensed under the MIT license."); 162 | 163 | var cfg = new MessageBoxExConfig() 164 | { 165 | Icon = MessageBoxExIcons.Information, 166 | OptionText = "Click here to go to the MessageBoxEx GitHub!", 167 | OptionTextUrl = "https://github.com/ironywrit/MessageBoxEx", 168 | Title = "About DataTools.MessageBoxEx", 169 | Message = sb.ToString(), 170 | UrlClickDismiss = true, 171 | OptionMode = OptionTextMode.Url 172 | }; 173 | 174 | MessageBoxEx.Show(cfg); 175 | 176 | } 177 | 178 | private void button5_Click(object sender, EventArgs e) 179 | { 180 | var cfg = new MessageBoxExConfig() 181 | { 182 | Icon = MessageBoxExIcons.Custom, 183 | CustomIcon = AppResources.Nurse, 184 | OptionTextUrl = "https://outlook.live.com/calendar", 185 | OptionText = "Go To Your Calendar", 186 | Message = "There is an incoming message from you Doctor.", 187 | Title = "New Doctor's Alert", 188 | MessageBoxType = MessageBoxExType.OKCancel, 189 | OptionMode = OptionTextMode.Url, 190 | UrlClickDismiss = true 191 | }; 192 | 193 | var res = MessageBoxEx.Show(cfg); 194 | 195 | 196 | } 197 | 198 | private void button6_Click(object sender, EventArgs e) 199 | { 200 | var cfg = new MessageBoxExConfig() 201 | { 202 | Icon = MessageBoxExIcons.Custom, 203 | CustomIcon = AppResources.Tractor, 204 | OptionText = "I work for a subsidiary.", 205 | Title = "Confirm Industry Program", 206 | Message = "Choose your company's default program.", 207 | OptionMode = OptionTextMode.Checkbox 208 | }; 209 | 210 | cfg.CustomButtons.Add(new MessageBoxExButton("&Livestock", "Livestock", false)); 211 | cfg.CustomButtons.Add(new MessageBoxExButton("&Agriculture", "Agriculture", false)); 212 | cfg.CustomButtons.Add(new MessageBoxExButton("&Textiles", "Textiles", false)); 213 | 214 | var button = cfg.CustomButtons[0]; 215 | 216 | button.DropDownMenuButtons.Add(new MessageBoxExButton("&Cattle", "Cattle")); 217 | button.DropDownMenuButtons.Add(new MessageBoxExButton("Por&k", "Pork")); 218 | button.DropDownMenuButtons.Add(new MessageBoxExButton("&Poultry", "Poultry")); 219 | button.DropDownMenuButtons.Add(new MessageBoxExButton("&Husbandry / Other", "Husbandry / Other")); 220 | button.DropDownPlacement = DropDownPlacement.Right; 221 | 222 | var res = MessageBoxEx.Show(cfg); 223 | // var res = MessageBoxEx.Show(cfg); 224 | 225 | 226 | string s; 227 | 228 | 229 | if (cfg.Dismissed) 230 | { 231 | s = "You dismissed the window without making a selection.\r\nTry again, later."; 232 | } 233 | else 234 | { 235 | s = "We have recorded your company's program as '" + (string)cfg.CustomResult + "'"; 236 | 237 | if (cfg.OptionResult) 238 | { 239 | s += "\r\nWe have recorded that you work for a subsidiary."; 240 | } 241 | else 242 | { 243 | s += "\r\nWe have recorded that you do not work for a subsidiary."; 244 | } 245 | 246 | } 247 | 248 | MessageBoxEx.Show(s, "Details Recorded", MessageBoxExType.OK, MessageBoxExIcons.Information); 249 | } 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /TestApp/Form1.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /TestApp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | using DataTools.MessageBoxEx; 7 | 8 | namespace TestApp 9 | { 10 | static class Program 11 | { 12 | /// 13 | /// The main entry point for the application. 14 | /// 15 | [STAThread] 16 | static void Main(string[] args) 17 | { 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | 20 | //bool vs = false; 21 | 22 | //if (args.Length > 0) 23 | //{ 24 | // foreach (string arg in args) 25 | // { 26 | // if (arg.ToLower() == "/vs") 27 | // { 28 | // vs = true; 29 | 30 | // } 31 | // } 32 | //} 33 | 34 | //if (!vs) 35 | //{ 36 | // var res = MessageBoxEx.Show("Enable Visual Styles?", "Visual Styles", MessageBoxExType.YesNo, MessageBoxExIcons.Question); 37 | 38 | // if (res == MessageBoxExResult.Yes) 39 | // { 40 | // System.Diagnostics.Process.Start(Application.ExecutablePath, "/vs"); 41 | // Application.Exit(); 42 | 43 | // return; 44 | // } 45 | //} 46 | 47 | //if (vs) 48 | 49 | Application.EnableVisualStyles(); 50 | Application.Run(new Form1()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /TestApp/Resources/AppResources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TestApp.Resources { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class AppResources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal AppResources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TestApp.Resources.AppResources", typeof(AppResources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to &Abort. 65 | /// 66 | internal static string Abort { 67 | get { 68 | return ResourceManager.GetString("Abort", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to &All. 74 | /// 75 | internal static string All { 76 | get { 77 | return ResourceManager.GetString("All", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to &Cancel. 83 | /// 84 | internal static string Cancel { 85 | get { 86 | return ResourceManager.GetString("Cancel", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to Custom Value. 92 | /// 93 | internal static string Custom { 94 | get { 95 | return ResourceManager.GetString("Custom", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to &Ignore. 101 | /// 102 | internal static string Ignore { 103 | get { 104 | return ResourceManager.GetString("Ignore", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Looks up a localized string similar to &No. 110 | /// 111 | internal static string No { 112 | get { 113 | return ResourceManager.GetString("No", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized resource of type System.Drawing.Bitmap. 119 | /// 120 | internal static System.Drawing.Bitmap Nurse { 121 | get { 122 | object obj = ResourceManager.GetObject("Nurse", resourceCulture); 123 | return ((System.Drawing.Bitmap)(obj)); 124 | } 125 | } 126 | 127 | /// 128 | /// Looks up a localized string similar to &OK. 129 | /// 130 | internal static string OK { 131 | get { 132 | return ResourceManager.GetString("OK", resourceCulture); 133 | } 134 | } 135 | 136 | /// 137 | /// Looks up a localized string similar to &Retry. 138 | /// 139 | internal static string Retry { 140 | get { 141 | return ResourceManager.GetString("Retry", resourceCulture); 142 | } 143 | } 144 | 145 | /// 146 | /// Looks up a localized resource of type System.Drawing.Bitmap. 147 | /// 148 | internal static System.Drawing.Bitmap Tractor { 149 | get { 150 | object obj = ResourceManager.GetObject("Tractor", resourceCulture); 151 | return ((System.Drawing.Bitmap)(obj)); 152 | } 153 | } 154 | 155 | /// 156 | /// Looks up a localized string similar to &Yes. 157 | /// 158 | internal static string Yes { 159 | get { 160 | return ResourceManager.GetString("Yes", resourceCulture); 161 | } 162 | } 163 | 164 | /// 165 | /// Looks up a localized string similar to Yes To &All. 166 | /// 167 | internal static string YesToAll { 168 | get { 169 | return ResourceManager.GetString("YesToAll", resourceCulture); 170 | } 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /TestApp/Resources/AppResources.fr.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | &Avorter 122 | 123 | 124 | &Tout 125 | 126 | 127 | &Annuler 128 | 129 | 130 | Valeur Personnalisée 131 | 132 | 133 | &Ignorer 134 | 135 | 136 | &Non 137 | 138 | 139 | &Valider 140 | 141 | 142 | &Recommencer 143 | 144 | 145 | &Oui 146 | 147 | 148 | Oui à &Tout 149 | 150 | -------------------------------------------------------------------------------- /TestApp/Resources/AppResources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | &Abort 122 | 123 | 124 | &All 125 | 126 | 127 | &Cancel 128 | 129 | 130 | Custom Value 131 | 132 | 133 | &Ignore 134 | 135 | 136 | &No 137 | 138 | 139 | 140 | Medical-Nurse-Male-Light-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 141 | 142 | 143 | &OK 144 | 145 | 146 | &Retry 147 | 148 | 149 | icons8-color-50.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 150 | 151 | 152 | &Yes 153 | 154 | 155 | Yes To &All 156 | 157 | -------------------------------------------------------------------------------- /TestApp/Resources/Medical-Nurse-Male-Light-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/TestApp/Resources/Medical-Nurse-Male-Light-icon.png -------------------------------------------------------------------------------- /TestApp/Resources/icons8-color-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nmoschkin/MessageBoxEx/591ee5ecc8d38ffa3d5d48bde480b405264d7ec7/TestApp/Resources/icons8-color-50.png -------------------------------------------------------------------------------- /TestApp/TestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | WinExe 4 | net6.0-windows;net7.0-windows;net472;net48;net481 5 | true 6 | TestApp 7 | TestApp 8 | Debug;Release;NuGet 9 | 1.2.0.1011 10 | 1.2.0.1011 11 | 1.2.0.1010 12 | 1.2.0.1011 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Form1.cs 22 | 23 | 24 | AppResources.resx 25 | True 26 | True 27 | 28 | 29 | 30 | 31 | Form1.cs 32 | 33 | 34 | Designer 35 | AppResources.Designer.cs 36 | ResXFileCodeGenerator 37 | 38 | 39 | --------------------------------------------------------------------------------